Processing math: 0%
 deal.II version GIT relicensing-2968-g5f01c80b02 2025-03-29 13:10:00+00:00
\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}} \newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=} \newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]} \newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
tria.cc
Go to the documentation of this file.
1// ------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: LGPL-2.1-or-later
4// Copyright (C) 1999 - 2024 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Part of the source code is dual licensed under Apache-2.0 WITH
9// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
10// governing the source code and code contributions can be found in
11// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
12//
13// ------------------------------------------------------------------------
14
15
18#include <deal.II/base/mpi.templates.h>
23
26
31#include <deal.II/grid/tria.h>
37
38#include <boost/archive/text_iarchive.hpp>
39#include <boost/archive/text_oarchive.hpp>
40
41#include <algorithm>
42#include <array>
43#include <cmath>
44#include <cstdint>
45#include <fstream>
46#include <functional>
47#include <limits>
48#include <list>
49#include <map>
50#include <memory>
51#include <numeric>
52
53
55
56
57namespace internal
58{
59 namespace TriangulationImplementation
60 {
62 : n_levels(0)
63 , n_lines(0)
64 , n_active_lines(0)
65 // all other fields are
66 // default constructed
67 {}
68
69
70
71 std::size_t
73 {
74 std::size_t mem =
79 MemoryConsumption::memory_consumption(n_active_lines_level);
80
81 if (active_cell_index_partitioner)
82 mem += active_cell_index_partitioner->memory_consumption();
83
84 for (const auto &partitioner : level_cell_index_partitioners)
85 if (partitioner)
86 mem += partitioner->memory_consumption();
87
88 return mem;
89 }
90
91
93 : n_quads(0)
94 , n_active_quads(0)
95 // all other fields are
96 // default constructed
97 {}
98
99
100
101 std::size_t
110
111
112
114 : n_hexes(0)
115 , n_active_hexes(0)
116 // all other fields are
117 // default constructed
118 {}
119
120
121
122 std::size_t
131 } // namespace TriangulationImplementation
132
133
134 template <int dim, int spacedim>
137 : variable_size_data_stored(false)
138 {}
139
140
141 template <int dim, int spacedim>
143 void CellAttachedDataSerializer<dim, spacedim>::pack_data(
144 const std::vector<cell_relation_t> &cell_relations,
145 const std::vector<
146 typename internal::CellAttachedData<dim, spacedim>::pack_callback_t>
147 &pack_callbacks_fixed,
148 const std::vector<
149 typename internal::CellAttachedData<dim, spacedim>::pack_callback_t>
150 &pack_callbacks_variable,
151 const MPI_Comm &mpi_communicator)
152 {
153 Assert(src_data_fixed.empty(),
154 ExcMessage("Previously packed data has not been released yet!"));
155 Assert(src_sizes_variable.empty(), ExcInternalError());
156
157 const unsigned int n_callbacks_fixed = pack_callbacks_fixed.size();
158 const unsigned int n_callbacks_variable = pack_callbacks_variable.size();
159
160 // Store information that we packed variable size data in
161 // a member variable for later.
162 variable_size_data_stored = (n_callbacks_variable > 0);
163
164 // If variable transfer is scheduled, we will store the data size that
165 // each variable size callback function writes in this auxiliary
166 // container. The information will be stored by each cell in this vector
167 // temporarily.
168 std::vector<unsigned int> cell_sizes_variable_cumulative(
169 n_callbacks_variable);
170
171 // Prepare the buffer structure, in which each callback function will
172 // store its data for each active cell.
173 // The outmost shell in this container construct corresponds to the
174 // data packed per cell. The next layer resembles the data that
175 // each callback function packs on the corresponding cell. These
176 // buffers are chains of chars stored in an std::vector<char>.
177 // A visualisation of the data structure:
178 /* clang-format off */
179 // | cell_1 | | cell_2 | ...
180 // || callback_1 || callback_2 |...| || callback_1 || callback_2 |...| ...
181 // |||char|char|...|||char|char|...|...| |||char|char|...|||char|char|...|...| ...
182 /* clang-format on */
183 std::vector<std::vector<std::vector<char>>> packed_fixed_size_data(
184 cell_relations.size());
185 std::vector<std::vector<std::vector<char>>> packed_variable_size_data(
186 variable_size_data_stored ? cell_relations.size() : 0);
187
188 //
189 // --------- Pack data for fixed and variable size transfer ---------
190 //
191 // Iterate over all cells, call all callback functions on each cell,
192 // and store their data in the corresponding buffer scope.
193 {
194 auto cell_rel_it = cell_relations.cbegin();
195 auto data_cell_fixed_it = packed_fixed_size_data.begin();
196 auto data_cell_variable_it = packed_variable_size_data.begin();
197 for (; cell_rel_it != cell_relations.cend(); ++cell_rel_it)
198 {
199 const auto &dealii_cell = cell_rel_it->first;
200 const auto &cell_status = cell_rel_it->second;
201
202 // Assertions about the tree structure.
203 switch (cell_status)
204 {
207 // double check the condition that we will only ever attach
208 // data to active cells when we get here
209 Assert(dealii_cell->is_active(), ExcInternalError());
210 break;
211
213 // double check the condition that we will only ever attach
214 // data to cells with children when we get here. however, we
215 // can only tolerate one level of coarsening at a time, so
216 // check that the children are all active
217 Assert(dealii_cell->is_active() == false, ExcInternalError());
218 for (unsigned int c = 0; c < dealii_cell->n_children(); ++c)
219 Assert(dealii_cell->child(c)->is_active(),
221 break;
222
224 // do nothing on invalid cells
225 break;
226
227 default:
229 break;
230 }
231
232 // Reserve memory corresponding to the number of callback
233 // functions that will be called.
234 // If variable size transfer is scheduled, we need to leave
235 // room for an array that holds information about how many
236 // bytes each of the variable size callback functions will
237 // write.
238 // On cells flagged with CellStatus::cell_invalid, only its CellStatus
239 // will be stored.
240 const unsigned int n_fixed_size_data_sets_on_cell =
241 1 + ((cell_status == CellStatus::cell_invalid) ?
242 0 :
243 ((variable_size_data_stored ? 1 : 0) + n_callbacks_fixed));
244 data_cell_fixed_it->resize(n_fixed_size_data_sets_on_cell);
245
246 // We continue with packing all data on this specific cell.
247 auto data_fixed_it = data_cell_fixed_it->begin();
248
249 // First, we pack the CellStatus information.
250 // to get consistent data sizes on each cell for the fixed size
251 // transfer, we won't allow compression
252 *data_fixed_it =
253 Utilities::pack(cell_status, /*allow_compression=*/false);
254 ++data_fixed_it;
255
256 // Proceed with all registered callback functions.
257 // Skip cells with the CellStatus::cell_invalid flag.
258 if (cell_status != CellStatus::cell_invalid)
259 {
260 // Pack fixed size data.
261 for (auto callback_it = pack_callbacks_fixed.cbegin();
262 callback_it != pack_callbacks_fixed.cend();
263 ++callback_it, ++data_fixed_it)
264 {
265 *data_fixed_it = (*callback_it)(dealii_cell, cell_status);
266 }
267
268 // Pack variable size data.
269 // If we store variable size data, we need to transfer
270 // the sizes of each corresponding callback function
271 // via fixed size transfer as well.
272 if (variable_size_data_stored)
273 {
274 const unsigned int n_variable_size_data_sets_on_cell =
275 ((cell_status == CellStatus::cell_invalid) ?
276 0 :
277 n_callbacks_variable);
278 data_cell_variable_it->resize(
279 n_variable_size_data_sets_on_cell);
280
281 auto callback_it = pack_callbacks_variable.cbegin();
282 auto data_variable_it = data_cell_variable_it->begin();
283 auto sizes_variable_it =
284 cell_sizes_variable_cumulative.begin();
285 for (; callback_it != pack_callbacks_variable.cend();
286 ++callback_it, ++data_variable_it, ++sizes_variable_it)
287 {
288 *data_variable_it =
289 (*callback_it)(dealii_cell, cell_status);
290
291 // Store data sizes for each callback function first.
292 // Make it cumulative below.
293 *sizes_variable_it = data_variable_it->size();
294 }
295
296 // Turn size vector into its cumulative representation.
297 std::partial_sum(cell_sizes_variable_cumulative.begin(),
298 cell_sizes_variable_cumulative.end(),
299 cell_sizes_variable_cumulative.begin());
300
301 // Serialize cumulative variable size vector
302 // value-by-value. This way we can circumvent the overhead
303 // of storing the container object as a whole, since we
304 // know its size by the number of registered callback
305 // functions.
306 data_fixed_it->resize(n_callbacks_variable *
307 sizeof(unsigned int));
308 for (unsigned int i = 0; i < n_callbacks_variable; ++i)
309 std::memcpy(&(data_fixed_it->at(i * sizeof(unsigned int))),
310 &(cell_sizes_variable_cumulative.at(i)),
311 sizeof(unsigned int));
312
313 ++data_fixed_it;
314 }
315
316 // Double check that we packed everything we wanted
317 // in the fixed size buffers.
318 Assert(data_fixed_it == data_cell_fixed_it->end(),
320 }
321
322 ++data_cell_fixed_it;
323
324 // Increment the variable size data iterator
325 // only if we actually pack this kind of data
326 // to avoid getting out of bounds.
327 if (variable_size_data_stored)
328 ++data_cell_variable_it;
329 } // loop over cell_relations
330 }
331
332 //
333 // ----------- Gather data sizes for fixed size transfer ------------
334 //
335 // Generate a vector which stores the sizes of each callback function,
336 // including the packed CellStatus transfer.
337 // Find the very first cell that we wrote to with all callback
338 // functions (i.e. a cell that was not flagged with
339 // CellStatus::cell_invalid) and store the sizes of each buffer.
340 //
341 // To deal with the case that at least one of the processors does not
342 // own any cell at all, we will exchange the information about the data
343 // sizes among them later. The code in between is still well-defined,
344 // since the following loops will be skipped.
345 std::vector<unsigned int> local_sizes_fixed(
346 1 + n_callbacks_fixed + (variable_size_data_stored ? 1 : 0));
347 for (const auto &data_cell : packed_fixed_size_data)
348 {
349 if (data_cell.size() == local_sizes_fixed.size())
350 {
351 auto sizes_fixed_it = local_sizes_fixed.begin();
352 auto data_fixed_it = data_cell.cbegin();
353 for (; data_fixed_it != data_cell.cend();
354 ++data_fixed_it, ++sizes_fixed_it)
355 {
356 *sizes_fixed_it = data_fixed_it->size();
357 }
358
359 break;
360 }
361 }
362
363 // Check if all cells have valid sizes.
364 for (auto data_cell_fixed_it = packed_fixed_size_data.cbegin();
365 data_cell_fixed_it != packed_fixed_size_data.cend();
366 ++data_cell_fixed_it)
367 {
368 Assert((data_cell_fixed_it->size() == 1) ||
369 (data_cell_fixed_it->size() == local_sizes_fixed.size()),
371 }
372
373 // Share information about the packed data sizes
374 // of all callback functions across all processors, in case one
375 // of them does not own any cells at all.
376 std::vector<unsigned int> global_sizes_fixed(local_sizes_fixed.size());
377 Utilities::MPI::max(local_sizes_fixed,
378 mpi_communicator,
379 global_sizes_fixed);
380
381 // Construct cumulative sizes, since this is the only information
382 // we need from now on.
383 sizes_fixed_cumulative.resize(global_sizes_fixed.size());
384 std::partial_sum(global_sizes_fixed.begin(),
385 global_sizes_fixed.end(),
386 sizes_fixed_cumulative.begin());
387
388 //
389 // ---------- Gather data sizes for variable size transfer ----------
390 //
391 if (variable_size_data_stored)
392 {
393 src_sizes_variable.reserve(packed_variable_size_data.size());
394 for (const auto &data_cell : packed_variable_size_data)
395 {
396 int variable_data_size_on_cell = 0;
397
398 for (const auto &data : data_cell)
399 variable_data_size_on_cell += data.size();
400
401 src_sizes_variable.push_back(variable_data_size_on_cell);
402 }
403 }
404
405 //
406 // ------------------------ Build buffers ---------------------------
407 //
408 const unsigned int expected_size_fixed =
409 cell_relations.size() * sizes_fixed_cumulative.back();
410 const unsigned int expected_size_variable =
411 std::accumulate(src_sizes_variable.begin(),
412 src_sizes_variable.end(),
413 std::vector<int>::size_type(0));
414
415 // Move every piece of packed fixed size data into the consecutive
416 // buffer.
417 src_data_fixed.reserve(expected_size_fixed);
418 for (const auto &data_cell_fixed : packed_fixed_size_data)
419 {
420 // Move every fraction of packed data into the buffer
421 // reserved for this particular cell.
422 for (const auto &data_fixed : data_cell_fixed)
423 std::move(data_fixed.begin(),
424 data_fixed.end(),
425 std::back_inserter(src_data_fixed));
426
427 // If we only packed the CellStatus information
428 // (i.e. encountered a cell flagged CellStatus::cell_invalid),
429 // fill the remaining space with invalid entries.
430 // We can skip this if there is nothing else to pack.
431 if ((data_cell_fixed.size() == 1) &&
432 (sizes_fixed_cumulative.size() > 1))
433 {
434 const std::size_t bytes_skipped =
435 sizes_fixed_cumulative.back() - sizes_fixed_cumulative.front();
436
437 src_data_fixed.insert(src_data_fixed.end(),
438 bytes_skipped,
439 static_cast<char>(-1)); // invalid_char
441 }
442
443 // Move every piece of packed variable size data into the consecutive
444 // buffer.
445 if (variable_size_data_stored)
446 {
447 src_data_variable.reserve(expected_size_variable);
448 for (const auto &data_cell : packed_variable_size_data)
449 {
450 // Move every fraction of packed data into the buffer
451 // reserved for this particular cell.
452 for (const auto &data : data_cell)
453 std::move(data.begin(),
454 data.end(),
455 std::back_inserter(src_data_variable));
456 }
457 }
458
459 // Double check that we packed everything correctly.
460 Assert(src_data_fixed.size() == expected_size_fixed, ExcInternalError());
461 Assert(src_data_variable.size() == expected_size_variable,
463 }
465
466
467 template <int dim, int spacedim>
469 void CellAttachedDataSerializer<dim, spacedim>::unpack_cell_status(
470 std::vector<
471 typename CellAttachedDataSerializer<dim, spacedim>::cell_relation_t>
472 &cell_relations) const
473 {
474 Assert(sizes_fixed_cumulative.size() > 0,
475 ExcMessage("No data has been packed!"));
476 if (cell_relations.size() > 0)
477 {
478 Assert(dest_data_fixed.size() > 0,
479 ExcMessage("No data has been received!"));
480 }
481
482 // Size of CellStatus object that will be unpacked on each cell.
483 const unsigned int size = sizes_fixed_cumulative.front();
484
485 // Iterate over all cells and overwrite the CellStatus
486 // information from the transferred data.
487 // Proceed buffer iterator position to next cell after
488 // each iteration.
489 auto cell_rel_it = cell_relations.begin();
490 auto dest_fixed_it = dest_data_fixed.cbegin();
491 for (; cell_rel_it != cell_relations.end();
492 ++cell_rel_it, dest_fixed_it += sizes_fixed_cumulative.back())
493 {
494 cell_rel_it->second = // cell_status
495 Utilities::unpack<CellStatus>(dest_fixed_it,
496 dest_fixed_it + size,
497 /*allow_compression=*/false);
498 }
499 }
500
501
502
503 template <int dim, int spacedim>
505 void CellAttachedDataSerializer<dim, spacedim>::unpack_data(
506 const std::vector<
507 typename CellAttachedDataSerializer<dim, spacedim>::cell_relation_t>
508 &cell_relations,
509 const unsigned int handle,
510 const std::function<
511 void(const cell_iterator &,
512 const CellStatus &,
513 const boost::iterator_range<std::vector<char>::const_iterator> &)>
514 &unpack_callback) const
515 {
516 // We decode the handle returned by register_data_attach() back into
517 // a format we can use. All even handles belong to those callback
518 // functions which write/read variable size data, all odd handles
519 // interact with fixed size buffers.
520 const bool callback_variable_transfer = (handle % 2 == 0);
521 const unsigned int callback_index = handle / 2;
522
523 // Cells will always receive fixed size data (i.e., CellStatus
524 // information), but not necessarily variable size data (e.g., with a
525 // ParticleHandler a cell might not contain any particle at all).
526 // Thus it is sufficient to check if fixed size data has been received.
527 Assert(sizes_fixed_cumulative.size() > 0,
528 ExcMessage("No data has been packed!"));
529 if (cell_relations.size() > 0)
530 {
531 Assert(dest_data_fixed.size() > 0,
532 ExcMessage("No data has been received!"));
533 }
534
535 std::vector<char>::const_iterator dest_data_it;
536 std::vector<char>::const_iterator dest_sizes_cell_it;
537
538 // Depending on whether our callback function unpacks fixed or
539 // variable size data, we have to pursue different approaches
540 // to localize the correct fraction of the buffer from which
541 // we are allowed to read.
542 unsigned int offset = numbers::invalid_unsigned_int;
543 unsigned int size = numbers::invalid_unsigned_int;
544 unsigned int data_increment = numbers::invalid_unsigned_int;
545
546 if (callback_variable_transfer)
547 {
548 // For the variable size data, we need to extract the
549 // data size from the fixed size buffer on each cell.
550 //
551 // We packed this information last, so the last packed
552 // object in the fixed size buffer corresponds to the
553 // variable data sizes.
554 //
555 // The last entry of sizes_fixed_cumulative corresponds
556 // to the size of all fixed size data packed on the cell.
557 // To get the offset for the last packed object, we need
558 // to get the next-to-last entry.
559 const unsigned int offset_variable_data_sizes =
560 sizes_fixed_cumulative[sizes_fixed_cumulative.size() - 2];
561
562 // This iterator points to the data size that the
563 // callback_function packed for each specific cell.
564 // Adjust buffer iterator to the offset of the callback
565 // function so that we only have to advance its position
566 // to the next cell after each iteration.
567 dest_sizes_cell_it = dest_data_fixed.cbegin() +
568 offset_variable_data_sizes +
569 callback_index * sizeof(unsigned int);
570
571 // Let the data iterator point to the correct buffer.
572 dest_data_it = dest_data_variable.cbegin();
573 }
574 else
575 {
576 // For the fixed size data, we can get the information about
577 // the buffer location on each cell directly from the
578 // sizes_fixed_cumulative vector.
579 offset = sizes_fixed_cumulative[callback_index];
580 size = sizes_fixed_cumulative[callback_index + 1] - offset;
581 data_increment = sizes_fixed_cumulative.back();
582
583 // Let the data iterator point to the correct buffer.
584 // Adjust buffer iterator to the offset of the callback
585 // function so that we only have to advance its position
586 // to the next cell after each iteration.
587 if (cell_relations.begin() != cell_relations.end())
588 dest_data_it = dest_data_fixed.cbegin() + offset;
589 }
590
591 // Iterate over all cells and unpack the transferred data.
592 auto cell_rel_it = cell_relations.begin();
593 auto dest_sizes_it = dest_sizes_variable.cbegin();
594 for (; cell_rel_it != cell_relations.end(); ++cell_rel_it)
595 {
596 const auto &dealii_cell = cell_rel_it->first;
597 const auto &cell_status = cell_rel_it->second;
598
599 if (callback_variable_transfer)
600 {
601 // Update the increment according to the whole data size
602 // of the current cell.
603 data_increment = *dest_sizes_it;
604
605 if (cell_status != CellStatus::cell_invalid)
606 {
607 // Extract the corresponding values for offset and size from
608 // the cumulative sizes array stored in the fixed size
609 // buffer.
610 if (callback_index == 0)
611 offset = 0;
612 else
613 std::memcpy(&offset,
614 &(*(dest_sizes_cell_it - sizeof(unsigned int))),
615 sizeof(unsigned int));
616
617 std::memcpy(&size,
618 &(*dest_sizes_cell_it),
619 sizeof(unsigned int));
620
621 size -= offset;
622
623 // Move the data iterator to the corresponding position
624 // of the callback function and adjust the increment
625 // accordingly.
626 dest_data_it += offset;
627 data_increment -= offset;
628 }
629
630 // Advance data size iterators to the next cell, avoid iterating
631 // past the end of dest_sizes_cell_it
632 if (cell_rel_it != cell_relations.end() - 1)
633 dest_sizes_cell_it += sizes_fixed_cumulative.back();
634 ++dest_sizes_it;
635 }
636
637 switch (cell_status)
638 {
641 unpack_callback(dealii_cell,
642 cell_status,
643 boost::make_iterator_range(dest_data_it,
644 dest_data_it + size));
645 break;
646
648 unpack_callback(dealii_cell->parent(),
649 cell_status,
650 boost::make_iterator_range(dest_data_it,
651 dest_data_it + size));
652 break;
653
655 // Skip this cell.
656 break;
657
658 default:
660 break;
661 }
662
663 if (cell_rel_it != cell_relations.end() - 1)
664 dest_data_it += data_increment;
665 }
666 }
667
668
669
670 template <int dim, int spacedim>
672 void CellAttachedDataSerializer<dim, spacedim>::save(
673 const unsigned int global_first_cell,
674 const unsigned int global_num_cells,
675 const std::string &file_basename,
676 const MPI_Comm &mpi_communicator) const
677 {
678 Assert(sizes_fixed_cumulative.size() > 0,
679 ExcMessage("No data has been packed!"));
680
681#ifdef DEAL_II_WITH_MPI
682 // Large fractions of this function have been copied from
683 // DataOutInterface::write_vtu_in_parallel.
684 // TODO: Write general MPIIO interface.
685
686 const unsigned int myrank =
687 Utilities::MPI::this_mpi_process(mpi_communicator);
688 const unsigned int mpisize =
689 Utilities::MPI::n_mpi_processes(mpi_communicator);
690
691 if (mpisize > 1)
692 {
693 const unsigned int bytes_per_cell = sizes_fixed_cumulative.back();
694
695 //
696 // ---------- Fixed size data ----------
697 //
698 {
699 const std::string fname_fixed =
700 std::string(file_basename) + "_fixed.data";
701
702 MPI_Info info;
703 int ierr = MPI_Info_create(&info);
704 AssertThrowMPI(ierr);
705
706 MPI_File fh;
707 ierr = MPI_File_open(mpi_communicator,
708 fname_fixed.c_str(),
709 MPI_MODE_CREATE | MPI_MODE_WRONLY,
710 info,
711 &fh);
712 AssertThrowMPI(ierr);
713
714 ierr = MPI_File_set_size(fh, 0); // delete the file contents
715 AssertThrowMPI(ierr);
716 // this barrier is necessary, because otherwise others might already
717 // write while one core is still setting the size to zero.
718 ierr = MPI_Barrier(mpi_communicator);
719 AssertThrowMPI(ierr);
720 ierr = MPI_Info_free(&info);
721 AssertThrowMPI(ierr);
722 // ------------------
723
724 // Write cumulative sizes to file.
725 // Since each processor owns the same information about the data
726 // sizes, it is sufficient to let only the first processor perform
727 // this task.
728 if (myrank == 0)
729 {
731 fh,
732 0,
733 sizes_fixed_cumulative.data(),
734 sizes_fixed_cumulative.size(),
735 MPI_UNSIGNED,
736 MPI_STATUS_IGNORE);
737 AssertThrowMPI(ierr);
738 }
739
740 // Write packed data to file simultaneously.
741 const MPI_Offset size_header =
742 sizes_fixed_cumulative.size() * sizeof(unsigned int);
743
744 // Make sure we do the following computation in 64bit integers to be
745 // able to handle 4GB+ files:
746 const MPI_Offset my_global_file_position =
747 size_header +
748 static_cast<MPI_Offset>(global_first_cell) * bytes_per_cell;
749
750 ierr =
752 my_global_file_position,
753 src_data_fixed.data(),
754 src_data_fixed.size(),
755 MPI_BYTE,
756 MPI_STATUS_IGNORE);
757 AssertThrowMPI(ierr);
758
759 ierr = MPI_File_close(&fh);
760 AssertThrowMPI(ierr);
761 }
762
763
764
765 //
766 // ---------- Variable size data ----------
767 //
768 if (variable_size_data_stored)
769 {
770 const std::string fname_variable =
771 std::string(file_basename) + "_variable.data";
772
773 MPI_Info info;
774 int ierr = MPI_Info_create(&info);
775 AssertThrowMPI(ierr);
776
777 MPI_File fh;
778 ierr = MPI_File_open(mpi_communicator,
779 fname_variable.c_str(),
780 MPI_MODE_CREATE | MPI_MODE_WRONLY,
781 info,
782 &fh);
783 AssertThrowMPI(ierr);
784
785 ierr = MPI_File_set_size(fh, 0); // delete the file contents
786 AssertThrowMPI(ierr);
787 // this barrier is necessary, because otherwise others might already
788 // write while one core is still setting the size to zero.
789 ierr = MPI_Barrier(mpi_communicator);
790 AssertThrowMPI(ierr);
791 ierr = MPI_Info_free(&info);
792 AssertThrowMPI(ierr);
793
794 // Write sizes of each cell into file simultaneously.
795 {
796 const MPI_Offset my_global_file_position =
797 static_cast<MPI_Offset>(global_first_cell) *
798 sizeof(unsigned int);
799
800 // It is very unlikely that a single process has more than
801 // 2 billion cells, but we might as well check.
802 AssertThrow(src_sizes_variable.size() <
803 static_cast<std::size_t>(
804 std::numeric_limits<int>::max()),
806
808 fh,
809 my_global_file_position,
810 src_sizes_variable.data(),
811 src_sizes_variable.size(),
812 MPI_INT,
813 MPI_STATUS_IGNORE);
814 AssertThrowMPI(ierr);
815 }
816
817 // Gather size of data in bytes we want to store from this
818 // processor and compute the prefix sum. We do this in 64 bit
819 // to avoid overflow for files larger than 4GB:
820 const std::uint64_t size_on_proc = src_data_variable.size();
821 std::uint64_t prefix_sum = 0;
822 ierr = MPI_Exscan(&size_on_proc,
823 &prefix_sum,
824 1,
825 MPI_UINT64_T,
826 MPI_SUM,
827 mpi_communicator);
828 AssertThrowMPI(ierr);
829
830 const MPI_Offset my_global_file_position =
831 static_cast<MPI_Offset>(global_num_cells) * sizeof(unsigned int) +
832 prefix_sum;
833
834 // Write data consecutively into file.
836 fh,
837 my_global_file_position,
838 src_data_variable.data(),
839 src_data_variable.size(),
840 MPI_BYTE,
841 MPI_STATUS_IGNORE);
842 AssertThrowMPI(ierr);
843
844
845 ierr = MPI_File_close(&fh);
846 AssertThrowMPI(ierr);
847 }
848 } // if (mpisize > 1)
849 else
850#endif
851 {
852 (void)global_first_cell;
853 (void)global_num_cells;
854 (void)mpi_communicator;
855
856 //
857 // ---------- Fixed size data ----------
858 //
859 {
860 const std::string fname_fixed =
861 std::string(file_basename) + "_fixed.data";
862
863 std::ofstream file(fname_fixed, std::ios::binary | std::ios::out);
864 AssertThrow(file.fail() == false, ExcIO());
865
866 // Write header data.
867 file.write(reinterpret_cast<const char *>(
868 sizes_fixed_cumulative.data()),
869 sizes_fixed_cumulative.size() * sizeof(unsigned int));
870
871 // Write packed data.
872 file.write(reinterpret_cast<const char *>(src_data_fixed.data()),
873 src_data_fixed.size() * sizeof(char));
874 }
875
876 //
877 // ---------- Variable size data ----------
878 //
879 if (variable_size_data_stored)
880 {
881 const std::string fname_variable =
882 std::string(file_basename) + "_variable.data";
883
884 std::ofstream file(fname_variable,
885 std::ios::binary | std::ios::out);
886 AssertThrow(file.fail() == false, ExcIO());
887
888 // Write header data.
889 file.write(reinterpret_cast<const char *>(
890 src_sizes_variable.data()),
891 src_sizes_variable.size() * sizeof(int));
892
893 // Write packed data.
894 file.write(reinterpret_cast<const char *>(src_data_variable.data()),
895 src_data_variable.size() * sizeof(char));
896 }
897 }
898 }
899
900
901 template <int dim, int spacedim>
903 void CellAttachedDataSerializer<dim, spacedim>::load(
904 const unsigned int global_first_cell,
905 const unsigned int global_num_cells,
906 const unsigned int local_num_cells,
907 const std::string &file_basename,
908 const unsigned int n_attached_deserialize_fixed,
909 const unsigned int n_attached_deserialize_variable,
910 const MPI_Comm &mpi_communicator)
911 {
912 Assert(dest_data_fixed.empty(),
913 ExcMessage("Previously loaded data has not been released yet!"));
914
915 variable_size_data_stored = (n_attached_deserialize_variable > 0);
916
917#ifdef DEAL_II_WITH_MPI
918 // Large fractions of this function have been copied from
919 // DataOutInterface::write_vtu_in_parallel.
920 // TODO: Write general MPIIO interface.
921
922 const unsigned int mpisize =
923 Utilities::MPI::n_mpi_processes(mpi_communicator);
924
925 if (mpisize > 1)
926 {
927 //
928 // ---------- Fixed size data ----------
929 //
930 {
931 const std::string fname_fixed =
932 std::string(file_basename) + "_fixed.data";
933
934 MPI_Info info;
935 int ierr = MPI_Info_create(&info);
936 AssertThrowMPI(ierr);
937
938 MPI_File fh;
939 ierr = MPI_File_open(
940 mpi_communicator, fname_fixed.c_str(), MPI_MODE_RDONLY, info, &fh);
941 AssertThrowMPI(ierr);
942
943 ierr = MPI_Info_free(&info);
944 AssertThrowMPI(ierr);
945
946 // Read cumulative sizes from file.
947 // Since all processors need the same information about the data
948 // sizes, let each of them retrieve it by reading from the same
949 // location in the file.
950 sizes_fixed_cumulative.resize(1 + n_attached_deserialize_fixed +
951 (variable_size_data_stored ? 1 : 0));
953 fh,
954 0,
955 sizes_fixed_cumulative.data(),
956 sizes_fixed_cumulative.size(),
957 MPI_UNSIGNED,
958 MPI_STATUS_IGNORE);
959 AssertThrowMPI(ierr);
960
961 // Allocate sufficient memory.
962 const unsigned int bytes_per_cell = sizes_fixed_cumulative.back();
963 dest_data_fixed.resize(static_cast<std::size_t>(local_num_cells) *
964 bytes_per_cell);
965
966 // Read packed data from file simultaneously.
967 const MPI_Offset size_header =
968 sizes_fixed_cumulative.size() * sizeof(unsigned int);
969
970 // Make sure we do the following computation in 64bit integers to be
971 // able to handle 4GB+ files:
972 const MPI_Offset my_global_file_position =
973 size_header +
974 static_cast<MPI_Offset>(global_first_cell) * bytes_per_cell;
975
976 ierr =
978 my_global_file_position,
979 dest_data_fixed.data(),
980 dest_data_fixed.size(),
981 MPI_BYTE,
982 MPI_STATUS_IGNORE);
983 AssertThrowMPI(ierr);
984
985
986 ierr = MPI_File_close(&fh);
987 AssertThrowMPI(ierr);
988 }
989
990 //
991 // ---------- Variable size data ----------
992 //
993 if (variable_size_data_stored)
994 {
995 const std::string fname_variable =
996 std::string(file_basename) + "_variable.data";
997
998 MPI_Info info;
999 int ierr = MPI_Info_create(&info);
1000 AssertThrowMPI(ierr);
1001
1002 MPI_File fh;
1003 ierr = MPI_File_open(mpi_communicator,
1004 fname_variable.c_str(),
1005 MPI_MODE_RDONLY,
1006 info,
1007 &fh);
1008 AssertThrowMPI(ierr);
1009
1010 ierr = MPI_Info_free(&info);
1011 AssertThrowMPI(ierr);
1012
1013 // Read sizes of all locally owned cells.
1014 dest_sizes_variable.resize(local_num_cells);
1015
1016 const MPI_Offset my_global_file_position_sizes =
1017 static_cast<MPI_Offset>(global_first_cell) * sizeof(unsigned int);
1018
1020 fh,
1021 my_global_file_position_sizes,
1022 dest_sizes_variable.data(),
1023 dest_sizes_variable.size(),
1024 MPI_INT,
1025 MPI_STATUS_IGNORE);
1026 AssertThrowMPI(ierr);
1027
1028
1029 // Compute my data size in bytes and compute prefix sum. We do this
1030 // in 64 bit to avoid overflow for files larger than 4 GB:
1031 const std::uint64_t size_on_proc =
1032 std::accumulate(dest_sizes_variable.begin(),
1033 dest_sizes_variable.end(),
1034 0ULL);
1035
1036 std::uint64_t prefix_sum = 0;
1037 ierr = MPI_Exscan(&size_on_proc,
1038 &prefix_sum,
1039 1,
1040 MPI_UINT64_T,
1041 MPI_SUM,
1042 mpi_communicator);
1043 AssertThrowMPI(ierr);
1044
1045 const MPI_Offset my_global_file_position =
1046 static_cast<MPI_Offset>(global_num_cells) * sizeof(unsigned int) +
1047 prefix_sum;
1048
1049 dest_data_variable.resize(size_on_proc);
1050
1052 fh,
1053 my_global_file_position,
1054 dest_data_variable.data(),
1055 dest_data_variable.size(),
1056 MPI_BYTE,
1057 MPI_STATUS_IGNORE);
1058 AssertThrowMPI(ierr);
1059
1060 ierr = MPI_File_close(&fh);
1061 AssertThrowMPI(ierr);
1062 }
1063 }
1064 else // if (mpisize > 1)
1065#endif
1066 {
1067 (void)mpi_communicator;
1068 (void)global_first_cell;
1069 (void)global_num_cells;
1070
1071 //
1072 // ---------- Fixed size data ----------
1073 //
1074 {
1075 const std::string fname_fixed =
1076 std::string(file_basename) + "_fixed.data";
1077
1078 std::ifstream file(fname_fixed, std::ios::binary | std::ios::in);
1079 AssertThrow(file.fail() == false, ExcIO());
1080
1081 sizes_fixed_cumulative.resize(1 + n_attached_deserialize_fixed +
1082 (variable_size_data_stored ? 1 : 0));
1083 // Read header data.
1084 file.read(reinterpret_cast<char *>(sizes_fixed_cumulative.data()),
1085 sizes_fixed_cumulative.size() * sizeof(unsigned int));
1086
1087 const unsigned int bytes_per_cell = sizes_fixed_cumulative.back();
1088 dest_data_fixed.resize(static_cast<std::size_t>(local_num_cells) *
1089 bytes_per_cell);
1090
1091 // Read packed data.
1092 file.read(reinterpret_cast<char *>(dest_data_fixed.data()),
1093 dest_data_fixed.size() * sizeof(char));
1094 }
1095
1096 //
1097 // ---------- Variable size data ----------
1098 //
1099 if (variable_size_data_stored)
1100 {
1101 const std::string fname_variable =
1102 std::string(file_basename) + "_variable.data";
1103
1104 std::ifstream file(fname_variable, std::ios::binary | std::ios::in);
1105 AssertThrow(file.fail() == false, ExcIO());
1106
1107 // Read header data.
1108 dest_sizes_variable.resize(local_num_cells);
1109 file.read(reinterpret_cast<char *>(dest_sizes_variable.data()),
1110 dest_sizes_variable.size() * sizeof(int));
1111
1112 // Read packed data.
1113 const std::uint64_t size =
1114 std::accumulate(dest_sizes_variable.begin(),
1115 dest_sizes_variable.end(),
1116 0ULL);
1117 dest_data_variable.resize(size);
1118 file.read(reinterpret_cast<char *>(dest_data_variable.data()),
1119 dest_data_variable.size() * sizeof(char));
1120 }
1121 }
1122 }
1123
1124
1125 template <int dim, int spacedim>
1127 void CellAttachedDataSerializer<dim, spacedim>::clear()
1128 {
1129 variable_size_data_stored = false;
1130
1131 // free information about data sizes
1132 sizes_fixed_cumulative.clear();
1133 sizes_fixed_cumulative.shrink_to_fit();
1134
1135 // free fixed size transfer data
1136 src_data_fixed.clear();
1137 src_data_fixed.shrink_to_fit();
1138
1139 dest_data_fixed.clear();
1140 dest_data_fixed.shrink_to_fit();
1141
1142 // free variable size transfer data
1143 src_sizes_variable.clear();
1144 src_sizes_variable.shrink_to_fit();
1145
1146 src_data_variable.clear();
1147 src_data_variable.shrink_to_fit();
1148
1149 dest_sizes_variable.clear();
1150 dest_sizes_variable.shrink_to_fit();
1151
1152 dest_data_variable.clear();
1153 dest_data_variable.shrink_to_fit();
1154 }
1155
1156} // namespace internal
1157
1158// anonymous namespace for internal helper functions
1159namespace
1160{
1161 // return whether the given cell is
1162 // patch_level_1, i.e. determine
1163 // whether either all or none of
1164 // its children are further
1165 // refined. this function can only
1166 // be called for non-active cells.
1167 template <int dim, int spacedim>
1168 bool
1169 cell_is_patch_level_1(
1171 {
1172 Assert(cell->is_active() == false, ExcInternalError());
1173
1174 unsigned int n_active_children = 0;
1175 for (unsigned int i = 0; i < cell->n_children(); ++i)
1176 if (cell->child(i)->is_active())
1177 ++n_active_children;
1178
1179 return (n_active_children == 0) ||
1180 (n_active_children == cell->n_children());
1181 }
1182
1183
1184
1185 // return, whether a given @p cell will be
1186 // coarsened, which is the case if all
1187 // children are active and have their coarsen
1188 // flag set. In case only part of the coarsen
1189 // flags are set, remove them.
1190 template <int dim, int spacedim>
1191 bool
1192 cell_will_be_coarsened(
1194 {
1195 // only cells with children should be
1196 // considered for coarsening
1197
1198 if (cell->has_children())
1199 {
1200 unsigned int children_to_coarsen = 0;
1201 const unsigned int n_children = cell->n_children();
1202
1203 for (unsigned int c = 0; c < n_children; ++c)
1204 if (cell->child(c)->is_active() && cell->child(c)->coarsen_flag_set())
1205 ++children_to_coarsen;
1206 if (children_to_coarsen == n_children)
1207 return true;
1208 else
1209 for (unsigned int c = 0; c < n_children; ++c)
1210 if (cell->child(c)->is_active())
1211 cell->child(c)->clear_coarsen_flag();
1212 }
1213 // no children, so no coarsening
1214 // possible. however, no children also
1215 // means that this cell will be in the same
1216 // state as if it had children and was
1217 // coarsened. So, what should we return -
1218 // false or true?
1219 // make sure we do not have to do this at
1220 // all...
1221 Assert(cell->has_children(), ExcInternalError());
1222 // ... and then simply return false
1223 return false;
1224 }
1225
1226
1227 // return, whether the face @p face_no of the
1228 // given @p cell will be refined after the
1229 // current refinement step, considering
1230 // refine and coarsen flags and considering
1231 // only those refinemnts that will be caused
1232 // by the neighboring cell.
1233
1234 // this function is used on both active cells
1235 // and cells with children. on cells with
1236 // children it also of interest to know 'how'
1237 // the face will be refined. thus there is an
1238 // additional third argument @p
1239 // expected_face_ref_case returning just
1240 // that. be aware, that this variable will
1241 // only contain useful information if this
1242 // function is called for an active cell.
1243 //
1244 // thus, this is an internal function, users
1245 // should call one of the two alternatives
1246 // following below.
1247 template <int dim, int spacedim>
1248 bool
1249 face_will_be_refined_by_neighbor_internal(
1251 const unsigned int face_no,
1252 RefinementCase<dim - 1> &expected_face_ref_case)
1253 {
1254 // first of all: set the default value for
1255 // expected_face_ref_case, which is no
1256 // refinement at all
1257 expected_face_ref_case = RefinementCase<dim - 1>::no_refinement;
1258
1259 const typename Triangulation<dim, spacedim>::cell_iterator neighbor =
1260 cell->neighbor(face_no);
1261
1262 // If we are at the boundary, there is no
1263 // neighbor which could refine the face
1264 if (neighbor.state() != IteratorState::valid)
1265 return false;
1266
1267 if (neighbor->has_children())
1268 {
1269 // if the neighbor is refined, it may be
1270 // coarsened. if so, then it won't refine
1271 // the face, no matter what else happens
1272 if (cell_will_be_coarsened(neighbor))
1273 return false;
1274 else
1275 // if the neighbor is refined, then it
1276 // is also refined at our current
1277 // face. It will stay so without
1278 // coarsening, so return true in that
1279 // case.
1280 {
1281 expected_face_ref_case = cell->face(face_no)->refinement_case();
1282 return true;
1283 }
1284 }
1285
1286 // now, the neighbor is not refined, but
1287 // perhaps it will be
1288 const RefinementCase<dim> nb_ref_flag = neighbor->refine_flag_set();
1289 if (nb_ref_flag != RefinementCase<dim>::no_refinement)
1290 {
1291 // now we need to know, which of the
1292 // neighbors faces points towards us
1293 const unsigned int neighbor_neighbor = cell->neighbor_face_no(face_no);
1294 // check, whether the cell will be
1295 // refined in a way that refines our
1296 // face
1297 const RefinementCase<dim - 1> face_ref_case =
1299 nb_ref_flag,
1300 neighbor_neighbor,
1301 neighbor->face_orientation(neighbor_neighbor),
1302 neighbor->face_flip(neighbor_neighbor),
1303 neighbor->face_rotation(neighbor_neighbor));
1304 if (face_ref_case != RefinementCase<dim - 1>::no_refinement)
1305 {
1307 neighbor_face = neighbor->face(neighbor_neighbor);
1308 const int this_face_index = cell->face_index(face_no);
1309
1310 // there are still two basic
1311 // possibilities here: the neighbor
1312 // might be coarser or as coarse
1313 // as we are
1314 if (neighbor_face->index() == this_face_index)
1315 // the neighbor is as coarse as
1316 // we are and will be refined at
1317 // the face of consideration, so
1318 // return true
1319 {
1320 expected_face_ref_case = face_ref_case;
1321 return true;
1322 }
1323 else
1324 {
1325 // the neighbor is coarser.
1326 // this is the most complicated
1327 // case. It might be, that the
1328 // neighbor's face will be
1329 // refined, but that we will
1330 // not see this, as we are
1331 // refined in a similar way.
1332
1333 // so, the neighbor's face must
1334 // have children. check, if our
1335 // cell's face is one of these
1336 // (it could also be a
1337 // grand_child)
1338 for (unsigned int c = 0; c < neighbor_face->n_children(); ++c)
1339 if (neighbor_face->child_index(c) == this_face_index)
1340 {
1341 // if the flagged refine
1342 // case of the face is a
1343 // subset or the same as
1344 // the current refine case,
1345 // then the face, as seen
1346 // from our cell, won't be
1347 // refined by the neighbor
1348 if ((neighbor_face->refinement_case() | face_ref_case) ==
1349 neighbor_face->refinement_case())
1350 return false;
1351 else
1352 {
1353 // if we are active, we
1354 // must be an
1355 // anisotropic child
1356 // and the coming
1357 // face_ref_case is
1358 // isotropic. Thus,
1359 // from our cell we
1360 // will see exactly the
1361 // opposite refine case
1362 // that the face has
1363 // now...
1364 Assert(
1365 face_ref_case ==
1368 expected_face_ref_case =
1369 ~neighbor_face->refinement_case();
1370 return true;
1371 }
1372 }
1373
1374 // so, obviously we were not
1375 // one of the children, but a
1376 // grandchild. This is only
1377 // possible in 3d.
1378 Assert(dim == 3, ExcInternalError());
1379 // In that case, however, no
1380 // matter what the neighbor
1381 // does, it won't be finer
1382 // after the next refinement
1383 // step.
1384 return false;
1385 }
1386 } // if face will be refined
1387 } // if neighbor is flagged for refinement
1388
1389 // no cases left, so the neighbor will not
1390 // refine the face
1391 return false;
1392 }
1393
1394 // version of above function for both active
1395 // and non-active cells
1396 template <int dim, int spacedim>
1397 bool
1398 face_will_be_refined_by_neighbor(
1400 const unsigned int face_no)
1401 {
1402 RefinementCase<dim - 1> dummy = RefinementCase<dim - 1>::no_refinement;
1403 return face_will_be_refined_by_neighbor_internal(cell, face_no, dummy);
1404 }
1405
1406 // version of above function for active cells
1407 // only. Additionally returning the refine
1408 // case (to come) of the face under
1409 // consideration
1410 template <int dim, int spacedim>
1411 bool
1412 face_will_be_refined_by_neighbor(
1414 const unsigned int face_no,
1415 RefinementCase<dim - 1> &expected_face_ref_case)
1416 {
1417 return face_will_be_refined_by_neighbor_internal(cell,
1418 face_no,
1419 expected_face_ref_case);
1420 }
1421
1422
1423
1424 template <int dim, int spacedim>
1425 bool
1426 satisfies_level1_at_vertex_rule(
1428 {
1429 std::vector<unsigned int> min_adjacent_cell_level(
1430 triangulation.n_vertices(), triangulation.n_levels());
1431 std::vector<unsigned int> max_adjacent_cell_level(
1432 triangulation.n_vertices(), 0);
1433
1434 for (const auto &cell : triangulation.active_cell_iterators())
1435 for (const unsigned int v : cell->vertex_indices())
1436 {
1437 min_adjacent_cell_level[cell->vertex_index(v)] =
1438 std::min<unsigned int>(
1439 min_adjacent_cell_level[cell->vertex_index(v)], cell->level());
1440 max_adjacent_cell_level[cell->vertex_index(v)] =
1441 std::max<unsigned int>(
1442 min_adjacent_cell_level[cell->vertex_index(v)], cell->level());
1443 }
1444
1445 for (unsigned int k = 0; k < triangulation.n_vertices(); ++k)
1446 if (triangulation.vertex_used(k))
1447 if (max_adjacent_cell_level[k] - min_adjacent_cell_level[k] > 1)
1448 return false;
1449 return true;
1450 }
1451
1452
1453
1471 template <int dim, int spacedim>
1472 unsigned int
1473 middle_vertex_index(
1475 {
1476 if (line->has_children())
1477 return line->child(0)->vertex_index(1);
1479 }
1480
1481
1482 template <int dim, int spacedim>
1483 unsigned int
1484 middle_vertex_index(
1486 {
1487 switch (static_cast<unsigned char>(quad->refinement_case()))
1488 {
1490 return middle_vertex_index<dim, spacedim>(quad->child(0)->line(1));
1491 break;
1493 return middle_vertex_index<dim, spacedim>(quad->child(0)->line(3));
1494 break;
1496 return quad->child(0)->vertex_index(3);
1497 break;
1498 default:
1499 break;
1500 }
1502 }
1503
1504
1505 template <int dim, int spacedim>
1506 unsigned int
1507 middle_vertex_index(
1509 {
1510 switch (static_cast<unsigned char>(hex->refinement_case()))
1511 {
1513 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(1));
1514 break;
1516 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(3));
1517 break;
1519 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(5));
1520 break;
1522 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(11));
1523 break;
1525 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(5));
1526 break;
1528 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(7));
1529 break;
1531 return hex->child(0)->vertex_index(7);
1532 break;
1533 default:
1534 break;
1535 }
1537 }
1538
1539
1552 template <class TRIANGULATION>
1553 inline typename TRIANGULATION::DistortedCellList
1554 collect_distorted_coarse_cells(const TRIANGULATION &)
1555 {
1556 return typename TRIANGULATION::DistortedCellList();
1557 }
1558
1559
1560
1569 template <int dim>
1571 collect_distorted_coarse_cells(const Triangulation<dim, dim> &triangulation)
1572 {
1573 typename Triangulation<dim, dim>::DistortedCellList distorted_cells;
1574 for (const auto &cell : triangulation.cell_iterators_on_level(0))
1575 {
1577 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1578 vertices[i] = cell->vertex(i);
1579
1582
1583 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1584 if (determinants[i] <=
1585 1e-9 * Utilities::fixed_power<dim>(cell->diameter()))
1586 {
1587 distorted_cells.distorted_cells.push_back(cell);
1588 break;
1589 }
1590 }
1591
1592 return distorted_cells;
1593 }
1594
1595
1602 template <int dim>
1603 bool
1604 has_distorted_children(
1605 const typename Triangulation<dim, dim>::cell_iterator &cell)
1606 {
1607 Assert(cell->has_children(), ExcInternalError());
1608
1609 for (unsigned int c = 0; c < cell->n_children(); ++c)
1610 {
1612 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1613 vertices[i] = cell->child(c)->vertex(i);
1614
1617
1618 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1619 if (determinants[i] <=
1620 1e-9 * Utilities::fixed_power<dim>(cell->child(c)->diameter()))
1621 return true;
1622 }
1623
1624 return false;
1625 }
1626
1627
1635 template <int dim, int spacedim>
1636 bool
1637 has_distorted_children(
1639 {
1640 return false;
1641 }
1642
1643
1644 template <int dim, int spacedim>
1645 void
1646 update_periodic_face_map_recursively(
1647 const typename Triangulation<dim, spacedim>::cell_iterator &cell_1,
1648 const typename Triangulation<dim, spacedim>::cell_iterator &cell_2,
1649 unsigned int n_face_1,
1650 unsigned int n_face_2,
1651 const types::geometric_orientation orientation,
1652 typename std::map<
1654 unsigned int>,
1655 std::pair<std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
1656 unsigned int>,
1657 types::geometric_orientation>> &periodic_face_map)
1658 {
1659 using FaceIterator = typename Triangulation<dim, spacedim>::face_iterator;
1660 const FaceIterator face_1 = cell_1->face(n_face_1);
1661 const FaceIterator face_2 = cell_2->face(n_face_2);
1662
1663 const auto inverse_orientation =
1664 face_1->reference_cell().get_inverse_combined_orientation(orientation);
1665
1666 if constexpr (running_in_debug_mode())
1667 {
1668 const auto [face_orientation, face_rotation, face_flip] =
1670
1671 Assert((dim != 1) || (face_orientation == true && face_flip == false &&
1672 face_rotation == false),
1673 ExcMessage("The supplied orientation "
1674 "(face_orientation, face_flip, face_rotation) "
1675 "is invalid for 1d"));
1676
1677 Assert((dim != 2) || (face_flip == false && face_rotation == false),
1678 ExcMessage("The supplied orientation "
1679 "(face_orientation, face_flip, face_rotation) "
1680 "is invalid for 2d"));
1681 }
1682
1683 Assert(face_1 != face_2, ExcMessage("face_1 and face_2 are equal!"));
1684
1685 Assert(face_1->at_boundary() && face_2->at_boundary(),
1686 ExcMessage("Periodic faces must be on the boundary"));
1687
1688 // Check if the requirement that each edge can only have at most one hanging
1689 // node, and as a consequence neighboring cells can differ by at most
1690 // one refinement level is enforced. In 1d, there are no hanging nodes and
1691 // so neighboring cells can differ by more than one refinement level.
1692 Assert(dim == 1 || std::abs(cell_1->level() - cell_2->level()) < 2,
1694
1695 // insert periodic face pair for both cells
1696 using CellFace =
1697 std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
1698 unsigned int>;
1699 const CellFace cell_face_1(cell_1, n_face_1);
1700 const CellFace cell_face_2(cell_2, n_face_2);
1701 const std::pair<CellFace, types::geometric_orientation>
1702 cell_face_orientation_2(cell_face_2, orientation);
1703
1704 const std::pair<CellFace, std::pair<CellFace, types::geometric_orientation>>
1705 periodic_faces(cell_face_1, cell_face_orientation_2);
1706
1707 // Only one periodic neighbor is allowed
1708 Assert(periodic_face_map.count(cell_face_1) == 0, ExcInternalError());
1709 periodic_face_map.insert(periodic_faces);
1710
1711 if (dim == 1)
1712 {
1713 if (cell_1->has_children())
1714 {
1715 if (cell_2->has_children())
1716 {
1717 update_periodic_face_map_recursively<dim, spacedim>(
1718 cell_1->child(n_face_1),
1719 cell_2->child(n_face_2),
1720 n_face_1,
1721 n_face_2,
1722 orientation,
1723 periodic_face_map);
1724 }
1725 else // only face_1 has children
1726 {
1727 update_periodic_face_map_recursively<dim, spacedim>(
1728 cell_1->child(n_face_1),
1729 cell_2,
1730 n_face_1,
1731 n_face_2,
1732 orientation,
1733 periodic_face_map);
1734 }
1735 }
1736 }
1737 else // dim == 2 || dim == 3
1738 {
1739 if (cell_1->has_children())
1740 {
1741 if (cell_2->has_children())
1742 {
1743 // In the case that both faces have children, we loop over all
1744 // children and apply update_periodic_face_map_recursively
1745 // recursively:
1746
1747 Assert(face_1->n_children() ==
1749 face_2->n_children() ==
1752
1753 const auto reference_cell = cell_1->reference_cell();
1754
1755 for (unsigned int i = 0;
1756 i < GeometryInfo<dim>::max_children_per_face;
1757 ++i)
1758 {
1759 // Lookup the index for the second face
1760 const unsigned int j =
1761 reference_cell.standard_to_real_face_vertex(
1762 i, n_face_1, inverse_orientation);
1763
1764 // find subcell ids that belong to the subface indices
1765 unsigned int child_cell_1 =
1767 cell_1->refinement_case(),
1768 n_face_1,
1769 i,
1770 cell_1->face_orientation(n_face_1),
1771 cell_1->face_flip(n_face_1),
1772 cell_1->face_rotation(n_face_1),
1773 face_1->refinement_case());
1774 unsigned int child_cell_2 =
1776 cell_2->refinement_case(),
1777 n_face_2,
1778 j,
1779 cell_2->face_orientation(n_face_2),
1780 cell_2->face_flip(n_face_2),
1781 cell_2->face_rotation(n_face_2),
1782 face_2->refinement_case());
1783
1784 Assert(cell_1->child(child_cell_1)->face(n_face_1) ==
1785 face_1->child(i),
1787 Assert(cell_2->child(child_cell_2)->face(n_face_2) ==
1788 face_2->child(j),
1790
1791 // precondition: subcell has the same orientation as cell
1792 // (so that the face numbers coincide) recursive call
1793 update_periodic_face_map_recursively<dim, spacedim>(
1794 cell_1->child(child_cell_1),
1795 cell_2->child(child_cell_2),
1796 n_face_1,
1797 n_face_2,
1798 orientation,
1799 periodic_face_map);
1800 }
1801 }
1802 else // only face_1 has children
1803 {
1804 for (unsigned int i = 0;
1805 i < GeometryInfo<dim>::max_children_per_face;
1806 ++i)
1807 {
1808 // find subcell ids that belong to the subface indices
1809 unsigned int child_cell_1 =
1811 cell_1->refinement_case(),
1812 n_face_1,
1813 i,
1814 cell_1->face_orientation(n_face_1),
1815 cell_1->face_flip(n_face_1),
1816 cell_1->face_rotation(n_face_1),
1817 face_1->refinement_case());
1818
1819 // recursive call
1820 update_periodic_face_map_recursively<dim, spacedim>(
1821 cell_1->child(child_cell_1),
1822 cell_2,
1823 n_face_1,
1824 n_face_2,
1825 orientation,
1826 periodic_face_map);
1827 }
1828 }
1829 }
1830 }
1831 }
1832
1833 // Given the child number and parent's line orientation, return the child face
1834 // number.
1835 unsigned int
1836 child_line_index(const unsigned int child_no,
1837 const types::geometric_orientation line_orientation)
1838 {
1839 AssertIndexRange(child_no, ReferenceCells::Line.template n_children<1>());
1840 Assert(line_orientation == numbers::default_geometric_orientation ||
1841 line_orientation == numbers::reverse_line_orientation,
1843 constexpr auto D = numbers::default_geometric_orientation;
1844 if (child_no == 0)
1845 return line_orientation == D ? 0 : 1;
1846 else
1847 return line_orientation == D ? 1 : 0;
1848 }
1849
1850 // Several parts of Triangulation (e.g., TriaLevel) are not templated on the
1851 // dimension and thus require de-templated versions of some ReferenceCell
1852 // functions.
1853 unsigned int
1854 max_n_faces(const unsigned int structdim)
1855 {
1856 switch (structdim)
1857 {
1858 case 0:
1859 return ReferenceCells::max_n_faces<0>();
1860 case 1:
1861 return ReferenceCells::max_n_faces<1>();
1862 case 2:
1863 return ReferenceCells::max_n_faces<2>();
1864 case 3:
1865 return ReferenceCells::max_n_faces<3>();
1866 default:
1869 }
1870 }
1871} // end of anonymous namespace
1872
1873
1874namespace internal
1875{
1876 namespace TriangulationImplementation
1877 {
1878 // make sure that if in the following we
1879 // write Triangulation<dim,spacedim>
1880 // we mean the *class*
1881 // ::Triangulation, not the
1882 // enclosing namespace
1883 // internal::TriangulationImplementation
1884 using ::Triangulation;
1885
1891 int,
1892 << "Something went wrong upon construction of cell "
1893 << arg1);
1904 int,
1905 << "Cell " << arg1
1906 << " has negative measure. This typically "
1907 << "indicates some distortion in the cell, or a mistakenly "
1908 << "swapped pair of vertices in the input to "
1909 << "Triangulation::create_triangulation().");
1918 int,
1919 int,
1920 int,
1921 << "Error while creating cell " << arg1
1922 << ": the vertex index " << arg2 << " must be between 0 and "
1923 << arg3 << '.');
1930 int,
1931 int,
1933 << "The input data for creating a triangulation contained "
1934 << "information about a line with indices " << arg1 << " and " << arg2
1935 << " that is described to have boundary indicator "
1936 << static_cast<int>(arg3)
1937 << ". However, this is an internal line not located on the "
1938 << "boundary. You cannot assign a boundary indicator to it." << std::endl
1939 << std::endl
1940 << "If this happened at a place where you call "
1941 << "Triangulation::create_triangulation() yourself, you need "
1942 << "to check the SubCellData object you pass to this function."
1943 << std::endl
1944 << std::endl
1945 << "If this happened in a place where you are reading a mesh "
1946 << "from a file, then you need to investigate why such a line "
1947 << "ended up in the input file. A typical case is a geometry "
1948 << "that consisted of multiple parts and for which the mesh "
1949 << "generator program assumes that the interface between "
1950 << "two parts is a boundary when that isn't supposed to be "
1951 << "the case, or where the mesh generator simply assigns "
1952 << "'geometry indicators' to lines at the perimeter of "
1953 << "a part that are not supposed to be interpreted as "
1954 << "'boundary indicators'.");
1961 int,
1962 int,
1963 int,
1964 int,
1966 << "The input data for creating a triangulation contained "
1967 << "information about a quad with indices " << arg1 << ", " << arg2
1968 << ", " << arg3 << ", and " << arg4
1969 << " that is described to have boundary indicator "
1970 << static_cast<int>(arg5)
1971 << ". However, this is an internal quad not located on the "
1972 << "boundary. You cannot assign a boundary indicator to it." << std::endl
1973 << std::endl
1974 << "If this happened at a place where you call "
1975 << "Triangulation::create_triangulation() yourself, you need "
1976 << "to check the SubCellData object you pass to this function."
1977 << std::endl
1978 << std::endl
1979 << "If this happened in a place where you are reading a mesh "
1980 << "from a file, then you need to investigate why such a quad "
1981 << "ended up in the input file. A typical case is a geometry "
1982 << "that consisted of multiple parts and for which the mesh "
1983 << "generator program assumes that the interface between "
1984 << "two parts is a boundary when that isn't supposed to be "
1985 << "the case, or where the mesh generator simply assigns "
1986 << "'geometry indicators' to quads at the surface of "
1987 << "a part that are not supposed to be interpreted as "
1988 << "'boundary indicators'.");
1995 int,
1996 int,
1997 << "In SubCellData the line info of the line with vertex indices " << arg1
1998 << " and " << arg2 << " appears more than once. "
1999 << "This is not allowed.");
2006 int,
2007 int,
2008 std::string,
2009 << "In SubCellData the line info of the line with vertex indices " << arg1
2010 << " and " << arg2 << " appears multiple times with different (valid) "
2011 << arg3 << ". This is not allowed.");
2018 int,
2019 int,
2020 int,
2021 int,
2022 std::string,
2023 << "In SubCellData the quad info of the quad with line indices " << arg1
2024 << ", " << arg2 << ", " << arg3 << " and " << arg4
2025 << " appears multiple times with different (valid) " << arg5
2026 << ". This is not allowed.");
2027
2028 /*
2029 * Reserve space for TriaFaces. Details:
2030 *
2031 * Reserve space for line_orientations.
2032 *
2033 * @note Used only for dim=3.
2034 */
2035 void
2037 const unsigned int new_quads_in_pairs,
2038 const unsigned int new_quads_single)
2039 {
2040 AssertDimension(tria_faces.dim, 3);
2041
2042 Assert(new_quads_in_pairs % 2 == 0, ExcInternalError());
2043
2044 unsigned int next_free_single = 0;
2045 unsigned int next_free_pair = 0;
2046
2047 // count the number of objects, of unused single objects and of
2048 // unused pairs of objects
2049 [[maybe_unused]] unsigned int n_quads = 0;
2050 unsigned int n_unused_pairs = 0;
2051 unsigned int n_unused_singles = 0;
2052 for (unsigned int i = 0; i < tria_faces.quads.used.size(); ++i)
2053 {
2054 if (tria_faces.quads.used[i])
2055 ++n_quads;
2056 else if (i + 1 < tria_faces.quads.used.size())
2057 {
2058 if (tria_faces.quads.used[i + 1])
2059 {
2060 ++n_unused_singles;
2061 if (next_free_single == 0)
2062 next_free_single = i;
2063 }
2064 else
2065 {
2066 ++n_unused_pairs;
2067 if (next_free_pair == 0)
2068 next_free_pair = i;
2069 ++i;
2070 }
2071 }
2072 else
2073 ++n_unused_singles;
2074 }
2075 Assert(n_quads + 2 * n_unused_pairs + n_unused_singles ==
2076 tria_faces.quads.used.size(),
2078
2079 // how many single quads are needed in addition to n_unused_quads?
2080 const int additional_single_quads = new_quads_single - n_unused_singles;
2081
2082 unsigned int new_size =
2083 tria_faces.quads.used.size() + new_quads_in_pairs - 2 * n_unused_pairs;
2084 if (additional_single_quads > 0)
2085 new_size += additional_single_quads;
2086
2087 // see above...
2088 if (new_size > tria_faces.quads.n_objects())
2089 {
2090 // reserve the field of the derived class
2091 tria_faces.quads_line_orientations.resize(
2092 new_size * ReferenceCells::max_n_lines<2>(), true);
2093
2094 auto &q_is_q = tria_faces.quad_is_quadrilateral;
2095 q_is_q.reserve(new_size);
2096 q_is_q.insert(q_is_q.end(), new_size - q_is_q.size(), true);
2097 }
2098 }
2099
2100
2101
2112 void
2114 const unsigned int total_cells,
2115 const unsigned int space_dimension,
2116 const bool tetraheder_in_mesh = false)
2117 {
2118 const unsigned int dim = tria_level.dim;
2119
2120 // we need space for total_cells cells. Maybe we have more already
2121 // with those cells which are unused, so only allocate new space if
2122 // needed.
2123 //
2124 // note that all arrays should have equal sizes (checked by
2125 // @p{monitor_memory}
2126 if (total_cells > tria_level.refine_flags.size())
2127 {
2128 tria_level.refine_flags.reserve(total_cells);
2129 tria_level.refine_flags.insert(tria_level.refine_flags.end(),
2130 total_cells -
2131 tria_level.refine_flags.size(),
2132 /*RefinementCase::no_refinement=*/0);
2133
2134 if (tetraheder_in_mesh)
2135 {
2136 tria_level.refine_choice.reserve(total_cells);
2137 tria_level.refine_choice.insert(
2138 tria_level.refine_choice.end(),
2139 total_cells - tria_level.refine_choice.size(),
2140 static_cast<char>(
2142 }
2143
2144 tria_level.coarsen_flags.reserve(total_cells);
2145 tria_level.coarsen_flags.insert(tria_level.coarsen_flags.end(),
2146 total_cells -
2147 tria_level.coarsen_flags.size(),
2148 false);
2149
2150 tria_level.active_cell_indices.reserve(total_cells);
2151 tria_level.active_cell_indices.insert(
2152 tria_level.active_cell_indices.end(),
2153 total_cells - tria_level.active_cell_indices.size(),
2155
2156 tria_level.subdomain_ids.reserve(total_cells);
2157 tria_level.subdomain_ids.insert(tria_level.subdomain_ids.end(),
2158 total_cells -
2159 tria_level.subdomain_ids.size(),
2160 0);
2161
2162 tria_level.level_subdomain_ids.reserve(total_cells);
2163 tria_level.level_subdomain_ids.insert(
2164 tria_level.level_subdomain_ids.end(),
2165 total_cells - tria_level.level_subdomain_ids.size(),
2166 0);
2167
2168 tria_level.global_active_cell_indices.reserve(total_cells);
2169 tria_level.global_active_cell_indices.insert(
2170 tria_level.global_active_cell_indices.end(),
2171 total_cells - tria_level.global_active_cell_indices.size(),
2173
2174 tria_level.global_level_cell_indices.reserve(total_cells);
2175 tria_level.global_level_cell_indices.insert(
2176 tria_level.global_level_cell_indices.end(),
2177 total_cells - tria_level.global_level_cell_indices.size(),
2179
2180 if (dim == space_dimension - 1)
2181 {
2182 tria_level.direction_flags.reserve(total_cells);
2183 tria_level.direction_flags.insert(
2184 tria_level.direction_flags.end(),
2185 total_cells - tria_level.direction_flags.size(),
2186 true);
2187 }
2188 else
2189 tria_level.direction_flags.clear();
2190
2191 tria_level.parents.reserve((total_cells + 1) / 2);
2192 tria_level.parents.insert(tria_level.parents.end(),
2193 (total_cells + 1) / 2 -
2194 tria_level.parents.size(),
2195 -1);
2196
2197 tria_level.neighbors.reserve(total_cells * max_n_faces(dim));
2198 tria_level.neighbors.insert(tria_level.neighbors.end(),
2199 total_cells * max_n_faces(dim) -
2200 tria_level.neighbors.size(),
2201 std::make_pair(-1, -1));
2202
2203 if (dim == 2 || dim == 3)
2204 {
2205 tria_level.face_orientations.resize(total_cells *
2206 max_n_faces(dim));
2207
2208 tria_level.reference_cell.reserve(total_cells);
2209 tria_level.reference_cell.insert(
2210 tria_level.reference_cell.end(),
2211 total_cells - tria_level.reference_cell.size(),
2214 }
2215 }
2216 }
2217
2218
2219
2224 int,
2225 int,
2226 << "The containers have sizes " << arg1 << " and " << arg2
2227 << ", which is not as expected.");
2228
2234 void
2235 monitor_memory(const TriaLevel &tria_level,
2236 const unsigned int true_dimension)
2237 {
2238 Assert(2 * true_dimension * tria_level.refine_flags.size() ==
2239 tria_level.neighbors.size(),
2240 ExcMemoryInexact(tria_level.refine_flags.size(),
2241 tria_level.neighbors.size()));
2242 Assert(2 * true_dimension * tria_level.coarsen_flags.size() ==
2243 tria_level.neighbors.size(),
2244 ExcMemoryInexact(tria_level.coarsen_flags.size(),
2245 tria_level.neighbors.size()));
2246 }
2247
2248
2249
2262 void
2264 const unsigned int new_objects_in_pairs,
2265 const unsigned int new_objects_single = 0)
2266 {
2267 if (tria_objects.structdim <= 2)
2268 {
2269 Assert(new_objects_in_pairs % 2 == 0, ExcInternalError());
2270
2271 tria_objects.next_free_single = 0;
2272 tria_objects.next_free_pair = 0;
2273 tria_objects.reverse_order_next_free_single = false;
2274
2275 // count the number of objects, of unused single objects and of
2276 // unused pairs of objects
2277 [[maybe_unused]] unsigned int n_objects = 0;
2278 unsigned int n_unused_pairs = 0;
2279 unsigned int n_unused_singles = 0;
2280 for (unsigned int i = 0; i < tria_objects.used.size(); ++i)
2281 {
2282 if (tria_objects.used[i])
2283 ++n_objects;
2284 else if (i + 1 < tria_objects.used.size())
2285 {
2286 if (tria_objects.used[i + 1])
2287 {
2288 ++n_unused_singles;
2289 if (tria_objects.next_free_single == 0)
2290 tria_objects.next_free_single = i;
2291 }
2292 else
2293 {
2294 ++n_unused_pairs;
2295 if (tria_objects.next_free_pair == 0)
2296 tria_objects.next_free_pair = i;
2297 ++i;
2298 }
2299 }
2300 else
2301 ++n_unused_singles;
2302 }
2303 Assert(n_objects + 2 * n_unused_pairs + n_unused_singles ==
2304 tria_objects.used.size(),
2306
2307 // how many single objects are needed in addition to
2308 // n_unused_objects?
2309 const int additional_single_objects =
2310 new_objects_single - n_unused_singles;
2311
2312 unsigned int new_size = tria_objects.used.size() +
2313 new_objects_in_pairs - 2 * n_unused_pairs;
2314 if (additional_single_objects > 0)
2315 new_size += additional_single_objects;
2316
2317 // only allocate space if necessary
2318 if (new_size > tria_objects.n_objects())
2319 {
2320 const unsigned int max_children_per_cell =
2321 1 << tria_objects.structdim;
2322
2323 tria_objects.cells.reserve(new_size *
2324 max_n_faces(tria_objects.structdim));
2325 tria_objects.cells.insert(tria_objects.cells.end(),
2326 (new_size - tria_objects.n_objects()) *
2327 max_n_faces(tria_objects.structdim),
2328 -1);
2329
2330 tria_objects.used.reserve(new_size);
2331 tria_objects.used.insert(tria_objects.used.end(),
2332 new_size - tria_objects.used.size(),
2333 false);
2334
2335 tria_objects.user_flags.reserve(new_size);
2336 tria_objects.user_flags.insert(tria_objects.user_flags.end(),
2337 new_size -
2338 tria_objects.user_flags.size(),
2339 false);
2340
2341 const unsigned int factor = max_children_per_cell / 2;
2342 tria_objects.children.reserve(factor * new_size);
2343 tria_objects.children.insert(tria_objects.children.end(),
2344 factor * new_size -
2345 tria_objects.children.size(),
2346 -1);
2347
2348 if (tria_objects.structdim > 1)
2349 {
2350 tria_objects.refinement_cases.reserve(new_size);
2351 tria_objects.refinement_cases.insert(
2352 tria_objects.refinement_cases.end(),
2353 new_size - tria_objects.refinement_cases.size(),
2354 /*RefinementCase::no_refinement=*/0);
2355 }
2356
2357 // first reserve, then resize. Otherwise the std library can
2358 // decide to allocate more entries.
2359 tria_objects.boundary_or_material_id.reserve(new_size);
2360 tria_objects.boundary_or_material_id.resize(new_size);
2361
2362 tria_objects.user_data.reserve(new_size);
2363 tria_objects.user_data.resize(new_size);
2364
2365 tria_objects.manifold_id.reserve(new_size);
2366 tria_objects.manifold_id.insert(tria_objects.manifold_id.end(),
2367 new_size -
2368 tria_objects.manifold_id.size(),
2370 }
2371
2372 if (n_unused_singles == 0)
2373 {
2374 tria_objects.next_free_single = new_size - 1;
2375 tria_objects.reverse_order_next_free_single = true;
2376 }
2377 }
2378 else
2379 {
2380 const unsigned int new_hexes = new_objects_in_pairs;
2381
2382 const unsigned int new_size =
2383 new_hexes + std::count(tria_objects.used.begin(),
2384 tria_objects.used.end(),
2385 true);
2386
2387 // see above...
2388 if (new_size > tria_objects.n_objects())
2389 {
2390 tria_objects.cells.reserve(new_size *
2391 max_n_faces(tria_objects.structdim));
2392 tria_objects.cells.insert(tria_objects.cells.end(),
2393 (new_size - tria_objects.n_objects()) *
2394 max_n_faces(tria_objects.structdim),
2395 -1);
2396
2397 tria_objects.used.reserve(new_size);
2398 tria_objects.used.insert(tria_objects.used.end(),
2399 new_size - tria_objects.used.size(),
2400 false);
2401
2402 tria_objects.user_flags.reserve(new_size);
2403 tria_objects.user_flags.insert(tria_objects.user_flags.end(),
2404 new_size -
2405 tria_objects.user_flags.size(),
2406 false);
2407
2408 tria_objects.children.reserve(4 * new_size);
2409 tria_objects.children.insert(tria_objects.children.end(),
2410 4 * new_size -
2411 tria_objects.children.size(),
2412 -1);
2413
2414 // for the following fields, we know exactly how many elements
2415 // we need, so first reserve then resize (resize itself, at least
2416 // with some compiler libraries, appears to round up the size it
2417 // actually reserves)
2418 tria_objects.boundary_or_material_id.reserve(new_size);
2419 tria_objects.boundary_or_material_id.resize(new_size);
2420
2421 tria_objects.manifold_id.reserve(new_size);
2422 tria_objects.manifold_id.insert(tria_objects.manifold_id.end(),
2423 new_size -
2424 tria_objects.manifold_id.size(),
2426
2427 tria_objects.user_data.reserve(new_size);
2428 tria_objects.user_data.resize(new_size);
2429
2430 tria_objects.refinement_cases.reserve(new_size);
2431 tria_objects.refinement_cases.insert(
2432 tria_objects.refinement_cases.end(),
2433 new_size - tria_objects.refinement_cases.size(),
2434 /*RefinementCase::no_refinement=*/0);
2435 }
2436 tria_objects.next_free_single = tria_objects.next_free_pair = 0;
2437 }
2438 }
2439
2440
2441
2447 void
2448 monitor_memory(const TriaObjects &tria_object, const unsigned int)
2449 {
2450 Assert(tria_object.n_objects() == tria_object.used.size(),
2451 ExcMemoryInexact(tria_object.n_objects(),
2452 tria_object.used.size()));
2453 Assert(tria_object.n_objects() == tria_object.user_flags.size(),
2454 ExcMemoryInexact(tria_object.n_objects(),
2455 tria_object.user_flags.size()));
2456 Assert(tria_object.n_objects() ==
2457 tria_object.boundary_or_material_id.size(),
2458 ExcMemoryInexact(tria_object.n_objects(),
2459 tria_object.boundary_or_material_id.size()));
2460 Assert(tria_object.n_objects() == tria_object.manifold_id.size(),
2461 ExcMemoryInexact(tria_object.n_objects(),
2462 tria_object.manifold_id.size()));
2463 Assert(tria_object.n_objects() == tria_object.user_data.size(),
2464 ExcMemoryInexact(tria_object.n_objects(),
2465 tria_object.user_data.size()));
2466
2467 if (tria_object.structdim == 1)
2468 {
2469 Assert(1 * tria_object.n_objects() == tria_object.children.size(),
2470 ExcMemoryInexact(tria_object.n_objects(),
2471 tria_object.children.size()));
2472 }
2473 else if (tria_object.structdim == 2)
2474 {
2475 Assert(2 * tria_object.n_objects() == tria_object.children.size(),
2476 ExcMemoryInexact(tria_object.n_objects(),
2477 tria_object.children.size()));
2478 }
2479 else if (tria_object.structdim == 3)
2480 {
2481 Assert(4 * tria_object.n_objects() == tria_object.children.size(),
2482 ExcMemoryInexact(tria_object.n_objects(),
2483 tria_object.children.size()));
2484 }
2485 }
2486
2487
2488
2493 template <int dim, int spacedim>
2495 {
2496 public:
2500 virtual ~Policy() = default;
2501
2505 virtual void
2507
2511 virtual void
2515 std::vector<unsigned int> &line_cell_count,
2516 std::vector<unsigned int> &quad_cell_count) = 0;
2517
2523 const bool check_for_distorted_cells) = 0;
2524
2528 virtual void
2531
2535 virtual void
2538
2542 virtual bool
2544 const typename Triangulation<dim, spacedim>::cell_iterator &cell) = 0;
2545
2552 virtual std::unique_ptr<Policy<dim, spacedim>>
2553 clone() = 0;
2554 };
2555
2556
2557
2563 template <int dim, int spacedim, typename T>
2564 class PolicyWrapper : public Policy<dim, spacedim>
2565 {
2566 public:
2567 void
2569 {
2570 T::update_neighbors(tria);
2571 }
2572
2573 void
2577 std::vector<unsigned int> &line_cell_count,
2578 std::vector<unsigned int> &quad_cell_count) override
2579 {
2580 T::delete_children(tria, cell, line_cell_count, quad_cell_count);
2581 }
2582
2585 const bool check_for_distorted_cells) override
2586 {
2587 return T::execute_refinement(triangulation, check_for_distorted_cells);
2588 }
2589
2590 void
2593 {
2594 T::prevent_distorted_boundary_cells(triangulation);
2595 }
2596
2597 void
2600 {
2601 T::prepare_refinement_dim_dependent(triangulation);
2602 }
2603
2604 bool
2607 override
2608 {
2609 return T::template coarsening_allowed<dim, spacedim>(cell);
2610 }
2611
2612 std::unique_ptr<Policy<dim, spacedim>>
2613 clone() override
2614 {
2615 return std::make_unique<PolicyWrapper<dim, spacedim, T>>();
2616 }
2617 };
2618
2619
2620
2717 {
2729 template <int dim, int spacedim>
2730 static void
2733 const unsigned int level_objects,
2735 {
2736 using line_iterator =
2738
2739 number_cache.n_levels = 0;
2740 if (level_objects > 0)
2741 // find the last level on which there are used cells
2742 for (unsigned int level = 0; level < level_objects; ++level)
2743 if (triangulation.begin(level) != triangulation.end(level))
2744 number_cache.n_levels = level + 1;
2745
2746 // no cells at all?
2747 Assert(number_cache.n_levels > 0, ExcInternalError());
2748
2749 //---------------------------------
2750 // update the number of lines on the different levels in the
2751 // cache
2752 number_cache.n_lines = 0;
2753 number_cache.n_active_lines = 0;
2754
2755 // for 1d, lines have levels so take count the objects per
2756 // level and globally
2757 if (dim == 1)
2758 {
2759 number_cache.n_lines_level.resize(number_cache.n_levels);
2760 number_cache.n_active_lines_level.resize(number_cache.n_levels);
2761
2762 for (unsigned int level = 0; level < number_cache.n_levels; ++level)
2763 {
2764 // count lines on this level
2765 number_cache.n_lines_level[level] = 0;
2766 number_cache.n_active_lines_level[level] = 0;
2767
2768 line_iterator line = triangulation.begin_line(level),
2769 endc =
2770 (level == number_cache.n_levels - 1 ?
2771 line_iterator(triangulation.end_line()) :
2772 triangulation.begin_line(level + 1));
2773 for (; line != endc; ++line)
2774 {
2775 ++number_cache.n_lines_level[level];
2776 if (line->has_children() == false)
2777 ++number_cache.n_active_lines_level[level];
2778 }
2779
2780 // update total number of lines
2781 number_cache.n_lines += number_cache.n_lines_level[level];
2782 number_cache.n_active_lines +=
2783 number_cache.n_active_lines_level[level];
2784 }
2785 }
2786 else
2787 {
2788 // for dim>1, there are no levels for lines
2789 number_cache.n_lines_level.clear();
2790 number_cache.n_active_lines_level.clear();
2791
2792 line_iterator line = triangulation.begin_line(),
2793 endc = triangulation.end_line();
2794 for (; line != endc; ++line)
2795 {
2796 ++number_cache.n_lines;
2797 if (line->has_children() == false)
2798 ++number_cache.n_active_lines;
2799 }
2800 }
2801 }
2802
2817 template <int dim, int spacedim>
2818 static void
2821 const unsigned int level_objects,
2823 {
2824 // update lines and n_levels in number_cache. since we don't
2825 // access any of these numbers, we can do this in the
2826 // background
2828 static_cast<
2829 void (*)(const Triangulation<dim, spacedim> &,
2830 const unsigned int,
2832 &compute_number_cache_dim<dim, spacedim>),
2834 level_objects,
2836 number_cache));
2837
2838 using quad_iterator =
2840
2841 //---------------------------------
2842 // update the number of quads on the different levels in the
2843 // cache
2844 number_cache.n_quads = 0;
2845 number_cache.n_active_quads = 0;
2846
2847 // for 2d, quads have levels so take count the objects per
2848 // level and globally
2849 if (dim == 2)
2850 {
2851 // count the number of levels; the function we called above
2852 // on a separate Task for lines also does this and puts it into
2853 // number_cache.n_levels, but this datum may not yet be
2854 // available as we call the function on a separate task
2855 unsigned int n_levels = 0;
2856 if (level_objects > 0)
2857 // find the last level on which there are used cells
2858 for (unsigned int level = 0; level < level_objects; ++level)
2859 if (triangulation.begin(level) != triangulation.end(level))
2860 n_levels = level + 1;
2861
2862 number_cache.n_quads_level.resize(n_levels);
2863 number_cache.n_active_quads_level.resize(n_levels);
2864
2865 for (unsigned int level = 0; level < n_levels; ++level)
2866 {
2867 // count quads on this level
2868 number_cache.n_quads_level[level] = 0;
2869 number_cache.n_active_quads_level[level] = 0;
2870
2871 quad_iterator quad = triangulation.begin_quad(level),
2872 endc =
2873 (level == n_levels - 1 ?
2874 quad_iterator(triangulation.end_quad()) :
2875 triangulation.begin_quad(level + 1));
2876 for (; quad != endc; ++quad)
2877 {
2878 ++number_cache.n_quads_level[level];
2879 if (quad->has_children() == false)
2880 ++number_cache.n_active_quads_level[level];
2881 }
2882
2883 // update total number of quads
2884 number_cache.n_quads += number_cache.n_quads_level[level];
2885 number_cache.n_active_quads +=
2886 number_cache.n_active_quads_level[level];
2887 }
2888 }
2889 else
2890 {
2891 // for dim>2, there are no levels for quads
2892 number_cache.n_quads_level.clear();
2893 number_cache.n_active_quads_level.clear();
2894
2895 quad_iterator quad = triangulation.begin_quad(),
2896 endc = triangulation.end_quad();
2897 for (; quad != endc; ++quad)
2898 {
2899 ++number_cache.n_quads;
2900 if (quad->has_children() == false)
2901 ++number_cache.n_active_quads;
2902 }
2903 }
2904
2905 // wait for the background computation for lines
2906 update_lines.join();
2907 }
2908
2924 template <int dim, int spacedim>
2925 static void
2928 const unsigned int level_objects,
2930 {
2931 // update quads, lines and n_levels in number_cache. since we
2932 // don't access any of these numbers, we can do this in the
2933 // background
2934 Threads::Task<void> update_quads_and_lines = Threads::new_task(
2935 static_cast<
2936 void (*)(const Triangulation<dim, spacedim> &,
2937 const unsigned int,
2939 &compute_number_cache_dim<dim, spacedim>),
2941 level_objects,
2943 number_cache));
2944
2945 using hex_iterator =
2947
2948 //---------------------------------
2949 // update the number of hexes on the different levels in the
2950 // cache
2951 number_cache.n_hexes = 0;
2952 number_cache.n_active_hexes = 0;
2953
2954 // for 3d, hexes have levels so take count the objects per
2955 // level and globally
2956 if (dim == 3)
2957 {
2958 // count the number of levels; the function we called
2959 // above on a separate Task for quads (recursively, via
2960 // the lines function) also does this and puts it into
2961 // number_cache.n_levels, but this datum may not yet be
2962 // available as we call the function on a separate task
2963 unsigned int n_levels = 0;
2964 if (level_objects > 0)
2965 // find the last level on which there are used cells
2966 for (unsigned int level = 0; level < level_objects; ++level)
2967 if (triangulation.begin(level) != triangulation.end(level))
2968 n_levels = level + 1;
2969
2970 number_cache.n_hexes_level.resize(n_levels);
2971 number_cache.n_active_hexes_level.resize(n_levels);
2972
2973 for (unsigned int level = 0; level < n_levels; ++level)
2974 {
2975 // count hexes on this level
2976 number_cache.n_hexes_level[level] = 0;
2977 number_cache.n_active_hexes_level[level] = 0;
2978
2979 hex_iterator hex = triangulation.begin_hex(level),
2980 endc = (level == n_levels - 1 ?
2981 hex_iterator(triangulation.end_hex()) :
2982 triangulation.begin_hex(level + 1));
2983 for (; hex != endc; ++hex)
2984 {
2985 ++number_cache.n_hexes_level[level];
2986 if (hex->has_children() == false)
2987 ++number_cache.n_active_hexes_level[level];
2988 }
2989
2990 // update total number of hexes
2991 number_cache.n_hexes += number_cache.n_hexes_level[level];
2992 number_cache.n_active_hexes +=
2993 number_cache.n_active_hexes_level[level];
2994 }
2995 }
2996 else
2997 {
2998 // for dim>3, there are no levels for hexes
2999 number_cache.n_hexes_level.clear();
3000 number_cache.n_active_hexes_level.clear();
3001
3002 hex_iterator hex = triangulation.begin_hex(),
3003 endc = triangulation.end_hex();
3004 for (; hex != endc; ++hex)
3005 {
3006 ++number_cache.n_hexes;
3007 if (hex->has_children() == false)
3008 ++number_cache.n_active_hexes;
3009 }
3010 }
3011
3012 // wait for the background computation for quads
3013 update_quads_and_lines.join();
3014 }
3015
3016
3017 template <int dim, int spacedim>
3018 static void
3021 const unsigned int level_objects,
3023 {
3024 compute_number_cache_dim(triangulation, level_objects, number_cache);
3025
3026 number_cache.active_cell_index_partitioner =
3027 std::make_shared<const Utilities::MPI::Partitioner>(
3028 triangulation.n_active_cells());
3029
3030 number_cache.level_cell_index_partitioners.resize(
3031 triangulation.n_levels());
3032 for (unsigned int level = 0; level < triangulation.n_levels(); ++level)
3033 number_cache.level_cell_index_partitioners[level] =
3034 std::make_shared<const Utilities::MPI::Partitioner>(
3035 triangulation.n_cells(level));
3036 }
3037
3038
3039 template <int spacedim>
3040 static void
3043
3044
3045 template <int dim, int spacedim>
3046 static void
3048 {
3049 // each face can be neighbored on two sides
3050 // by cells. according to the face's
3051 // intrinsic normal we define the left
3052 // neighbor as the one for which the face
3053 // normal points outward, and store that
3054 // one first; the second one is then
3055 // the right neighbor for which the
3056 // face normal points inward. This
3057 // information depends on the type of cell
3058 // and local number of face for the
3059 // 'standard ordering and orientation' of
3060 // faces and then on the face_orientation
3061 // information for the real mesh. Set up a
3062 // table to have fast access to those
3063 // offsets (0 for left and 1 for
3064 // right). Some of the values are invalid
3065 // as they reference too large face
3066 // numbers, but we just leave them at a
3067 // zero value.
3068 //
3069 // Note, that in 2d for lines as faces the
3070 // normal direction given in the
3071 // GeometryInfo class is not consistent. We
3072 // thus define here that the normal for a
3073 // line points to the right if the line
3074 // points upwards.
3075 //
3076 // There is one more point to
3077 // consider, however: if we have
3078 // dim<spacedim, then we may have
3079 // cases where cells are
3080 // inverted. In effect, both
3081 // cells think they are the left
3082 // neighbor of an edge, for
3083 // example, which leads us to
3084 // forget neighborship
3085 // information (a case that shows
3086 // this is
3087 // codim_one/hanging_nodes_02). We
3088 // store whether a cell is
3089 // inverted using the
3090 // direction_flag, so if a cell
3091 // has a false direction_flag,
3092 // then we need to invert our
3093 // selection whether we are a
3094 // left or right neighbor in all
3095 // following computations.
3096 //
3097 // first index: dimension (minus 2)
3098 // second index: local face index
3099 // third index: face_orientation (false and true)
3100 static const unsigned int left_right_offset[2][6][2] = {
3101 // quadrilateral
3102 {{0, 1}, // face 0, face_orientation = false and true
3103 {1, 0}, // face 1, face_orientation = false and true
3104 {1, 0}, // face 2, face_orientation = false and true
3105 {0, 1}, // face 3, face_orientation = false and true
3106 {0, 0}, // face 4, invalid face
3107 {0, 0}}, // face 5, invalid face
3108 // hexahedron
3109 {{0, 1}, {1, 0}, {0, 1}, {1, 0}, {0, 1}, {1, 0}}};
3110
3111 // now create a vector of the two active
3112 // neighbors (left and right) for each face
3113 // and fill it by looping over all cells. For
3114 // cases with anisotropic refinement and more
3115 // then one cell neighboring at a given side
3116 // of the face we will automatically get the
3117 // active one on the highest level as we loop
3118 // over cells from lower levels first.
3120 std::vector<typename Triangulation<dim, spacedim>::cell_iterator>
3121 adjacent_cells(2 * triangulation.n_raw_faces(), dummy);
3122
3123 for (const auto &cell : triangulation.cell_iterators())
3124 for (auto f : cell->face_indices())
3125 {
3127 cell->face(f);
3128
3129 const unsigned int offset =
3130 (cell->direction_flag() ?
3131 left_right_offset[dim - 2][f][cell->face_orientation(f)] :
3132 1 -
3133 left_right_offset[dim - 2][f][cell->face_orientation(f)]);
3134
3135 adjacent_cells[2 * face->index() + offset] = cell;
3136
3137 // if this cell is not refined, but the
3138 // face is, then we'll have to set our
3139 // cell as neighbor for the child faces
3140 // as well. Fortunately the normal
3141 // orientation of children will be just
3142 // the same.
3143 if (dim == 2)
3144 {
3145 if (cell->is_active() && face->has_children())
3146 {
3147 adjacent_cells[2 * face->child(0)->index() + offset] =
3148 cell;
3149 adjacent_cells[2 * face->child(1)->index() + offset] =
3150 cell;
3151 }
3152 }
3153 else // -> dim == 3
3154 {
3155 // We need the same as in 2d
3156 // here. Furthermore, if the face is
3157 // refined with cut_x or cut_y then
3158 // those children again in the other
3159 // direction, and if this cell is
3160 // refined isotropically (along the
3161 // face) then the neighbor will
3162 // (probably) be refined as cut_x or
3163 // cut_y along the face. For those
3164 // neighboring children cells, their
3165 // neighbor will be the current,
3166 // inactive cell, as our children are
3167 // too fine to be neighbors. Catch that
3168 // case by also acting on inactive
3169 // cells with isotropic refinement
3170 // along the face. If the situation
3171 // described is not present, the data
3172 // will be overwritten later on when we
3173 // visit cells on finer levels, so no
3174 // harm will be done.
3175 if (face->has_children() &&
3176 (cell->is_active() ||
3178 cell->refinement_case(), f) ==
3180 {
3181 for (unsigned int c = 0; c < face->n_children(); ++c)
3182 adjacent_cells[2 * face->child(c)->index() + offset] =
3183 cell;
3184 if (face->child(0)->has_children())
3185 {
3186 adjacent_cells[2 * face->child(0)->child(0)->index() +
3187 offset] = cell;
3188 adjacent_cells[2 * face->child(0)->child(1)->index() +
3189 offset] = cell;
3190 }
3191 if (face->child(1)->has_children())
3192 {
3193 adjacent_cells[2 * face->child(1)->child(0)->index() +
3194 offset] = cell;
3195 adjacent_cells[2 * face->child(1)->child(1)->index() +
3196 offset] = cell;
3197 }
3198 } // if cell active and face refined
3199 } // else -> dim==3
3200 } // for all faces of all cells
3201
3202 // now loop again over all cells and set the
3203 // corresponding neighbor cell. Note, that we
3204 // have to use the opposite of the
3205 // left_right_offset in this case as we want
3206 // the offset of the neighbor, not our own.
3207 for (const auto &cell : triangulation.cell_iterators())
3208 for (auto f : cell->face_indices())
3209 {
3210 const unsigned int offset =
3211 (cell->direction_flag() ?
3212 left_right_offset[dim - 2][f][cell->face_orientation(f)] :
3213 1 -
3214 left_right_offset[dim - 2][f][cell->face_orientation(f)]);
3215 cell->set_neighbor(
3216 f, adjacent_cells[2 * cell->face(f)->index() + 1 - offset]);
3217 }
3218 }
3219
3220
3224 template <int dim, int spacedim>
3225 static void
3226 create_triangulation(const std::vector<Point<spacedim>> &vertices,
3227 const std::vector<CellData<dim>> &cells,
3228 const SubCellData &subcelldata,
3230 {
3231 AssertThrow(vertices.size() > 0, ExcMessage("No vertices given"));
3232 AssertThrow(cells.size() > 0, ExcMessage("No cells given"));
3233
3234 // Check that all cells have positive volume.
3235#ifndef _MSC_VER
3236 // TODO: The following code does not compile with MSVC. Find a way
3237 // around it
3238 if (dim == spacedim)
3239 for (unsigned int cell_no = 0; cell_no < cells.size(); ++cell_no)
3240 {
3241 // If we should check for distorted cells, then we permit them
3242 // to exist. If a cell has negative measure, then it must be
3243 // distorted (the converse is not necessarily true); hence
3244 // throw an exception if no such cells should exist.
3246 {
3247 const double cell_measure = GridTools::cell_measure<spacedim>(
3248 vertices,
3249 ArrayView<const unsigned int>(cells[cell_no].vertices));
3250 AssertThrow(cell_measure > 0, ExcGridHasInvalidCell(cell_no));
3251 }
3252 }
3253#endif
3254
3255 // clear old content
3256 tria.levels.clear();
3257 tria.levels.push_back(
3258 std::make_unique<
3260
3261 if (dim > 1)
3262 tria.faces = std::make_unique<
3264
3265 // copy vertices
3266 tria.vertices = vertices;
3267 tria.vertices_used.assign(vertices.size(), true);
3268
3269 // compute connectivity
3270 const auto connectivity = build_connectivity<unsigned int>(cells);
3271 const unsigned int n_cell = cells.size();
3272
3273 // TriaObjects: lines
3274 if (dim >= 2)
3275 {
3276 auto &lines_0 = tria.faces->lines; // data structure to be filled
3277
3278 // get connectivity between quads and lines
3279 const auto &crs = connectivity.entity_to_entities(1, 0);
3280 const unsigned int n_lines = crs.ptr.size() - 1;
3281
3282 // allocate memory
3283 reserve_space_(lines_0, n_lines);
3284
3285 // loop over lines
3286 for (unsigned int line = 0; line < n_lines; ++line)
3287 for (unsigned int i = crs.ptr[line], j = 0; i < crs.ptr[line + 1];
3288 ++i, ++j)
3289 lines_0.cells[line * ReferenceCells::max_n_faces<1>() + j] =
3290 crs.col[i]; // set vertex indices
3291 }
3292
3293 // TriaObjects: quads
3294 if (dim == 3)
3295 {
3296 auto &quads_0 = tria.faces->quads; // data structures to be filled
3297 auto &faces = *tria.faces;
3298
3299 // get connectivity between quads and lines
3300 const auto &crs = connectivity.entity_to_entities(2, 1);
3301 const unsigned int n_quads = crs.ptr.size() - 1;
3302
3303 // allocate memory
3304 reserve_space_(quads_0, n_quads);
3305 reserve_space_(faces, 2 /*structdim*/, n_quads);
3306
3307 // loop over all quads -> entity type, line indices/orientations
3308 for (unsigned int q = 0, k = 0; q < n_quads; ++q)
3309 {
3310 // set entity type of quads
3311 const auto reference_cell = connectivity.entity_types(2)[q];
3312 faces.set_quad_type(q, reference_cell);
3313
3314 // loop over all its lines
3315 for (unsigned int i = crs.ptr[q], j = 0; i < crs.ptr[q + 1];
3316 ++i, ++j, ++k)
3317 {
3318 AssertIndexRange(j, reference_cell.n_lines());
3319 // set line index
3320 quads_0.cells[q * ReferenceCells::max_n_lines<2>() + j] =
3321 crs.col[i];
3322
3323 // set line orientations
3324 const auto combined_orientation =
3325 connectivity.entity_orientations(1)
3326 .get_combined_orientation(k);
3327 // it doesn't make sense to set any flags except
3328 // orientation for a line
3329 Assert(combined_orientation ==
3331 combined_orientation ==
3334 // Same convention as TriaAccessor::set_line_orientation():
3335 // store true for the default orientation and false for
3336 // reversed.
3337 faces.quads_line_orientations
3338 [q * ReferenceCells::max_n_lines<2>() + j] =
3339 combined_orientation ==
3341 }
3342 }
3343 }
3344
3345 // TriaObjects/TriaLevel: cell
3346 {
3347 auto &cells_0 = tria.levels[0]->cells; // data structure to be filled
3348 auto &level = *tria.levels[0];
3349
3350 // get connectivity between cells/faces and cells/cells
3351 const auto &crs = connectivity.entity_to_entities(dim, dim - 1);
3352 const auto &nei = connectivity.entity_to_entities(dim, dim);
3353
3354 // in 2d optional: since in in pure QUAD meshes same line
3355 // orientations can be guaranteed
3356 bool orientation_needed = false;
3357 if (dim == 3)
3358 orientation_needed = true;
3359 else if (dim == 2)
3360 {
3361 const auto &orientations = connectivity.entity_orientations(1);
3362 for (unsigned int i = 0; i < orientations.n_objects(); ++i)
3363 if (orientations.get_combined_orientation(i) !=
3365 {
3366 orientation_needed = true;
3367 break;
3368 }
3369 }
3370
3371 // allocate memory
3372 reserve_space_(cells_0, n_cell);
3373 reserve_space_(level, spacedim, n_cell, orientation_needed);
3374
3375 // loop over all cells
3376 for (unsigned int cell = 0; cell < n_cell; ++cell)
3377 {
3378 // set material ids
3379 cells_0.boundary_or_material_id[cell].material_id =
3380 cells[cell].material_id;
3381
3382 // set manifold ids
3383 cells_0.manifold_id[cell] = cells[cell].manifold_id;
3384
3385 // set entity types
3386 level.reference_cell[cell] = connectivity.entity_types(dim)[cell];
3387
3388 // loop over faces
3389 for (unsigned int i = crs.ptr[cell], j = 0; i < crs.ptr[cell + 1];
3390 ++i, ++j)
3391 {
3392 // set neighbor if not at boundary
3393 if (nei.col[i] != static_cast<unsigned int>(-1))
3394 level.neighbors[cell * ReferenceCells::max_n_faces<dim>() +
3395 j] = {0, nei.col[i]};
3396
3397 // set face indices
3398 cells_0.cells[cell * ReferenceCells::max_n_faces<dim>() + j] =
3399 crs.col[i];
3400
3401 // set face orientation if needed
3402 if (orientation_needed)
3403 {
3404 level.face_orientations.set_combined_orientation(
3405 cell * ReferenceCells::max_n_faces<dim>() + j,
3406 connectivity.entity_orientations(dim - 1)
3407 .get_combined_orientation(i));
3408 }
3409 }
3410 }
3411 }
3412
3413 // TriaFaces: boundary id of boundary faces
3414 if (dim > 1)
3415 {
3416 auto &bids_face = dim == 3 ?
3417 tria.faces->quads.boundary_or_material_id :
3418 tria.faces->lines.boundary_or_material_id;
3419
3420 // count number of cells a face is belonging to
3421 std::vector<unsigned int> count(bids_face.size(), 0);
3422
3423 // get connectivity between cells/faces
3424 const auto &crs = connectivity.entity_to_entities(dim, dim - 1);
3425
3426 // count how many cells are adjacent to the same face
3427 for (unsigned int cell = 0; cell < cells.size(); ++cell)
3428 for (unsigned int i = crs.ptr[cell]; i < crs.ptr[cell + 1]; ++i)
3429 count[crs.col[i]]++;
3430
3431 // loop over all faces
3432 for (unsigned int face = 0; face < count.size(); ++face)
3433 {
3434 if (count[face] != 1) // inner face
3435 continue;
3436
3437 // boundary faces ...
3438 bids_face[face].boundary_id = 0;
3439
3440 if (dim != 3)
3441 continue;
3442
3443 // ... and the lines of quads in 3d
3444 const auto &crs = connectivity.entity_to_entities(2, 1);
3445 for (unsigned int i = crs.ptr[face]; i < crs.ptr[face + 1]; ++i)
3446 tria.faces->lines.boundary_or_material_id[crs.col[i]]
3447 .boundary_id = 0;
3448 }
3449 }
3450 else // 1d
3451 {
3452 static const unsigned int t_tba = static_cast<unsigned int>(-1);
3453 static const unsigned int t_inner = static_cast<unsigned int>(-2);
3454
3455 std::vector<unsigned int> type(vertices.size(), t_tba);
3456
3457 const auto &crs = connectivity.entity_to_entities(1, 0);
3458
3459 for (unsigned int cell = 0; cell < cells.size(); ++cell)
3460 for (unsigned int i = crs.ptr[cell], j = 0; i < crs.ptr[cell + 1];
3461 ++i, ++j)
3462 if (type[crs.col[i]] != t_inner)
3463 type[crs.col[i]] = type[crs.col[i]] == t_tba ? j : t_inner;
3464
3465 for (unsigned int face = 0; face < type.size(); ++face)
3466 {
3467 // note: we also treat manifolds here!?
3468 (*tria.vertex_to_manifold_id_map_1d)[face] =
3470 if (type[face] != t_inner && type[face] != t_tba)
3471 (*tria.vertex_to_boundary_id_map_1d)[face] = type[face];
3472 }
3473 }
3474
3475 // SubCellData: line
3476 if (dim >= 2)
3477 process_subcelldata(connectivity.entity_to_entities(1, 0),
3478 tria.faces->lines,
3479 subcelldata.boundary_lines,
3480 vertices);
3481
3482 // SubCellData: quad
3483 if (dim == 3)
3484 process_subcelldata(connectivity.entity_to_entities(2, 0),
3485 tria.faces->quads,
3486 subcelldata.boundary_quads,
3487 vertices);
3488 }
3489
3490
3491 template <int structdim, int spacedim, typename T>
3492 static void
3494 const CRS<T> &crs,
3495 TriaObjects &obj,
3496 const std::vector<CellData<structdim>> &boundary_objects_in,
3497 const std::vector<Point<spacedim>> &vertex_locations)
3498 {
3499 AssertDimension(obj.structdim, structdim);
3500
3501 if (boundary_objects_in.empty())
3502 return; // empty subcelldata -> nothing to do
3503
3504 // pre-sort subcelldata
3505 auto boundary_objects = boundary_objects_in;
3506
3507 // ... sort vertices
3508 for (auto &boundary_object : boundary_objects)
3509 std::sort(boundary_object.vertices.begin(),
3510 boundary_object.vertices.end());
3511
3512 // ... sort cells
3513 std::sort(boundary_objects.begin(),
3514 boundary_objects.end(),
3515 [](const auto &a, const auto &b) {
3516 return a.vertices < b.vertices;
3517 });
3518
3519 [[maybe_unused]] unsigned int counter = 0;
3520
3521 std::vector<unsigned int> key;
3522 key.reserve(ReferenceCells::max_n_vertices<structdim>());
3523
3524 for (unsigned int o = 0; o < obj.n_objects(); ++o)
3525 {
3526 auto &boundary_id = obj.boundary_or_material_id[o].boundary_id;
3527 auto &manifold_id = obj.manifold_id[o];
3528
3529 // assert that object has not been visited yet and its value
3530 // has not been modified yet
3531 AssertThrow(boundary_id == 0 ||
3536
3537 // create key
3538 key.assign(crs.col.data() + crs.ptr[o],
3539 crs.col.data() + crs.ptr[o + 1]);
3540 std::sort(key.begin(), key.end());
3541
3542 // is subcelldata provided? -> binary search
3543 const auto subcell_object =
3544 std::lower_bound(boundary_objects.begin(),
3545 boundary_objects.end(),
3546 key,
3547 [&](const auto &cell, const auto &key) {
3548 return cell.vertices < key;
3549 });
3550
3551 // no subcelldata provided for this object
3552 if (subcell_object == boundary_objects.end() ||
3553 subcell_object->vertices != key)
3554 continue;
3555
3556 ++counter;
3557
3558 // set manifold id
3559 manifold_id = subcell_object->manifold_id;
3560
3561 // set boundary id
3562 if (subcell_object->boundary_id !=
3564 {
3567 ExcMessage(
3568 "The input arguments for creating a triangulation "
3569 "specified a boundary id for an internal face. This "
3570 "is not allowed."
3571 "\n\n"
3572 "The object in question has vertex indices " +
3573 [subcell_object]() {
3574 std::string s;
3575 for (const auto v : subcell_object->vertices)
3576 s += std::to_string(v) + ',';
3577 return s;
3578 }() +
3579 " which are located at coordinates " +
3580 [vertex_locations, subcell_object]() {
3581 std::ostringstream s;
3582 for (unsigned int i = 0;
3583 i < subcell_object->vertices.size();
3584 ++i)
3585 s << '('
3586 << vertex_locations[subcell_object->vertices[i]]
3587 << (i != subcell_object->vertices.size() - 1 ? "), " :
3588 ")");
3589 return s.str();
3590 }() +
3591 "."));
3592 boundary_id = subcell_object->boundary_id;
3593 }
3594 }
3595
3596 // make sure that all subcelldata entries have been processed
3597 // TODO: this is not guaranteed, why?
3598 // AssertDimension(counter, boundary_objects_in.size());
3599 }
3600
3601
3602
3603 static void
3605 const unsigned structdim,
3606 const unsigned int size)
3607 {
3608 const unsigned int dim = faces.dim;
3609
3610 if (dim == 3 && structdim == 2)
3611 {
3612 // quad entity types
3613 faces.quad_is_quadrilateral.assign(size, true);
3614
3615 // quad line orientations
3616 faces.quads_line_orientations.assign(size * max_n_faces(structdim),
3617 true);
3618 }
3619 }
3620
3621
3622
3623 static void
3625 const unsigned int spacedim,
3626 const unsigned int size,
3627 const bool orientation_needed)
3628 {
3629 const unsigned int dim = level.dim;
3630
3631 level.active_cell_indices.assign(size, numbers::invalid_unsigned_int);
3632 level.subdomain_ids.assign(size, 0);
3633 level.level_subdomain_ids.assign(size, 0);
3634
3635 level.refine_flags.assign(size, 0u);
3636 level.refine_choice.assign(size, 0u);
3637 level.coarsen_flags.assign(size, false);
3638
3639 level.parents.assign((size + 1) / 2, -1);
3640
3641 if (dim == spacedim - 1)
3642 level.direction_flags.assign(size, true);
3643
3644 level.neighbors.assign(size * max_n_faces(dim), {-1, -1});
3645
3646 level.reference_cell.assign(size, ReferenceCells::Invalid);
3647
3648 if (orientation_needed)
3649 level.face_orientations.reinit(size * max_n_faces(dim));
3650
3651
3652 level.global_active_cell_indices.assign(size,
3654 level.global_level_cell_indices.assign(size,
3656 }
3657
3658
3659
3660 static void
3661 reserve_space_(TriaObjects &obj, const unsigned int size)
3662 {
3663 const unsigned int structdim = obj.structdim;
3664
3665 const unsigned int max_children_per_cell = 1 << structdim;
3666
3667 obj.used.assign(size, true);
3668 obj.boundary_or_material_id.assign(
3669 size,
3671 BoundaryOrMaterialId());
3672 obj.manifold_id.assign(size, -1);
3673 obj.user_flags.assign(size, false);
3674 obj.user_data.resize(size);
3675
3676 if (structdim > 1) // TODO: why?
3677 obj.refinement_cases.assign(size, 0);
3678
3679 obj.children.assign(max_children_per_cell / 2 * size, -1);
3680
3681 obj.cells.assign(size * max_n_faces(structdim), -1);
3682
3683 if (structdim <= 2)
3684 {
3685 obj.next_free_single = size - 1;
3686 obj.next_free_pair = 0;
3688 }
3689 else
3690 {
3691 obj.next_free_single = obj.next_free_pair = 0;
3692 }
3693 }
3694
3695
3711 template <int spacedim>
3712 static void
3715 std::vector<unsigned int> &,
3716 std::vector<unsigned int> &)
3717 {
3718 const unsigned int dim = 1;
3719
3720 // first we need to reset the
3721 // neighbor pointers of the
3722 // neighbors of this cell's
3723 // children to this cell. This is
3724 // different for one dimension,
3725 // since there neighbors can have a
3726 // refinement level differing from
3727 // that of this cell's children by
3728 // more than one level.
3729
3730 Assert(!cell->child(0)->has_children() &&
3731 !cell->child(1)->has_children(),
3733
3734 // first do it for the cells to the
3735 // left
3736 if (cell->neighbor(0).state() == IteratorState::valid)
3737 if (cell->neighbor(0)->has_children())
3738 {
3740 cell->neighbor(0);
3741 Assert(neighbor->level() == cell->level(), ExcInternalError());
3742
3743 // right child
3744 neighbor = neighbor->child(1);
3745 while (true)
3746 {
3747 Assert(neighbor->neighbor(1) == cell->child(0),
3749 neighbor->set_neighbor(1, cell);
3750
3751 // move on to further
3752 // children on the
3753 // boundary between this
3754 // cell and its neighbor
3755 if (neighbor->has_children())
3756 neighbor = neighbor->child(1);
3757 else
3758 break;
3759 }
3760 }
3761
3762 // now do it for the cells to the
3763 // left
3764 if (cell->neighbor(1).state() == IteratorState::valid)
3765 if (cell->neighbor(1)->has_children())
3766 {
3768 cell->neighbor(1);
3769 Assert(neighbor->level() == cell->level(), ExcInternalError());
3770
3771 // left child
3772 neighbor = neighbor->child(0);
3773 while (true)
3774 {
3775 Assert(neighbor->neighbor(0) == cell->child(1),
3777 neighbor->set_neighbor(0, cell);
3778
3779 // move on to further
3780 // children on the
3781 // boundary between this
3782 // cell and its neighbor
3783 if (neighbor->has_children())
3784 neighbor = neighbor->child(0);
3785 else
3786 break;
3787 }
3788 }
3789
3790
3791 // delete the vertex which will not
3792 // be needed anymore. This vertex
3793 // is the second of the first child
3794 triangulation.vertices_used[cell->child(0)->vertex_index(1)] = false;
3795
3796 // invalidate children. clear user
3797 // pointers, to avoid that they may
3798 // appear at unwanted places later
3799 // on...
3800 for (unsigned int child = 0; child < cell->n_children(); ++child)
3801 {
3802 cell->child(child)->clear_user_data();
3803 cell->child(child)->clear_user_flag();
3804 cell->child(child)->clear_used_flag();
3805 }
3806
3807
3808 // delete pointer to children
3809 cell->clear_children();
3810 cell->clear_user_flag();
3811 }
3812
3813
3814
3815 template <int spacedim>
3816 static void
3819 std::vector<unsigned int> &line_cell_count,
3820 std::vector<unsigned int> &)
3821 {
3822 const unsigned int dim = 2;
3823 const RefinementCase<dim> ref_case = cell->refinement_case();
3824
3825 Assert(line_cell_count.size() == triangulation.n_raw_lines(),
3827
3828 // vectors to hold all lines which
3829 // may be deleted
3830 std::vector<typename Triangulation<dim, spacedim>::line_iterator>
3831 lines_to_delete(0);
3832
3833 lines_to_delete.reserve(4 * 2 + 4);
3834
3835 // now we decrease the counters for
3836 // lines contained in the child
3837 // cells
3838 for (unsigned int c = 0; c < cell->n_children(); ++c)
3839 {
3841 cell->child(c);
3842 for (unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++l)
3843 --line_cell_count[child->line_index(l)];
3844 }
3845
3846
3847 // delete the vertex which will not
3848 // be needed anymore. This vertex
3849 // is the second of the second line
3850 // of the first child, if the cell
3851 // is refined with cut_xy, else there
3852 // is no inner vertex.
3853 // additionally delete unneeded inner
3854 // lines
3855 if (ref_case == RefinementCase<dim>::cut_xy)
3856 {
3858 .vertices_used[cell->child(0)->line(1)->vertex_index(1)] = false;
3859
3860 lines_to_delete.push_back(cell->child(0)->line(1));
3861 lines_to_delete.push_back(cell->child(0)->line(3));
3862 lines_to_delete.push_back(cell->child(3)->line(0));
3863 lines_to_delete.push_back(cell->child(3)->line(2));
3864 }
3865 else
3866 {
3867 unsigned int inner_face_no =
3868 ref_case == RefinementCase<dim>::cut_x ? 1 : 3;
3869
3870 // the inner line will not be
3871 // used any more
3872 lines_to_delete.push_back(cell->child(0)->line(inner_face_no));
3873 }
3874
3875 // invalidate children
3876 for (unsigned int child = 0; child < cell->n_children(); ++child)
3877 {
3878 cell->child(child)->clear_user_data();
3879 cell->child(child)->clear_user_flag();
3880 cell->child(child)->clear_used_flag();
3881 }
3882
3883
3884 // delete pointer to children
3885 cell->clear_children();
3886 cell->clear_refinement_case();
3887 cell->clear_user_flag();
3888
3889 // look at the refinement of outer
3890 // lines. if nobody needs those
3891 // anymore we can add them to the
3892 // list of lines to be deleted.
3893 for (unsigned int line_no = 0;
3894 line_no < GeometryInfo<dim>::lines_per_cell;
3895 ++line_no)
3896 {
3898 cell->line(line_no);
3899
3900 if (line->has_children())
3901 {
3902 // if one of the cell counters is
3903 // zero, the other has to be as well
3904
3905 Assert((line_cell_count[line->child_index(0)] == 0 &&
3906 line_cell_count[line->child_index(1)] == 0) ||
3907 (line_cell_count[line->child_index(0)] > 0 &&
3908 line_cell_count[line->child_index(1)] > 0),
3910
3911 if (line_cell_count[line->child_index(0)] == 0)
3912 {
3913 for (unsigned int c = 0; c < 2; ++c)
3914 Assert(!line->child(c)->has_children(),
3916
3917 // we may delete the line's
3918 // children and the middle vertex
3919 // as no cell references them
3920 // anymore
3922 .vertices_used[line->child(0)->vertex_index(1)] = false;
3923
3924 lines_to_delete.push_back(line->child(0));
3925 lines_to_delete.push_back(line->child(1));
3926
3927 line->clear_children();
3928 }
3929 }
3930 }
3931
3932 // finally, delete unneeded lines
3933
3934 // clear user pointers, to avoid that
3935 // they may appear at unwanted places
3936 // later on...
3937 // same for user flags, then finally
3938 // delete the lines
3939 typename std::vector<
3941 line = lines_to_delete.begin(),
3942 endline = lines_to_delete.end();
3943 for (; line != endline; ++line)
3944 {
3945 (*line)->clear_user_data();
3946 (*line)->clear_user_flag();
3947 (*line)->clear_used_flag();
3948 }
3949 }
3950
3951
3952
3953 template <int spacedim>
3954 static void
3957 std::vector<unsigned int> &line_cell_count,
3958 std::vector<unsigned int> &quad_cell_count)
3959 {
3960 const unsigned int dim = 3;
3961
3962 Assert(line_cell_count.size() == triangulation.n_raw_lines(),
3964 Assert(quad_cell_count.size() == triangulation.n_raw_quads(),
3966
3967 // first of all, we store the RefineCase of
3968 // this cell
3969 const RefinementCase<dim> ref_case = cell->refinement_case();
3970 // vectors to hold all lines and quads which
3971 // may be deleted
3972 std::vector<typename Triangulation<dim, spacedim>::line_iterator>
3973 lines_to_delete(0);
3974 std::vector<typename Triangulation<dim, spacedim>::quad_iterator>
3975 quads_to_delete(0);
3976
3977 lines_to_delete.reserve(12 * 2 + 6 * 4 + 6);
3978 quads_to_delete.reserve(6 * 4 + 12);
3979
3980 // now we decrease the counters for lines and
3981 // quads contained in the child cells
3982 for (unsigned int c = 0; c < cell->n_children(); ++c)
3983 {
3985 cell->child(c);
3986 const auto line_indices = TriaAccessorImplementation::
3987 Implementation::get_line_indices_of_cell(*child);
3988 for (const unsigned int l : cell->line_indices())
3989 --line_cell_count[line_indices[l]];
3990 for (auto f : GeometryInfo<dim>::face_indices())
3991 --quad_cell_count[child->quad_index(f)];
3992 }
3993
3994 //-------------------------------------
3995 // delete interior quads and lines and the
3996 // interior vertex, depending on the
3997 // refinement case of the cell
3998 //
3999 // for append quads and lines: only append
4000 // them to the list of objects to be deleted
4001
4002 switch (ref_case)
4003 {
4005 quads_to_delete.push_back(cell->child(0)->face(1));
4006 break;
4008 quads_to_delete.push_back(cell->child(0)->face(3));
4009 break;
4011 quads_to_delete.push_back(cell->child(0)->face(5));
4012 break;
4014 quads_to_delete.push_back(cell->child(0)->face(1));
4015 quads_to_delete.push_back(cell->child(0)->face(3));
4016 quads_to_delete.push_back(cell->child(3)->face(0));
4017 quads_to_delete.push_back(cell->child(3)->face(2));
4018
4019 lines_to_delete.push_back(cell->child(0)->line(11));
4020 break;
4022 quads_to_delete.push_back(cell->child(0)->face(1));
4023 quads_to_delete.push_back(cell->child(0)->face(5));
4024 quads_to_delete.push_back(cell->child(3)->face(0));
4025 quads_to_delete.push_back(cell->child(3)->face(4));
4026
4027 lines_to_delete.push_back(cell->child(0)->line(5));
4028 break;
4030 quads_to_delete.push_back(cell->child(0)->face(3));
4031 quads_to_delete.push_back(cell->child(0)->face(5));
4032 quads_to_delete.push_back(cell->child(3)->face(2));
4033 quads_to_delete.push_back(cell->child(3)->face(4));
4034
4035 lines_to_delete.push_back(cell->child(0)->line(7));
4036 break;
4038 quads_to_delete.push_back(cell->child(0)->face(1));
4039 quads_to_delete.push_back(cell->child(2)->face(1));
4040 quads_to_delete.push_back(cell->child(4)->face(1));
4041 quads_to_delete.push_back(cell->child(6)->face(1));
4042
4043 quads_to_delete.push_back(cell->child(0)->face(3));
4044 quads_to_delete.push_back(cell->child(1)->face(3));
4045 quads_to_delete.push_back(cell->child(4)->face(3));
4046 quads_to_delete.push_back(cell->child(5)->face(3));
4047
4048 quads_to_delete.push_back(cell->child(0)->face(5));
4049 quads_to_delete.push_back(cell->child(1)->face(5));
4050 quads_to_delete.push_back(cell->child(2)->face(5));
4051 quads_to_delete.push_back(cell->child(3)->face(5));
4052
4053 lines_to_delete.push_back(cell->child(0)->line(5));
4054 lines_to_delete.push_back(cell->child(0)->line(7));
4055 lines_to_delete.push_back(cell->child(0)->line(11));
4056 lines_to_delete.push_back(cell->child(7)->line(0));
4057 lines_to_delete.push_back(cell->child(7)->line(2));
4058 lines_to_delete.push_back(cell->child(7)->line(8));
4059 // delete the vertex which will not
4060 // be needed anymore. This vertex
4061 // is the vertex at the heart of
4062 // this cell, which is the sixth of
4063 // the first child
4064 triangulation.vertices_used[cell->child(0)->vertex_index(7)] =
4065 false;
4066 break;
4067 default:
4068 // only remaining case is
4069 // no_refinement, thus an error
4071 break;
4072 }
4073
4074
4075 // invalidate children
4076 for (unsigned int child = 0; child < cell->n_children(); ++child)
4077 {
4078 cell->child(child)->clear_user_data();
4079 cell->child(child)->clear_user_flag();
4080
4081 for (auto f : GeometryInfo<dim>::face_indices())
4082 // set flags denoting deviations from standard orientation of
4083 // faces back to initialization values
4084 cell->child(child)->set_combined_face_orientation(
4086
4087 cell->child(child)->clear_used_flag();
4088 }
4089
4090
4091 // delete pointer to children
4092 cell->clear_children();
4093 cell->clear_refinement_case();
4094 cell->clear_user_flag();
4095
4096 // so far we only looked at inner quads,
4097 // lines and vertices. Now we have to
4098 // consider outer ones as well. here, we have
4099 // to check, whether there are other cells
4100 // still needing these objects. otherwise we
4101 // can delete them. first for quads (and
4102 // their inner lines).
4103
4104 for (const unsigned int quad_no : GeometryInfo<dim>::face_indices())
4105 {
4107 cell->face(quad_no);
4108
4109 Assert(
4110 (GeometryInfo<dim>::face_refinement_case(ref_case, quad_no) &&
4111 quad->has_children()) ||
4112 GeometryInfo<dim>::face_refinement_case(ref_case, quad_no) ==
4115
4116 switch (quad->refinement_case())
4117 {
4118 case RefinementCase<dim - 1>::no_refinement:
4119 // nothing to do as the quad
4120 // is not refined
4121 break;
4122 case RefinementCase<dim - 1>::cut_x:
4123 case RefinementCase<dim - 1>::cut_y:
4124 {
4125 // if one of the cell counters is
4126 // zero, the other has to be as
4127 // well
4128 Assert((quad_cell_count[quad->child_index(0)] == 0 &&
4129 quad_cell_count[quad->child_index(1)] == 0) ||
4130 (quad_cell_count[quad->child_index(0)] > 0 &&
4131 quad_cell_count[quad->child_index(1)] > 0),
4133 // it might be, that the quad is
4134 // refined twice anisotropically,
4135 // first check, whether we may
4136 // delete possible grand_children
4137 unsigned int deleted_grandchildren = 0;
4138 unsigned int number_of_child_refinements = 0;
4139
4140 for (unsigned int c = 0; c < 2; ++c)
4141 if (quad->child(c)->has_children())
4142 {
4143 ++number_of_child_refinements;
4144 // if one of the cell counters is
4145 // zero, the other has to be as
4146 // well
4147 Assert(
4148 (quad_cell_count[quad->child(c)->child_index(0)] ==
4149 0 &&
4150 quad_cell_count[quad->child(c)->child_index(1)] ==
4151 0) ||
4152 (quad_cell_count[quad->child(c)->child_index(0)] >
4153 0 &&
4154 quad_cell_count[quad->child(c)->child_index(1)] >
4155 0),
4157 if (quad_cell_count[quad->child(c)->child_index(0)] ==
4158 0)
4159 {
4160 // Assert, that the two
4161 // anisotropic
4162 // refinements add up to
4163 // isotropic refinement
4164 Assert(quad->refinement_case() +
4165 quad->child(c)->refinement_case() ==
4168 // we may delete the
4169 // quad's children and
4170 // the inner line as no
4171 // cell references them
4172 // anymore
4173 quads_to_delete.push_back(
4174 quad->child(c)->child(0));
4175 quads_to_delete.push_back(
4176 quad->child(c)->child(1));
4177 if (quad->child(c)->refinement_case() ==
4179 lines_to_delete.push_back(
4180 quad->child(c)->child(0)->line(1));
4181 else
4182 lines_to_delete.push_back(
4183 quad->child(c)->child(0)->line(3));
4184 quad->child(c)->clear_children();
4185 quad->child(c)->clear_refinement_case();
4186 ++deleted_grandchildren;
4187 }
4188 }
4189 // if no grandchildren are left, we
4190 // may as well delete the
4191 // refinement of the inner line
4192 // between our children and the
4193 // corresponding vertex
4194 if (number_of_child_refinements > 0 &&
4195 deleted_grandchildren == number_of_child_refinements)
4196 {
4198 middle_line;
4199 if (quad->refinement_case() == RefinementCase<2>::cut_x)
4200 middle_line = quad->child(0)->line(1);
4201 else
4202 middle_line = quad->child(0)->line(3);
4203
4204 lines_to_delete.push_back(middle_line->child(0));
4205 lines_to_delete.push_back(middle_line->child(1));
4207 .vertices_used[middle_vertex_index<dim, spacedim>(
4208 middle_line)] = false;
4209 middle_line->clear_children();
4210 }
4211
4212 // now consider the direct children
4213 // of the given quad
4214 if (quad_cell_count[quad->child_index(0)] == 0)
4215 {
4216 // we may delete the quad's
4217 // children and the inner line
4218 // as no cell references them
4219 // anymore
4220 quads_to_delete.push_back(quad->child(0));
4221 quads_to_delete.push_back(quad->child(1));
4222 if (quad->refinement_case() == RefinementCase<2>::cut_x)
4223 lines_to_delete.push_back(quad->child(0)->line(1));
4224 else
4225 lines_to_delete.push_back(quad->child(0)->line(3));
4226
4227 // if the counters just dropped
4228 // to zero, otherwise the
4229 // children would have been
4230 // deleted earlier, then this
4231 // cell's children must have
4232 // contained the anisotropic
4233 // quad children. thus, if
4234 // those have again anisotropic
4235 // children, which are in
4236 // effect isotropic children of
4237 // the original quad, those are
4238 // still needed by a
4239 // neighboring cell and we
4240 // cannot delete them. instead,
4241 // we have to reset this quad's
4242 // refine case to isotropic and
4243 // set the children
4244 // accordingly.
4245 if (quad->child(0)->has_children())
4246 if (quad->refinement_case() ==
4248 {
4249 // now evereything is
4250 // quite complicated. we
4251 // have the children
4252 // numbered according to
4253 //
4254 // *---*---*
4255 // |n+1|m+1|
4256 // *---*---*
4257 // | n | m |
4258 // *---*---*
4259 //
4260 // from the original
4261 // anisotropic
4262 // refinement. we have to
4263 // reorder them as
4264 //
4265 // *---*---*
4266 // | m |m+1|
4267 // *---*---*
4268 // | n |n+1|
4269 // *---*---*
4270 //
4271 // for isotropic refinement.
4272 //
4273 // this is a bit ugly, of
4274 // course: loop over all
4275 // cells on all levels
4276 // and look for faces n+1
4277 // (switch_1) and m
4278 // (switch_2).
4279 const typename Triangulation<dim, spacedim>::
4280 quad_iterator switch_1 =
4281 quad->child(0)->child(1),
4282 switch_2 =
4283 quad->child(1)->child(0);
4284
4285 Assert(!switch_1->has_children(),
4287 Assert(!switch_2->has_children(),
4289
4290 const int switch_1_index = switch_1->index();
4291 const int switch_2_index = switch_2->index();
4292 for (unsigned int l = 0;
4293 l < triangulation.levels.size();
4294 ++l)
4295 for (unsigned int h = 0;
4296 h <
4297 triangulation.levels[l]->cells.n_objects();
4298 ++h)
4299 for (const unsigned int q :
4301 {
4302 const int index =
4304 ->cells.get_bounding_object_indices(
4305 h)[q];
4306 if (index == switch_1_index)
4307 triangulation.levels[l]
4308 ->cells.get_bounding_object_indices(
4309 h)[q] = switch_2_index;
4310 else if (index == switch_2_index)
4311 triangulation.levels[l]
4312 ->cells.get_bounding_object_indices(
4313 h)[q] = switch_1_index;
4314 }
4315 // now we have to copy
4316 // all information of the
4317 // two quads
4318 const int switch_1_lines[4] = {
4319 static_cast<signed int>(
4320 switch_1->line_index(0)),
4321 static_cast<signed int>(
4322 switch_1->line_index(1)),
4323 static_cast<signed int>(
4324 switch_1->line_index(2)),
4325 static_cast<signed int>(
4326 switch_1->line_index(3))};
4328 switch_1_line_orientations[4] = {
4329 switch_1->line_orientation(0),
4330 switch_1->line_orientation(1),
4331 switch_1->line_orientation(2),
4332 switch_1->line_orientation(3)};
4333 const types::boundary_id switch_1_boundary_id =
4334 switch_1->boundary_id();
4335 const unsigned int switch_1_user_index =
4336 switch_1->user_index();
4337 const bool switch_1_user_flag =
4338 switch_1->user_flag_set();
4339
4340 switch_1->set_bounding_object_indices(
4341 {switch_2->line_index(0),
4342 switch_2->line_index(1),
4343 switch_2->line_index(2),
4344 switch_2->line_index(3)});
4345 switch_1->set_line_orientation(
4346 0, switch_2->line_orientation(0));
4347 switch_1->set_line_orientation(
4348 1, switch_2->line_orientation(1));
4349 switch_1->set_line_orientation(
4350 2, switch_2->line_orientation(2));
4351 switch_1->set_line_orientation(
4352 3, switch_2->line_orientation(3));
4353 switch_1->set_boundary_id_internal(
4354 switch_2->boundary_id());
4355 switch_1->set_manifold_id(
4356 switch_2->manifold_id());
4357 switch_1->set_user_index(switch_2->user_index());
4358 if (switch_2->user_flag_set())
4359 switch_1->set_user_flag();
4360 else
4361 switch_1->clear_user_flag();
4362
4363 switch_2->set_bounding_object_indices(
4364 {switch_1_lines[0],
4365 switch_1_lines[1],
4366 switch_1_lines[2],
4367 switch_1_lines[3]});
4368 switch_2->set_line_orientation(
4369 0, switch_1_line_orientations[0]);
4370 switch_2->set_line_orientation(
4371 1, switch_1_line_orientations[1]);
4372 switch_2->set_line_orientation(
4373 2, switch_1_line_orientations[2]);
4374 switch_2->set_line_orientation(
4375 3, switch_1_line_orientations[3]);
4376 switch_2->set_boundary_id_internal(
4377 switch_1_boundary_id);
4378 switch_2->set_manifold_id(
4379 switch_1->manifold_id());
4380 switch_2->set_user_index(switch_1_user_index);
4381 if (switch_1_user_flag)
4382 switch_2->set_user_flag();
4383 else
4384 switch_2->clear_user_flag();
4385
4386 const unsigned int child_0 =
4387 quad->child(0)->child_index(0);
4388 const unsigned int child_2 =
4389 quad->child(1)->child_index(0);
4390 quad->clear_children();
4391 quad->clear_refinement_case();
4392 quad->set_refinement_case(
4394 quad->set_children(0, child_0);
4395 quad->set_children(2, child_2);
4396 std::swap(quad_cell_count[child_0 + 1],
4397 quad_cell_count[child_2]);
4398 }
4399 else
4400 {
4401 // the face was refined
4402 // with cut_y, thus the
4403 // children are already
4404 // in correct order. we
4405 // only have to set them
4406 // correctly, deleting
4407 // the indirection of two
4408 // anisotropic refinement
4409 // and going directly
4410 // from the quad to
4411 // isotropic children
4412 const unsigned int child_0 =
4413 quad->child(0)->child_index(0);
4414 const unsigned int child_2 =
4415 quad->child(1)->child_index(0);
4416 quad->clear_children();
4417 quad->clear_refinement_case();
4418 quad->set_refinement_case(
4420 quad->set_children(0, child_0);
4421 quad->set_children(2, child_2);
4422 }
4423 else
4424 {
4425 quad->clear_children();
4426 quad->clear_refinement_case();
4427 }
4428 }
4429 break;
4430 }
4431 case RefinementCase<dim - 1>::cut_xy:
4432 {
4433 // if one of the cell counters is
4434 // zero, the others have to be as
4435 // well
4436
4437 Assert((quad_cell_count[quad->child_index(0)] == 0 &&
4438 quad_cell_count[quad->child_index(1)] == 0 &&
4439 quad_cell_count[quad->child_index(2)] == 0 &&
4440 quad_cell_count[quad->child_index(3)] == 0) ||
4441 (quad_cell_count[quad->child_index(0)] > 0 &&
4442 quad_cell_count[quad->child_index(1)] > 0 &&
4443 quad_cell_count[quad->child_index(2)] > 0 &&
4444 quad_cell_count[quad->child_index(3)] > 0),
4446
4447 if (quad_cell_count[quad->child_index(0)] == 0)
4448 {
4449 // we may delete the quad's
4450 // children, the inner lines
4451 // and the middle vertex as no
4452 // cell references them anymore
4453 lines_to_delete.push_back(quad->child(0)->line(1));
4454 lines_to_delete.push_back(quad->child(3)->line(0));
4455 lines_to_delete.push_back(quad->child(0)->line(3));
4456 lines_to_delete.push_back(quad->child(3)->line(2));
4457
4458 for (unsigned int child = 0; child < quad->n_children();
4459 ++child)
4460 quads_to_delete.push_back(quad->child(child));
4461
4463 .vertices_used[quad->child(0)->vertex_index(3)] =
4464 false;
4465
4466 quad->clear_children();
4467 quad->clear_refinement_case();
4468 }
4469 }
4470 break;
4471
4472 default:
4474 break;
4475 }
4476 }
4477
4478 // now we repeat a similar procedure
4479 // for the outer lines of this cell.
4480
4481 // if in debug mode: check that each
4482 // of the lines for which we consider
4483 // deleting the children in fact has
4484 // children (the bits/coarsening_3d
4485 // test tripped over this initially)
4486 for (unsigned int line_no = 0;
4487 line_no < GeometryInfo<dim>::lines_per_cell;
4488 ++line_no)
4489 {
4491 cell->line(line_no);
4492
4493 Assert(
4494 (GeometryInfo<dim>::line_refinement_case(ref_case, line_no) &&
4495 line->has_children()) ||
4496 GeometryInfo<dim>::line_refinement_case(ref_case, line_no) ==
4499
4500 if (line->has_children())
4501 {
4502 // if one of the cell counters is
4503 // zero, the other has to be as well
4504
4505 Assert((line_cell_count[line->child_index(0)] == 0 &&
4506 line_cell_count[line->child_index(1)] == 0) ||
4507 (line_cell_count[line->child_index(0)] > 0 &&
4508 line_cell_count[line->child_index(1)] > 0),
4510
4511 if (line_cell_count[line->child_index(0)] == 0)
4512 {
4513 for (unsigned int c = 0; c < 2; ++c)
4514 Assert(!line->child(c)->has_children(),
4516
4517 // we may delete the line's
4518 // children and the middle vertex
4519 // as no cell references them
4520 // anymore
4522 .vertices_used[line->child(0)->vertex_index(1)] = false;
4523
4524 lines_to_delete.push_back(line->child(0));
4525 lines_to_delete.push_back(line->child(1));
4526
4527 line->clear_children();
4528 }
4529 }
4530 }
4531
4532 // finally, delete unneeded quads and lines
4533
4534 // clear user pointers, to avoid that
4535 // they may appear at unwanted places
4536 // later on...
4537 // same for user flags, then finally
4538 // delete the quads and lines
4539 typename std::vector<
4541 line = lines_to_delete.begin(),
4542 endline = lines_to_delete.end();
4543 for (; line != endline; ++line)
4544 {
4545 (*line)->clear_user_data();
4546 (*line)->clear_user_flag();
4547 (*line)->clear_used_flag();
4548 }
4549
4550 typename std::vector<
4552 quad = quads_to_delete.begin(),
4553 endquad = quads_to_delete.end();
4554 for (; quad != endquad; ++quad)
4555 {
4556 (*quad)->clear_user_data();
4557 (*quad)->clear_children();
4558 (*quad)->clear_refinement_case();
4559 (*quad)->clear_user_flag();
4560 (*quad)->clear_used_flag();
4561 }
4562 }
4563
4564
4582 template <int spacedim>
4583 static void
4586 unsigned int &next_unused_vertex,
4588 &next_unused_line,
4590 &next_unused_cell,
4591 const typename Triangulation<2, spacedim>::cell_iterator &cell)
4592 {
4593 const unsigned int dim = 2;
4594 // clear refinement flag
4595 const RefinementCase<dim> ref_case = cell->refine_flag_set();
4596 cell->clear_refine_flag();
4597
4598 /* For the refinement process: since we go the levels up from the
4599 lowest, there are (unlike above) only two possibilities: a neighbor
4600 cell is on the same level or one level up (in both cases, it may or
4601 may not be refined later on, but we don't care here).
4602
4603 First:
4604 Set up an array of the 3x3 vertices, which are distributed on the
4605 cell (the array consists of indices into the @p{vertices} std::vector
4606
4607 2--7--3
4608 | | |
4609 4--8--5
4610 | | |
4611 0--6--1
4612
4613 note: in case of cut_x or cut_y not all these vertices are needed for
4614 the new cells
4615
4616 Second:
4617 Set up an array of the new lines (the array consists of iterator
4618 pointers into the lines arrays)
4619
4620 .-6-.-7-. The directions are: .->-.->-.
4621 1 9 3 ^ ^ ^
4622 .-10.11-. .->-.->-.
4623 0 8 2 ^ ^ ^
4624 .-4-.-5-. .->-.->-.
4625
4626 cut_x:
4627 .-4-.-5-.
4628 | | |
4629 0 6 1
4630 | | |
4631 .-2-.-3-.
4632
4633 cut_y:
4634 .---5---.
4635 1 3
4636 .---6---.
4637 0 2
4638 .---4---.
4639
4640
4641 Third:
4642 Set up an array of neighbors:
4643
4644 6 7
4645 .--.--.
4646 1| | |3
4647 .--.--.
4648 0| | |2
4649 .--.--.
4650 4 5
4651
4652 We need this array for two reasons: first to get the lines which will
4653 bound the four subcells (if the neighboring cell is refined, these
4654 lines already exist), and second to update neighborship information.
4655 Since if a neighbor is not refined, its neighborship record only
4656 points to the present, unrefined, cell rather than the children we
4657 are presently creating, we only need the neighborship information
4658 if the neighbor cells are refined. In all other cases, we store
4659 the unrefined neighbor address
4660
4661 We also need for every neighbor (if refined) which number among its
4662 neighbors the present (unrefined) cell has, since that number is to
4663 be replaced and because that also is the number of the subline which
4664 will be the interface between that neighbor and the to be created
4665 cell. We will store this number (between 0 and 3) in the field
4666 @p{neighbors_neighbor}.
4667
4668 It would be sufficient to use the children of the common line to the
4669 neighbor, if we only wanted to get the new sublines and the new
4670 vertex, but because we need to update the neighborship information of
4671 the two refined subcells of the neighbor, we need to search these
4672 anyway.
4673
4674 Convention:
4675 The created children are numbered like this:
4676
4677 .--.--.
4678 |2 . 3|
4679 .--.--.
4680 |0 | 1|
4681 .--.--.
4682 */
4683 // collect the indices of the eight surrounding vertices
4684 // 2--7--3
4685 // | | |
4686 // 4--8--5
4687 // | | |
4688 // 0--6--1
4689 int new_vertices[9];
4690 for (unsigned int vertex_no = 0; vertex_no < 4; ++vertex_no)
4691 new_vertices[vertex_no] = cell->vertex_index(vertex_no);
4692 for (unsigned int line_no = 0; line_no < 4; ++line_no)
4693 if (cell->line(line_no)->has_children())
4694 new_vertices[4 + line_no] =
4695 cell->line(line_no)->child(0)->vertex_index(1);
4696
4697 if (ref_case == RefinementCase<dim>::cut_xy)
4698 {
4699 // find the next
4700 // unused vertex and
4701 // allocate it for
4702 // the new vertex we
4703 // need here
4704 while (triangulation.vertices_used[next_unused_vertex] == true)
4705 ++next_unused_vertex;
4706 Assert(next_unused_vertex < triangulation.vertices.size(),
4707 ExcMessage(
4708 "Internal error: During refinement, the triangulation "
4709 "wants to access an element of the 'vertices' array "
4710 "but it turns out that the array is not large enough."));
4711 triangulation.vertices_used[next_unused_vertex] = true;
4712
4713 new_vertices[8] = next_unused_vertex;
4714
4715 // determine middle vertex by transfinite interpolation to be
4716 // consistent with what happens to quads in a
4717 // Triangulation<3,3> when they are refined
4718 triangulation.vertices[next_unused_vertex] =
4719 cell->center(true, true);
4720 }
4721
4722
4723 // Now the lines:
4725 unsigned int lmin = 8;
4726 unsigned int lmax = 12;
4727 if (ref_case != RefinementCase<dim>::cut_xy)
4728 {
4729 lmin = 6;
4730 lmax = 7;
4731 }
4732
4733 for (unsigned int l = lmin; l < lmax; ++l)
4734 {
4735 while (next_unused_line->used() == true)
4736 ++next_unused_line;
4737 new_lines[l] = next_unused_line;
4738 ++next_unused_line;
4739
4740 AssertIsNotUsed(new_lines[l]);
4741 }
4742
4743 if (ref_case == RefinementCase<dim>::cut_xy)
4744 {
4745 // .-6-.-7-.
4746 // 1 9 3
4747 // .-10.11-.
4748 // 0 8 2
4749 // .-4-.-5-.
4750
4751 // lines 0-7 already exist, create only the four interior
4752 // lines 8-11
4753 unsigned int l = 0;
4754 for (const unsigned int face_no : GeometryInfo<dim>::face_indices())
4755 for (unsigned int c = 0; c < 2; ++c, ++l)
4756 new_lines[l] = cell->line(face_no)->child(c);
4757 Assert(l == 8, ExcInternalError());
4758
4759 new_lines[8]->set_bounding_object_indices(
4760 {new_vertices[6], new_vertices[8]});
4761 new_lines[9]->set_bounding_object_indices(
4762 {new_vertices[8], new_vertices[7]});
4763 new_lines[10]->set_bounding_object_indices(
4764 {new_vertices[4], new_vertices[8]});
4765 new_lines[11]->set_bounding_object_indices(
4766 {new_vertices[8], new_vertices[5]});
4767 }
4768 else if (ref_case == RefinementCase<dim>::cut_x)
4769 {
4770 // .-4-.-5-.
4771 // | | |
4772 // 0 6 1
4773 // | | |
4774 // .-2-.-3-.
4775 new_lines[0] = cell->line(0);
4776 new_lines[1] = cell->line(1);
4777 new_lines[2] = cell->line(2)->child(0);
4778 new_lines[3] = cell->line(2)->child(1);
4779 new_lines[4] = cell->line(3)->child(0);
4780 new_lines[5] = cell->line(3)->child(1);
4781 new_lines[6]->set_bounding_object_indices(
4782 {new_vertices[6], new_vertices[7]});
4783 }
4784 else
4785 {
4787 // .---5---.
4788 // 1 3
4789 // .---6---.
4790 // 0 2
4791 // .---4---.
4792 new_lines[0] = cell->line(0)->child(0);
4793 new_lines[1] = cell->line(0)->child(1);
4794 new_lines[2] = cell->line(1)->child(0);
4795 new_lines[3] = cell->line(1)->child(1);
4796 new_lines[4] = cell->line(2);
4797 new_lines[5] = cell->line(3);
4798 new_lines[6]->set_bounding_object_indices(
4799 {new_vertices[4], new_vertices[5]});
4800 }
4801
4802 for (unsigned int l = lmin; l < lmax; ++l)
4803 {
4804 new_lines[l]->set_used_flag();
4805 new_lines[l]->clear_user_flag();
4806 new_lines[l]->clear_user_data();
4807 new_lines[l]->clear_children();
4808 // interior line
4809 new_lines[l]->set_boundary_id_internal(
4811 new_lines[l]->set_manifold_id(cell->manifold_id());
4812 }
4813
4814 // Now add the four (two)
4815 // new cells!
4818 while (next_unused_cell->used() == true)
4819 ++next_unused_cell;
4820
4821 const unsigned int n_children = GeometryInfo<dim>::n_children(ref_case);
4822 for (unsigned int i = 0; i < n_children; ++i)
4823 {
4824 AssertIsNotUsed(next_unused_cell);
4825 subcells[i] = next_unused_cell;
4826 ++next_unused_cell;
4827 if (i % 2 == 1 && i < n_children - 1)
4828 while (next_unused_cell->used() == true)
4829 ++next_unused_cell;
4830 }
4831
4832 if (ref_case == RefinementCase<dim>::cut_xy)
4833 {
4834 // children:
4835 // .--.--.
4836 // |2 . 3|
4837 // .--.--.
4838 // |0 | 1|
4839 // .--.--.
4840 // lines:
4841 // .-6-.-7-.
4842 // 1 9 3
4843 // .-10.11-.
4844 // 0 8 2
4845 // .-4-.-5-.
4846 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
4847 new_lines[8]->index(),
4848 new_lines[4]->index(),
4849 new_lines[10]->index()});
4850 subcells[1]->set_bounding_object_indices({new_lines[8]->index(),
4851 new_lines[2]->index(),
4852 new_lines[5]->index(),
4853 new_lines[11]->index()});
4854 subcells[2]->set_bounding_object_indices({new_lines[1]->index(),
4855 new_lines[9]->index(),
4856 new_lines[10]->index(),
4857 new_lines[6]->index()});
4858 subcells[3]->set_bounding_object_indices({new_lines[9]->index(),
4859 new_lines[3]->index(),
4860 new_lines[11]->index(),
4861 new_lines[7]->index()});
4862 }
4863 else if (ref_case == RefinementCase<dim>::cut_x)
4864 {
4865 // children:
4866 // .--.--.
4867 // | . |
4868 // .0 . 1.
4869 // | | |
4870 // .--.--.
4871 // lines:
4872 // .-4-.-5-.
4873 // | | |
4874 // 0 6 1
4875 // | | |
4876 // .-2-.-3-.
4877 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
4878 new_lines[6]->index(),
4879 new_lines[2]->index(),
4880 new_lines[4]->index()});
4881 subcells[1]->set_bounding_object_indices({new_lines[6]->index(),
4882 new_lines[1]->index(),
4883 new_lines[3]->index(),
4884 new_lines[5]->index()});
4885 }
4886 else
4887 {
4889 // children:
4890 // .-----.
4891 // | 1 |
4892 // .-----.
4893 // | 0 |
4894 // .-----.
4895 // lines:
4896 // .---5---.
4897 // 1 3
4898 // .---6---.
4899 // 0 2
4900 // .---4---.
4901 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
4902 new_lines[2]->index(),
4903 new_lines[4]->index(),
4904 new_lines[6]->index()});
4905 subcells[1]->set_bounding_object_indices({new_lines[1]->index(),
4906 new_lines[3]->index(),
4907 new_lines[6]->index(),
4908 new_lines[5]->index()});
4909 }
4910
4911 types::subdomain_id subdomainid = cell->subdomain_id();
4912
4913 for (unsigned int i = 0; i < n_children; ++i)
4914 {
4915 subcells[i]->set_used_flag();
4916 subcells[i]->clear_refine_flag();
4917 subcells[i]->clear_user_flag();
4918 subcells[i]->clear_user_data();
4919 subcells[i]->clear_children();
4920 // inherit material properties
4921 subcells[i]->set_material_id(cell->material_id());
4922 subcells[i]->set_manifold_id(cell->manifold_id());
4923 subcells[i]->set_subdomain_id(subdomainid);
4924
4925 if (i % 2 == 0)
4926 subcells[i]->set_parent(cell->index());
4927 }
4928
4929
4930
4931 // set child index for even children i=0,2 (0)
4932 for (unsigned int i = 0; i < n_children / 2; ++i)
4933 cell->set_children(2 * i, subcells[2 * i]->index());
4934 // set the refine case
4935 cell->set_refinement_case(ref_case);
4936
4937 // note that the
4938 // refinement flag was
4939 // already cleared at the
4940 // beginning of this function
4941
4942 if (dim == spacedim - 1)
4943 for (unsigned int c = 0; c < n_children; ++c)
4944 cell->child(c)->set_direction_flag(cell->direction_flag());
4945 }
4946
4947
4948
4949 template <int dim, int spacedim>
4952 const bool check_for_distorted_cells)
4953 {
4954 AssertDimension(dim, 2);
4955
4956 // Check whether a new level is needed. We have to check for
4957 // this on the highest level only
4958 for (const auto &cell : triangulation.active_cell_iterators_on_level(
4959 triangulation.levels.size() - 1))
4960 if (cell->refine_flag_set())
4961 {
4962 triangulation.levels.push_back(
4963 std::make_unique<
4965 break;
4966 }
4967
4970 line != triangulation.end_line();
4971 ++line)
4972 {
4973 line->clear_user_flag();
4974 line->clear_user_data();
4975 }
4976
4977 unsigned int n_single_lines = 0;
4978 unsigned int n_lines_in_pairs = 0;
4979 unsigned int needed_vertices = 0;
4980
4981 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
4982 {
4983 // count number of flagged cells on this level and compute
4984 // how many new vertices and new lines will be needed
4985 unsigned int needed_cells = 0;
4986
4987 for (const auto &cell :
4988 triangulation.active_cell_iterators_on_level(level))
4989 if (cell->refine_flag_set())
4990 {
4991 if (cell->reference_cell() == ReferenceCells::Triangle)
4992 {
4993 needed_cells += 4;
4994 needed_vertices += 0;
4995 n_single_lines += 3;
4996 }
4997 else if (cell->reference_cell() ==
4999 {
5000 needed_cells += 4;
5001 needed_vertices += 1;
5002 n_single_lines += 4;
5003 }
5004 else
5005 {
5007 }
5008
5009 for (const auto line_no : cell->face_indices())
5010 {
5011 auto line = cell->line(line_no);
5012 if (line->has_children() == false)
5013 line->set_user_flag();
5014 }
5015 }
5016
5017
5018 const unsigned int used_cells =
5019 std::count(triangulation.levels[level + 1]->cells.used.begin(),
5020 triangulation.levels[level + 1]->cells.used.end(),
5021 true);
5022
5023
5024 reserve_space(*triangulation.levels[level + 1],
5025 used_cells + needed_cells,
5026 spacedim);
5027
5028 reserve_space(triangulation.levels[level + 1]->cells,
5029 needed_cells,
5030 0);
5031 }
5032
5033 for (auto line = triangulation.begin_line();
5034 line != triangulation.end_line();
5035 ++line)
5036 if (line->user_flag_set())
5037 {
5038 Assert(line->has_children() == false, ExcInternalError());
5039 n_lines_in_pairs += 2;
5040 needed_vertices += 1;
5041 }
5042
5043 reserve_space(triangulation.faces->lines, n_lines_in_pairs, 0);
5044
5045 needed_vertices += std::count(triangulation.vertices_used.begin(),
5046 triangulation.vertices_used.end(),
5047 true);
5048
5049 if (needed_vertices > triangulation.vertices.size())
5050 {
5051 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
5052 triangulation.vertices_used.resize(needed_vertices, false);
5053 }
5054
5055 unsigned int next_unused_vertex = 0;
5056
5057 {
5060 endl = triangulation.end_line();
5062 next_unused_line = triangulation.begin_raw_line();
5063
5064 for (; line != endl; ++line)
5065 if (line->user_flag_set())
5066 {
5067 // This line needs to be refined. Find the next unused vertex
5068 // and set it appropriately
5069 while (triangulation.vertices_used[next_unused_vertex] == true)
5070 ++next_unused_vertex;
5071 Assert(next_unused_vertex < triangulation.vertices.size(),
5072 ExcMessage(
5073 "Internal error: During refinement, the triangulation "
5074 "wants to access an element of the 'vertices' array "
5075 "but it turns out that the array is not large "
5076 "enough."));
5077 triangulation.vertices_used[next_unused_vertex] = true;
5078
5079 triangulation.vertices[next_unused_vertex] = line->center(true);
5080
5081 [[maybe_unused]] bool pair_found = false;
5082 for (; next_unused_line != endl; ++next_unused_line)
5083 if (!next_unused_line->used() &&
5084 !(++next_unused_line)->used())
5085 {
5086 --next_unused_line;
5087 pair_found = true;
5088 break;
5089 }
5090 Assert(pair_found, ExcInternalError());
5091
5092 line->set_children(0, next_unused_line->index());
5093
5095 children[2] = {next_unused_line, ++next_unused_line};
5096
5097 AssertIsNotUsed(children[0]);
5098 AssertIsNotUsed(children[1]);
5099
5100 children[0]->set_bounding_object_indices(
5101 {line->vertex_index(0), next_unused_vertex});
5102 children[1]->set_bounding_object_indices(
5103 {next_unused_vertex, line->vertex_index(1)});
5104
5105 for (auto &child : children)
5106 {
5107 child->set_used_flag();
5108 child->clear_children();
5109 child->clear_user_data();
5110 child->clear_user_flag();
5111 child->set_boundary_id_internal(line->boundary_id());
5112 child->set_manifold_id(line->manifold_id());
5113 // Line orientation is relative to the cell it is on so
5114 // those cannot be set at this point.
5115 }
5116
5117 line->clear_user_flag();
5118 }
5119 }
5120
5121 reserve_space(triangulation.faces->lines, 0, n_single_lines);
5122
5124 cells_with_distorted_children;
5125
5127 next_unused_line = triangulation.begin_raw_line();
5128
5129 const auto create_children = [](auto &triangulation,
5130 unsigned int &next_unused_vertex,
5131 auto &next_unused_line,
5132 auto &next_unused_cell,
5133 const auto &cell) {
5134 const auto ref_case = cell->refine_flag_set();
5135 cell->clear_refine_flag();
5136
5137 unsigned int n_new_vertices = 0;
5138
5139 if (cell->reference_cell() == ReferenceCells::Triangle)
5140 n_new_vertices = 6;
5141 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5142 n_new_vertices = 9;
5143 else
5145
5146 std::vector<unsigned int> new_vertices(n_new_vertices,
5148 for (unsigned int vertex_no = 0; vertex_no < cell->n_vertices();
5149 ++vertex_no)
5150 new_vertices[vertex_no] = cell->vertex_index(vertex_no);
5151 for (unsigned int line_no = 0; line_no < cell->n_lines(); ++line_no)
5152 if (cell->line(line_no)->has_children())
5153 new_vertices[cell->n_vertices() + line_no] =
5154 cell->line(line_no)->child(0)->vertex_index(1);
5155
5156 if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5157 {
5158 while (triangulation.vertices_used[next_unused_vertex] == true)
5159 ++next_unused_vertex;
5160 Assert(
5161 next_unused_vertex < triangulation.vertices.size(),
5162 ExcMessage(
5163 "Internal error: During refinement, the triangulation wants "
5164 "to access an element of the 'vertices' array but it turns "
5165 "out that the array is not large enough."));
5166 triangulation.vertices_used[next_unused_vertex] = true;
5167
5168 new_vertices[8] = next_unused_vertex;
5169
5170 triangulation.vertices[next_unused_vertex] =
5171 cell->center(true, true);
5172 }
5173
5174 std::array<typename Triangulation<dim, spacedim>::raw_line_iterator,
5175 12>
5176 new_lines;
5177 std::array<types::geometric_orientation, 12> inherited_orientations;
5178 inherited_orientations.fill(numbers::default_geometric_orientation);
5179 unsigned int lmin = 0;
5180 unsigned int lmax = 0;
5181
5182 if (cell->reference_cell() == ReferenceCells::Triangle)
5183 {
5184 lmin = 6;
5185 lmax = 9;
5186 // For triangles, the innermost faces are always reversed for the
5187 // first three children and are in the standard orientation for
5188 // the last one.
5189 std::fill(inherited_orientations.begin() + lmin,
5190 inherited_orientations.begin() + lmax,
5192 }
5193 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5194 {
5195 lmin = 8;
5196 lmax = 12;
5197 }
5198 else
5199 {
5201 }
5202
5203 for (unsigned int l = lmin; l < lmax; ++l)
5204 {
5205 while (next_unused_line->used() == true)
5206 ++next_unused_line;
5207 new_lines[l] = next_unused_line;
5208 ++next_unused_line;
5209
5210 AssertIsNotUsed(new_lines[l]);
5211 }
5212
5213 // set up lines which have parents:
5214 for (const unsigned int face_no : cell->face_indices())
5215 {
5216 // Check the face (line) orientation to ensure that the (six or
5217 // eight) outer lines in new_lines are indexed in the default
5218 // orientation. This way we can index into this array in the
5219 // without special casing orientations (e.g., quadrilateral child
5220 // 3 will always have lines 9, 3, 11, 7) when setting child lines.
5221 const auto combined_orientation =
5222 cell->combined_face_orientation(face_no);
5223 Assert(combined_orientation ==
5225 combined_orientation ==
5228 for (unsigned int c = 0; c < 2; ++c)
5229 {
5230 new_lines[2 * face_no + c] = cell->line(face_no)->child(c);
5231 inherited_orientations[2 * face_no + c] =
5232 cell->combined_face_orientation(face_no);
5233 }
5234 if (combined_orientation == numbers::reverse_line_orientation)
5235 std::swap(new_lines[2 * face_no], new_lines[2 * face_no + 1]);
5236 }
5237
5238 // set up lines which do not have parents:
5239 if (cell->reference_cell() == ReferenceCells::Triangle)
5240 {
5241 new_lines[6]->set_bounding_object_indices(
5242 {new_vertices[3], new_vertices[4]});
5243 new_lines[7]->set_bounding_object_indices(
5244 {new_vertices[4], new_vertices[5]});
5245 new_lines[8]->set_bounding_object_indices(
5246 {new_vertices[5], new_vertices[3]});
5247 }
5248 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5249 {
5250 new_lines[8]->set_bounding_object_indices(
5251 {new_vertices[6], new_vertices[8]});
5252 new_lines[9]->set_bounding_object_indices(
5253 {new_vertices[8], new_vertices[7]});
5254 new_lines[10]->set_bounding_object_indices(
5255 {new_vertices[4], new_vertices[8]});
5256 new_lines[11]->set_bounding_object_indices(
5257 {new_vertices[8], new_vertices[5]});
5258 }
5259 else
5260 {
5262 }
5263
5264 for (unsigned int l = lmin; l < lmax; ++l)
5265 {
5266 new_lines[l]->set_used_flag();
5267 new_lines[l]->clear_user_flag();
5268 new_lines[l]->clear_user_data();
5269 new_lines[l]->clear_children();
5270 // new lines are always internal.
5271 new_lines[l]->set_boundary_id_internal(
5273 new_lines[l]->set_manifold_id(cell->manifold_id());
5274 }
5275
5278 while (next_unused_cell->used() == true)
5279 ++next_unused_cell;
5280
5281 unsigned int n_children = 0;
5282 if (cell->reference_cell() == ReferenceCells::Triangle)
5283 n_children = 4;
5284 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5285 n_children = 4;
5286 else
5288
5289 for (unsigned int i = 0; i < n_children; ++i)
5290 {
5291 AssertIsNotUsed(next_unused_cell);
5292 subcells[i] = next_unused_cell;
5293 ++next_unused_cell;
5294 if (i % 2 == 1 && i < n_children - 1)
5295 while (next_unused_cell->used() == true)
5296 ++next_unused_cell;
5297 }
5298
5299 // Assign lines to child cells:
5300 constexpr unsigned int X = numbers::invalid_unsigned_int;
5301 static constexpr ::ndarray<unsigned int, 4, 4> tri_child_lines =
5302 {{{{0, 8, 5, X}}, {{1, 2, 6, X}}, {{7, 3, 4, X}}, {{6, 7, 8, X}}}};
5303 static constexpr ::ndarray<unsigned int, 4, 4>
5304 quad_child_lines = {{{{0, 8, 4, 10}},
5305 {{8, 2, 5, 11}},
5306 {{1, 9, 10, 6}},
5307 {{9, 3, 11, 7}}}};
5308 // Here and below we assume that child cells have the same reference
5309 // cell type as the parent.
5310 const auto &child_lines =
5311 cell->reference_cell() == ReferenceCells::Triangle ?
5312 tri_child_lines :
5313 quad_child_lines;
5314 for (unsigned int i = 0; i < n_children; ++i)
5315 {
5316 if (cell->reference_cell() == ReferenceCells::Triangle)
5317 subcells[i]->set_bounding_object_indices(
5318 {new_lines[child_lines[i][0]]->index(),
5319 new_lines[child_lines[i][1]]->index(),
5320 new_lines[child_lines[i][2]]->index()});
5321 else
5322 subcells[i]->set_bounding_object_indices(
5323 {new_lines[child_lines[i][0]]->index(),
5324 new_lines[child_lines[i][1]]->index(),
5325 new_lines[child_lines[i][2]]->index(),
5326 new_lines[child_lines[i][3]]->index()});
5327
5328 subcells[i]->set_used_flag();
5329 subcells[i]->clear_refine_flag();
5330 subcells[i]->clear_user_flag();
5331 subcells[i]->clear_user_data();
5332 subcells[i]->clear_children();
5333 // inherit material properties
5334 subcells[i]->set_material_id(cell->material_id());
5335 subcells[i]->set_manifold_id(cell->manifold_id());
5336 subcells[i]->set_subdomain_id(cell->subdomain_id());
5337
5338 triangulation.levels[subcells[i]->level()]
5339 ->reference_cell[subcells[i]->index()] = cell->reference_cell();
5340
5341 // Finally, now that children are marked as used, we can set
5342 // orientation flags:
5343 for (unsigned int face_no : cell->face_indices())
5344 subcells[i]->set_combined_face_orientation(
5345 face_no, inherited_orientations[child_lines[i][face_no]]);
5346
5347 if (i % 2 == 0)
5348 subcells[i]->set_parent(cell->index());
5349 }
5350
5351 // Unlike the same lines on other children, the innermost triangle's
5352 // faces are all in the default orientation:
5353 if (cell->reference_cell() == ReferenceCells::Triangle)
5354 for (unsigned int face_no : cell->face_indices())
5355 subcells[3]->set_combined_face_orientation(
5357
5358 for (unsigned int i = 0; i < n_children / 2; ++i)
5359 cell->set_children(2 * i, subcells[2 * i]->index());
5360
5361 cell->set_refinement_case(ref_case);
5362
5363 if (dim == spacedim - 1)
5364 for (unsigned int c = 0; c < n_children; ++c)
5365 cell->child(c)->set_direction_flag(cell->direction_flag());
5366 };
5367
5368 for (int level = 0;
5369 level < static_cast<int>(triangulation.levels.size()) - 1;
5370 ++level)
5371 {
5373 next_unused_cell = triangulation.begin_raw(level + 1);
5374
5375 for (const auto &cell :
5376 triangulation.active_cell_iterators_on_level(level))
5377 if (cell->refine_flag_set())
5378 {
5380 next_unused_vertex,
5381 next_unused_line,
5382 next_unused_cell,
5383 cell);
5384
5385 if (cell->reference_cell() == ReferenceCells::Quadrilateral &&
5386 check_for_distorted_cells &&
5387 has_distorted_children<dim, spacedim>(cell))
5388 cells_with_distorted_children.distorted_cells.push_back(
5389 cell);
5390
5391 triangulation.signals.post_refinement_on_cell(cell);
5392 }
5393 }
5394
5395 return cells_with_distorted_children;
5396 }
5397
5398
5399
5404 template <int spacedim>
5407 const bool /*check_for_distorted_cells*/)
5408 {
5409 const unsigned int dim = 1;
5410
5411 // Check whether a new level is needed. We have to check for
5412 // this on the highest level only
5413 for (const auto &cell : triangulation.active_cell_iterators_on_level(
5414 triangulation.levels.size() - 1))
5415 if (cell->refine_flag_set())
5416 {
5417 triangulation.levels.push_back(
5418 std::make_unique<
5420 break;
5421 }
5422
5423
5424 // check how much space is needed on every level. We need not
5425 // check the highest level since either - on the highest level
5426 // no cells are flagged for refinement - there are, but
5427 // prepare_refinement added another empty level
5428 unsigned int needed_vertices = 0;
5429 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5430 {
5431 // count number of flagged
5432 // cells on this level
5433 unsigned int flagged_cells = 0;
5434
5435 for (const auto &acell :
5436 triangulation.active_cell_iterators_on_level(level))
5437 if (acell->refine_flag_set())
5438 ++flagged_cells;
5439
5440 // count number of used cells
5441 // on the next higher level
5442 const unsigned int used_cells =
5443 std::count(triangulation.levels[level + 1]->cells.used.begin(),
5444 triangulation.levels[level + 1]->cells.used.end(),
5445 true);
5446
5447 // reserve space for the used_cells cells already existing
5448 // on the next higher level as well as for the
5449 // 2*flagged_cells that will be created on that level
5450 reserve_space(*triangulation.levels[level + 1],
5452 flagged_cells,
5453 spacedim);
5454 // reserve space for 2*flagged_cells new lines on the next
5455 // higher level
5456 reserve_space(triangulation.levels[level + 1]->cells,
5458 flagged_cells,
5459 0);
5460
5461 needed_vertices += flagged_cells;
5462 }
5463
5464 // add to needed vertices how many
5465 // vertices are already in use
5466 needed_vertices += std::count(triangulation.vertices_used.begin(),
5467 triangulation.vertices_used.end(),
5468 true);
5469 // if we need more vertices: create them, if not: leave the
5470 // array as is, since shrinking is not really possible because
5471 // some of the vertices at the end may be in use
5472 if (needed_vertices > triangulation.vertices.size())
5473 {
5474 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
5475 triangulation.vertices_used.resize(needed_vertices, false);
5476 }
5477
5478
5479 // Do REFINEMENT on every level; exclude highest level as
5480 // above
5481
5482 // index of next unused vertex
5483 unsigned int next_unused_vertex = 0;
5484
5485 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5486 {
5488 next_unused_cell = triangulation.begin_raw(level + 1);
5489
5490 for (const auto &cell :
5491 triangulation.active_cell_iterators_on_level(level))
5492 if (cell->refine_flag_set())
5493 {
5494 // clear refinement flag
5495 cell->clear_refine_flag();
5496
5497 // search for next unused
5498 // vertex
5499 while (triangulation.vertices_used[next_unused_vertex] ==
5500 true)
5501 ++next_unused_vertex;
5502 Assert(
5503 next_unused_vertex < triangulation.vertices.size(),
5504 ExcMessage(
5505 "Internal error: During refinement, the triangulation "
5506 "wants to access an element of the 'vertices' array "
5507 "but it turns out that the array is not large enough."));
5508
5509 // Now we always ask the cell itself where to put
5510 // the new point. The cell in turn will query the
5511 // manifold object internally.
5512 triangulation.vertices[next_unused_vertex] =
5513 cell->center(true);
5514
5515 triangulation.vertices_used[next_unused_vertex] = true;
5516
5517 // search for next two unused cell (++ takes care of
5518 // the end of the vector)
5520 first_child,
5521 second_child;
5522 while (next_unused_cell->used() == true)
5523 ++next_unused_cell;
5524 first_child = next_unused_cell;
5525 first_child->set_used_flag();
5526 first_child->clear_user_data();
5527 ++next_unused_cell;
5528 AssertIsNotUsed(next_unused_cell);
5529 second_child = next_unused_cell;
5530 second_child->set_used_flag();
5531 second_child->clear_user_data();
5532
5533 types::subdomain_id subdomainid = cell->subdomain_id();
5534
5535 // insert first child
5536 cell->set_children(0, first_child->index());
5537 first_child->clear_children();
5538 first_child->set_bounding_object_indices(
5539 {cell->vertex_index(0), next_unused_vertex});
5540 first_child->set_material_id(cell->material_id());
5541 first_child->set_manifold_id(cell->manifold_id());
5542 first_child->set_subdomain_id(subdomainid);
5543 if (dim == spacedim - 1)
5544 first_child->set_direction_flag(cell->direction_flag());
5545
5546 first_child->set_parent(cell->index());
5547
5548 // Set manifold id of the right face. Only do this
5549 // on the first child.
5550 first_child->face(1)->set_manifold_id(cell->manifold_id());
5551
5552 // reset neighborship info (refer to
5553 // internal::TriangulationImplementation::TriaLevel<0> for
5554 // details)
5555 first_child->set_neighbor(1, second_child);
5556 if (cell->neighbor(0).state() != IteratorState::valid)
5557 first_child->set_neighbor(0, cell->neighbor(0));
5558 else if (cell->neighbor(0)->is_active())
5559 {
5560 // since the neighbors level is always <=level,
5561 // if the cell is active, then there are no
5562 // cells to the left which may want to know
5563 // about this new child cell.
5564 Assert(cell->neighbor(0)->level() <= cell->level(),
5566 first_child->set_neighbor(0, cell->neighbor(0));
5567 }
5568 else
5569 // left neighbor is refined
5570 {
5571 // set neighbor to cell on same level
5572 const unsigned int nbnb = cell->neighbor_of_neighbor(0);
5573 first_child->set_neighbor(0,
5574 cell->neighbor(0)->child(nbnb));
5575
5576 // reset neighbor info of all right descendant
5577 // of the left neighbor of cell
5579 left_neighbor = cell->neighbor(0);
5580 while (left_neighbor->has_children())
5581 {
5582 left_neighbor = left_neighbor->child(nbnb);
5583 left_neighbor->set_neighbor(nbnb, first_child);
5584 }
5585 }
5586
5587 // insert second child
5588 second_child->clear_children();
5589 second_child->set_bounding_object_indices(
5590 {next_unused_vertex, cell->vertex_index(1)});
5591 second_child->set_neighbor(0, first_child);
5592 second_child->set_material_id(cell->material_id());
5593 second_child->set_manifold_id(cell->manifold_id());
5594 second_child->set_subdomain_id(subdomainid);
5595 if (dim == spacedim - 1)
5596 second_child->set_direction_flag(cell->direction_flag());
5597
5598 if (cell->neighbor(1).state() != IteratorState::valid)
5599 second_child->set_neighbor(1, cell->neighbor(1));
5600 else if (cell->neighbor(1)->is_active())
5601 {
5602 Assert(cell->neighbor(1)->level() <= cell->level(),
5604 second_child->set_neighbor(1, cell->neighbor(1));
5605 }
5606 else
5607 // right neighbor is refined same as above
5608 {
5609 const unsigned int nbnb = cell->neighbor_of_neighbor(1);
5610 second_child->set_neighbor(
5611 1, cell->neighbor(1)->child(nbnb));
5612
5614 right_neighbor = cell->neighbor(1);
5615 while (right_neighbor->has_children())
5616 {
5617 right_neighbor = right_neighbor->child(nbnb);
5618 right_neighbor->set_neighbor(nbnb, second_child);
5619 }
5620 }
5621 // inform all listeners that cell refinement is done
5622 triangulation.signals.post_refinement_on_cell(cell);
5623 }
5624 }
5625
5626 // in 1d, we can not have distorted children unless the parent
5627 // was already distorted (that is because we don't use
5628 // boundary information for 1d triangulations). so return an
5629 // empty list
5631 }
5632
5633
5638 template <int spacedim>
5641 const bool check_for_distorted_cells)
5642 {
5643 const unsigned int dim = 2;
5644
5645 // First check whether we can get away with isotropic refinement, or
5646 // whether we need to run through the full anisotropic algorithm
5647 {
5648 bool do_isotropic_refinement = true;
5649 for (const auto &cell : triangulation.active_cell_iterators())
5650 if (cell->refine_flag_set() == RefinementCase<dim>::cut_x ||
5651 cell->refine_flag_set() == RefinementCase<dim>::cut_y)
5652 {
5653 do_isotropic_refinement = false;
5654 break;
5655 }
5656
5657 if (do_isotropic_refinement)
5659 check_for_distorted_cells);
5660 }
5661
5662 // If we get here, we are doing anisotropic refinement.
5663
5664 // Check whether a new level is needed. We have to check for
5665 // this on the highest level only
5666 for (const auto &cell : triangulation.active_cell_iterators_on_level(
5667 triangulation.levels.size() - 1))
5668 if (cell->refine_flag_set())
5669 {
5670 triangulation.levels.push_back(
5671 std::make_unique<
5673 break;
5674 }
5675
5676 // TODO[WB]: we clear user flags and pointers of lines; we're going
5677 // to use them to flag which lines need refinement
5680 line != triangulation.end_line();
5681 ++line)
5682 {
5683 line->clear_user_flag();
5684 line->clear_user_data();
5685 }
5686 // running over all cells and lines count the number
5687 // n_single_lines of lines which can be stored as single
5688 // lines, e.g. inner lines
5689 unsigned int n_single_lines = 0;
5690
5691 // New lines to be created: number lines which are stored in
5692 // pairs (the children of lines must be stored in pairs)
5693 unsigned int n_lines_in_pairs = 0;
5694
5695 // check how much space is needed on every level. We need not
5696 // check the highest level since either - on the highest level
5697 // no cells are flagged for refinement - there are, but
5698 // prepare_refinement added another empty level
5699 unsigned int needed_vertices = 0;
5700 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5701 {
5702 // count number of flagged cells on this level and compute
5703 // how many new vertices and new lines will be needed
5704 unsigned int needed_cells = 0;
5705
5706 for (const auto &cell :
5707 triangulation.active_cell_iterators_on_level(level))
5708 if (cell->refine_flag_set())
5709 {
5710 if (cell->refine_flag_set() == RefinementCase<dim>::cut_xy)
5711 {
5712 needed_cells += 4;
5713
5714 // new vertex at center of cell is needed in any
5715 // case
5716 ++needed_vertices;
5717
5718 // the four inner lines can be stored as singles
5719 n_single_lines += 4;
5720 }
5721 else // cut_x || cut_y
5722 {
5723 // set the flag showing that anisotropic
5724 // refinement is used for at least one cell
5725 triangulation.anisotropic_refinement = true;
5726
5727 needed_cells += 2;
5728 // no vertex at center
5729
5730 // the inner line can be stored as single
5731 n_single_lines += 1;
5732 }
5733
5734 // mark all faces (lines) for refinement; checking
5735 // locally whether the neighbor would also like to
5736 // refine them is rather difficult for lines so we
5737 // only flag them and after visiting all cells, we
5738 // decide which lines need refinement;
5739 for (const unsigned int line_no :
5741 {
5743 cell->refine_flag_set(), line_no) ==
5745 {
5747 line = cell->line(line_no);
5748 if (line->has_children() == false)
5749 line->set_user_flag();
5750 }
5751 }
5752 }
5753
5754
5755 // count number of used cells on the next higher level
5756 const unsigned int used_cells =
5757 std::count(triangulation.levels[level + 1]->cells.used.begin(),
5758 triangulation.levels[level + 1]->cells.used.end(),
5759 true);
5760
5761
5762 // reserve space for the used_cells cells already existing
5763 // on the next higher level as well as for the
5764 // needed_cells that will be created on that level
5765 reserve_space(*triangulation.levels[level + 1],
5766 used_cells + needed_cells,
5767 spacedim);
5768
5769 // reserve space for needed_cells new quads on the next
5770 // higher level
5771 reserve_space(triangulation.levels[level + 1]->cells,
5772 needed_cells,
5773 0);
5774 }
5775
5776 // now count the lines which were flagged for refinement
5779 line != triangulation.end_line();
5780 ++line)
5781 if (line->user_flag_set())
5782 {
5783 Assert(line->has_children() == false, ExcInternalError());
5784 n_lines_in_pairs += 2;
5785 needed_vertices += 1;
5786 }
5787 // reserve space for n_lines_in_pairs new lines. note, that
5788 // we can't reserve space for the single lines here as well,
5789 // as all the space reserved for lines in pairs would be
5790 // counted as unused and we would end up with too little space
5791 // to store all lines. memory reservation for n_single_lines
5792 // can only be done AFTER we refined the lines of the current
5793 // cells
5794 reserve_space(triangulation.faces->lines, n_lines_in_pairs, 0);
5795
5796 // add to needed vertices how many vertices are already in use
5797 needed_vertices += std::count(triangulation.vertices_used.begin(),
5798 triangulation.vertices_used.end(),
5799 true);
5800 // if we need more vertices: create them, if not: leave the
5801 // array as is, since shrinking is not really possible because
5802 // some of the vertices at the end may be in use
5803 if (needed_vertices > triangulation.vertices.size())
5804 {
5805 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
5806 triangulation.vertices_used.resize(needed_vertices, false);
5807 }
5808
5809
5810 // Do REFINEMENT on every level; exclude highest level as
5811 // above
5812
5813 // index of next unused vertex
5814 unsigned int next_unused_vertex = 0;
5815
5816 // first the refinement of lines. children are stored
5817 // pairwise
5818 {
5819 // only active objects can be refined further
5822 endl = triangulation.end_line();
5824 next_unused_line = triangulation.begin_raw_line();
5825
5826 for (; line != endl; ++line)
5827 if (line->user_flag_set())
5828 {
5829 // this line needs to be refined
5830
5831 // find the next unused vertex and set it
5832 // appropriately
5833 while (triangulation.vertices_used[next_unused_vertex] == true)
5834 ++next_unused_vertex;
5835 Assert(
5836 next_unused_vertex < triangulation.vertices.size(),
5837 ExcMessage(
5838 "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."));
5839 triangulation.vertices_used[next_unused_vertex] = true;
5840
5841 triangulation.vertices[next_unused_vertex] = line->center(true);
5842
5843 // now that we created the right point, make up the
5844 // two child lines. To this end, find a pair of
5845 // unused lines
5846 [[maybe_unused]] bool pair_found = false;
5847 for (; next_unused_line != endl; ++next_unused_line)
5848 if (!next_unused_line->used() &&
5849 !(++next_unused_line)->used())
5850 {
5851 // go back to the first of the two unused
5852 // lines
5853 --next_unused_line;
5854 pair_found = true;
5855 break;
5856 }
5857 Assert(pair_found, ExcInternalError());
5858
5859 // there are now two consecutive unused lines, such
5860 // that the children of a line will be consecutive.
5861 // then set the child pointer of the present line
5862 line->set_children(0, next_unused_line->index());
5863
5864 // set the two new lines
5866 children[2] = {next_unused_line, ++next_unused_line};
5867 // some tests; if any of the iterators should be
5868 // invalid, then already dereferencing will fail
5869 AssertIsNotUsed(children[0]);
5870 AssertIsNotUsed(children[1]);
5871
5872 children[0]->set_bounding_object_indices(
5873 {line->vertex_index(0), next_unused_vertex});
5874 children[1]->set_bounding_object_indices(
5875 {next_unused_vertex, line->vertex_index(1)});
5876
5877 children[0]->set_used_flag();
5878 children[1]->set_used_flag();
5879 children[0]->clear_children();
5880 children[1]->clear_children();
5881 children[0]->clear_user_data();
5882 children[1]->clear_user_data();
5883 children[0]->clear_user_flag();
5884 children[1]->clear_user_flag();
5885
5886
5887 children[0]->set_boundary_id_internal(line->boundary_id());
5888 children[1]->set_boundary_id_internal(line->boundary_id());
5889
5890 children[0]->set_manifold_id(line->manifold_id());
5891 children[1]->set_manifold_id(line->manifold_id());
5892
5893 // finally clear flag indicating the need for
5894 // refinement
5895 line->clear_user_flag();
5896 }
5897 }
5898
5899
5900 // Now set up the new cells
5901
5902 // reserve space for inner lines (can be stored as single
5903 // lines)
5904 reserve_space(triangulation.faces->lines, 0, n_single_lines);
5905
5907 cells_with_distorted_children;
5908
5909 // reset next_unused_line, as now also single empty places in
5910 // the vector can be used
5912 next_unused_line = triangulation.begin_raw_line();
5913
5914 for (int level = 0;
5915 level < static_cast<int>(triangulation.levels.size()) - 1;
5916 ++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 // actually set up the children and update neighbor
5926 // information
5928 next_unused_vertex,
5929 next_unused_line,
5930 next_unused_cell,
5931 cell);
5932
5933 if (check_for_distorted_cells &&
5934 has_distorted_children<dim, spacedim>(cell))
5935 cells_with_distorted_children.distorted_cells.push_back(
5936 cell);
5937 // inform all listeners that cell refinement is done
5938 triangulation.signals.post_refinement_on_cell(cell);
5939 }
5940 }
5941
5942 return cells_with_distorted_children;
5943 }
5944
5945
5946 template <int spacedim>
5949 const bool check_for_distorted_cells)
5950 {
5951 static const int dim = 3;
5952 static const unsigned int X = numbers::invalid_unsigned_int;
5953 using raw_line_iterator =
5955 using raw_quad_iterator =
5957
5958 Assert(spacedim == 3, ExcNotImplemented());
5959
5960 Assert(triangulation.vertices.size() ==
5961 triangulation.vertices_used.size(),
5963
5964 // Check whether a new level is needed. We have to check for
5965 // this on the highest level only
5966 for (const auto &cell : triangulation.active_cell_iterators_on_level(
5967 triangulation.levels.size() - 1))
5968 if (cell->refine_flag_set())
5969 {
5970 triangulation.levels.push_back(
5971 std::make_unique<
5973 break;
5974 }
5975
5976 // first clear user flags for quads and lines; we're going to
5977 // use them to flag which lines and quads need refinement
5978 triangulation.faces->quads.clear_user_data();
5979 triangulation.faces->lines.clear_user_flags();
5980 triangulation.faces->quads.clear_user_flags();
5981
5982 // check how much space is needed on every level. We need not
5983 // check the highest level since either
5984 // - on the highest level no cells are flagged for refinement
5985 // - there are, but prepare_refinement added another empty
5986 // level which then is the highest level
5987
5988 // variables to hold the number of newly to be created
5989 // vertices, lines and quads. as these are stored globally,
5990 // declare them outside the loop over al levels. we need lines
5991 // and quads in pairs for refinement of old ones and lines and
5992 // quads, that can be stored as single ones, as they are newly
5993 // created in the inside of an existing cell
5994 unsigned int needed_vertices = 0;
5995 unsigned int needed_lines_single = 0;
5996 unsigned int needed_quads_single = 0;
5997 unsigned int needed_lines_pair = 0;
5998 unsigned int needed_quads_pair = 0;
5999 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
6000 {
6001 unsigned int new_cells = 0;
6002
6003 for (const auto &cell :
6004 triangulation.active_cell_iterators_on_level(level))
6005 if (cell->refine_flag_set())
6006 {
6007 // Only support isotropic refinement
6008 Assert(cell->refine_flag_set() ==
6011
6012 // Now count up how many new cells, faces, edges, and vertices
6013 // we will need to allocate to do this refinement.
6014 new_cells += cell->reference_cell().n_isotropic_children();
6015
6016 if (cell->reference_cell() == ReferenceCells::Hexahedron)
6017 {
6018 ++needed_vertices;
6019 needed_lines_single += 6;
6020 needed_quads_single += 12;
6021 }
6022 else if (cell->reference_cell() ==
6024 {
6025 needed_lines_single += 1;
6026 needed_quads_single += 8;
6027 }
6028 else
6029 {
6031 }
6032
6033 // Also check whether we have to refine any of the faces and
6034 // edges that bound this cell. They may of course already be
6035 // refined, so we only *mark* them for refinement by setting
6036 // the user flags
6037 for (const auto face : cell->face_indices())
6038 if (cell->face(face)->n_children() == 0)
6039 cell->face(face)->set_user_flag();
6040 else
6041 Assert(cell->face(face)->n_children() ==
6042 cell->reference_cell()
6043 .face_reference_cell(face)
6044 .n_isotropic_children(),
6046
6047 for (const auto line : cell->line_indices())
6048 if (cell->line(line)->has_children() == false)
6049 cell->line(line)->set_user_flag();
6050 else
6051 Assert(cell->line(line)->n_children() == 2,
6053 }
6054
6055 const unsigned int used_cells =
6056 std::count(triangulation.levels[level + 1]->cells.used.begin(),
6057 triangulation.levels[level + 1]->cells.used.end(),
6058 true);
6059
6060 if (triangulation.all_reference_cells_are_hyper_cube())
6061 reserve_space(*triangulation.levels[level + 1],
6062 used_cells + new_cells,
6063 spacedim,
6064 false);
6065 else
6066 reserve_space(*triangulation.levels[level + 1],
6067 used_cells + new_cells,
6068 spacedim,
6069 true);
6070
6071 reserve_space(triangulation.levels[level + 1]->cells, new_cells);
6072 }
6073
6074 // now count the quads and lines which were flagged for
6075 // refinement
6078 quad != triangulation.end_quad();
6079 ++quad)
6080 {
6081 if (quad->user_flag_set() == false)
6082 continue;
6083
6084 if (quad->reference_cell() == ReferenceCells::Quadrilateral)
6085 {
6086 needed_quads_pair += 4;
6087 needed_lines_pair += 4;
6088 needed_vertices += 1;
6089 }
6090 else if (quad->reference_cell() == ReferenceCells::Triangle)
6091 {
6092 needed_quads_pair += 4;
6093 needed_lines_single += 3;
6094 }
6095 else
6096 {
6098 }
6099 }
6100
6103 line != triangulation.end_line();
6104 ++line)
6105 {
6106 if (line->user_flag_set() == false)
6107 continue;
6108
6109 needed_lines_pair += 2;
6110 needed_vertices += 1;
6111 }
6112
6113 reserve_space(triangulation.faces->lines,
6114 needed_lines_pair,
6115 needed_lines_single);
6117 needed_quads_pair,
6118 needed_quads_single);
6119 reserve_space(triangulation.faces->quads,
6120 needed_quads_pair,
6121 needed_quads_single);
6122
6123
6124 // add to needed vertices how many vertices are already in use
6125 needed_vertices += std::count(triangulation.vertices_used.begin(),
6126 triangulation.vertices_used.end(),
6127 true);
6128
6129 if (needed_vertices > triangulation.vertices.size())
6130 {
6131 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
6132 triangulation.vertices_used.resize(needed_vertices, false);
6133 }
6134
6135 //-----------------------------------------
6136 // Before we start with the actual refinement, we do some
6137 // sanity checks if in debug mode. especially, we try to catch
6138 // the notorious problem with lines being twice refined,
6139 // i.e. there are cells adjacent at one line ("around the
6140 // edge", but not at a face), with two cells differing by more
6141 // than one refinement level
6142 //
6143 // this check is very simple to implement here, since we have
6144 // all lines flagged if they shall be refined
6145 if constexpr (running_in_debug_mode())
6146 {
6147 for (const auto &cell : triangulation.active_cell_iterators())
6148 if (!cell->refine_flag_set())
6149 for (unsigned int line_n = 0; line_n < cell->n_lines();
6150 ++line_n)
6151 if (cell->line(line_n)->has_children())
6152 for (unsigned int c = 0; c < 2; ++c)
6153 Assert(cell->line(line_n)->child(c)->user_flag_set() ==
6154 false,
6156 }
6157
6158 unsigned int current_vertex = 0;
6159
6160 // helper function - find the next available vertex number and mark it
6161 // as used.
6162 auto get_next_unused_vertex = [](const unsigned int current_vertex,
6163 std::vector<bool> &vertices_used) {
6164 unsigned int next_vertex = current_vertex;
6165 while (next_vertex < vertices_used.size() &&
6166 vertices_used[next_vertex] == true)
6167 ++next_vertex;
6168 Assert(next_vertex < vertices_used.size(), ExcInternalError());
6169 vertices_used[next_vertex] = true;
6170
6171 return next_vertex;
6172 };
6173
6174 // LINES
6175 {
6178 endl = triangulation.end_line();
6179 raw_line_iterator next_unused_line = triangulation.begin_raw_line();
6180
6181 for (; line != endl; ++line)
6182 {
6183 if (line->user_flag_set() == false)
6184 continue;
6185
6186 next_unused_line =
6187 triangulation.faces->lines.template next_free_pair_object<1>(
6189 Assert(next_unused_line.state() == IteratorState::valid,
6191
6192 // now we found two consecutive unused lines, such
6193 // that the children of a line will be consecutive.
6194 // then set the child pointer of the present line
6195 line->set_children(0, next_unused_line->index());
6196
6197 const std::array<raw_line_iterator, 2> children{
6198 {next_unused_line, ++next_unused_line}};
6199
6200 AssertIsNotUsed(children[0]);
6201 AssertIsNotUsed(children[1]);
6202
6203 current_vertex =
6204 get_next_unused_vertex(current_vertex,
6205 triangulation.vertices_used);
6206 triangulation.vertices[current_vertex] = line->center(true);
6207
6208 children[0]->set_bounding_object_indices(
6209 {line->vertex_index(0), current_vertex});
6210 children[1]->set_bounding_object_indices(
6211 {current_vertex, line->vertex_index(1)});
6212
6213 const auto manifold_id = line->manifold_id();
6214 const auto boundary_id = line->boundary_id();
6215 for (const auto &child : children)
6216 {
6217 child->set_used_flag();
6218 child->clear_children();
6219 child->clear_user_data();
6220 child->clear_user_flag();
6221 child->set_boundary_id_internal(boundary_id);
6222 child->set_manifold_id(manifold_id);
6223 }
6224
6225 line->clear_user_flag();
6226 }
6227 }
6228
6229 // QUADS
6230 {
6232 quad = triangulation.begin_quad(),
6233 endq = triangulation.end_quad();
6234
6235 for (; quad != endq; ++quad)
6236 {
6237 if (quad->user_flag_set() == false)
6238 continue;
6239
6240 const auto reference_face_type = quad->reference_cell();
6241
6242 // 1) create new lines (property is set later)
6243 // maximum of 4 new lines (4 quadrilateral, 3 triangle)
6244 std::array<raw_line_iterator, 4> new_lines;
6245 if (reference_face_type == ReferenceCells::Quadrilateral)
6246 {
6247 for (unsigned int l = 0; l < 2; ++l)
6248 {
6249 auto next_unused_line =
6250 triangulation.faces->lines
6251 .template next_free_pair_object<1>(triangulation);
6252 new_lines[2 * l] = next_unused_line;
6253 new_lines[2 * l + 1] = ++next_unused_line;
6254 }
6255 }
6256 else if (reference_face_type == ReferenceCells::Triangle)
6257 {
6258 for (unsigned int l = 0; l < 3; ++l)
6259 new_lines[l] =
6260 triangulation.faces->lines
6261 .template next_free_single_object<1>(triangulation);
6262 }
6263 else
6264 {
6266 }
6267
6268 if constexpr (running_in_debug_mode())
6269 {
6270 for (const unsigned int line : quad->line_indices())
6271 AssertIsNotUsed(new_lines[line]);
6272 }
6273
6274 // 2) create new quads (properties are set below). Both triangles
6275 // and quads are divided in four.
6276 std::array<raw_quad_iterator, 4> new_quads;
6277 for (unsigned int q = 0; q < 2; ++q)
6278 {
6279 auto next_unused_quad =
6280 triangulation.faces->quads
6281 .template next_free_pair_object<2>(triangulation);
6282
6283 new_quads[2 * q] = next_unused_quad;
6284 new_quads[2 * q + 1] = ++next_unused_quad;
6285
6286 quad->set_children(2 * q, new_quads[2 * q]->index());
6287 }
6288 quad->set_refinement_case(RefinementCase<2>::cut_xy);
6289
6290 if constexpr (running_in_debug_mode())
6291 {
6292 for (const auto &quad : new_quads)
6293 AssertIsNotUsed(quad);
6294 }
6295
6296 // 3) set vertex indices and set new vertex
6297
6298 // Maximum of 9 vertices per refined quad (9 for Quadrilateral, 6
6299 // for Triangle)
6300 std::array<unsigned int, 9> vertex_indices = {};
6301 unsigned int k = 0;
6302 for (const auto i : quad->vertex_indices())
6303 vertex_indices[k++] = quad->vertex_index(i);
6304
6305 for (const auto i : quad->line_indices())
6306 vertex_indices[k++] = quad->line(i)->child(0)->vertex_index(1);
6307
6308 if (reference_face_type == ReferenceCells::Quadrilateral)
6309 {
6310 current_vertex =
6311 get_next_unused_vertex(current_vertex,
6312 triangulation.vertices_used);
6313 vertex_indices[k++] = current_vertex;
6314
6315 triangulation.vertices[current_vertex] =
6316 quad->center(true, true);
6317 }
6318
6319 // 4) set new lines on quads and their properties
6320 std::array<raw_line_iterator, 12> lines;
6321 unsigned int n_lines = 0;
6322 for (unsigned int l = 0; l < quad->n_lines(); ++l)
6323 for (unsigned int c = 0; c < 2; ++c)
6324 lines[n_lines++] = quad->line(l)->child(
6325 child_line_index(c, quad->line_orientation(l)));
6326
6327 for (unsigned int l = 0; l < quad->n_lines(); ++l)
6328 lines[n_lines++] = new_lines[l];
6329
6330 std::array<int, 12> line_indices;
6331 for (unsigned int i = 0; i < n_lines; ++i)
6332 line_indices[i] = lines[i]->index();
6333
6334 static constexpr ::ndarray<unsigned int, 12, 2>
6335 line_vertices_quad{{{{0, 4}},
6336 {{4, 2}},
6337 {{1, 5}},
6338 {{5, 3}},
6339 {{0, 6}},
6340 {{6, 1}},
6341 {{2, 7}},
6342 {{7, 3}},
6343 {{6, 8}},
6344 {{8, 7}},
6345 {{4, 8}},
6346 {{8, 5}}}};
6347
6348 static constexpr ::ndarray<unsigned int, 4, 4>
6349 quad_lines_quad{{{{0, 8, 4, 10}},
6350 {{8, 2, 5, 11}},
6351 {{1, 9, 10, 6}},
6352 {{9, 3, 11, 7}}}};
6353
6354 static constexpr ::ndarray<unsigned int, 12, 2>
6355 line_vertices_tri{{{{0, 3}},
6356 {{3, 1}},
6357 {{1, 4}},
6358 {{4, 2}},
6359 {{2, 5}},
6360 {{5, 0}},
6361 {{3, 4}},
6362 {{4, 5}},
6363 {{3, 5}},
6364 {{X, X}},
6365 {{X, X}},
6366 {{X, X}}}};
6367
6368 static constexpr ::ndarray<unsigned int, 4, 4>
6369 quad_lines_tri{{{{0, 8, 5, X}},
6370 {{1, 2, 6, X}},
6371 {{7, 3, 4, X}},
6372 {{6, 7, 8, X}}}};
6373
6374 static constexpr ::ndarray<unsigned int, 4, 4, 2>
6375 quad_line_vertices_tri{
6376 {{{{{0, 3}}, {{3, 5}}, {{5, 0}}, {{X, X}}}},
6377 {{{{3, 1}}, {{1, 4}}, {{4, 3}}, {{X, X}}}},
6378 {{{{5, 4}}, {{4, 2}}, {{2, 5}}, {{X, X}}}},
6379 {{{{3, 4}}, {{4, 5}}, {{5, 3}}, {{X, X}}}}}};
6380
6381 const auto &line_vertices =
6382 (reference_face_type == ReferenceCells::Quadrilateral) ?
6383 line_vertices_quad :
6384 line_vertices_tri;
6385 const auto &quad_lines =
6386 (reference_face_type == ReferenceCells::Quadrilateral) ?
6387 quad_lines_quad :
6388 quad_lines_tri;
6389
6390 for (unsigned int i = 0, j = 2 * quad->n_lines();
6391 i < quad->n_lines();
6392 ++i, ++j)
6393 {
6394 auto &new_line = new_lines[i];
6395 new_line->set_bounding_object_indices(
6396 {vertex_indices[line_vertices[j][0]],
6397 vertex_indices[line_vertices[j][1]]});
6398 new_line->set_used_flag();
6399 new_line->clear_user_flag();
6400 new_line->clear_user_data();
6401 new_line->clear_children();
6402 new_line->set_boundary_id_internal(quad->boundary_id());
6403 new_line->set_manifold_id(quad->manifold_id());
6404 }
6405
6406 // 5) set properties of quads
6407 for (unsigned int i = 0; i < new_quads.size(); ++i)
6408 {
6409 auto &new_quad = new_quads[i];
6410
6411 // TODO: we assume here that all children have the same type
6412 // as the parent
6413 triangulation.faces->set_quad_type(new_quad->index(),
6414 reference_face_type);
6415
6416 if (reference_face_type == ReferenceCells::Triangle)
6417 new_quad->set_bounding_object_indices(
6418 {line_indices[quad_lines[i][0]],
6419 line_indices[quad_lines[i][1]],
6420 line_indices[quad_lines[i][2]]});
6421 else if (reference_face_type == ReferenceCells::Quadrilateral)
6422 new_quad->set_bounding_object_indices(
6423 {line_indices[quad_lines[i][0]],
6424 line_indices[quad_lines[i][1]],
6425 line_indices[quad_lines[i][2]],
6426 line_indices[quad_lines[i][3]]});
6427 else
6429
6430 new_quad->set_used_flag();
6431 new_quad->clear_user_flag();
6432 new_quad->clear_user_data();
6433 new_quad->clear_children();
6434 new_quad->set_boundary_id_internal(quad->boundary_id());
6435 new_quad->set_manifold_id(quad->manifold_id());
6436
6437 [[maybe_unused]] std::set<unsigned int> s;
6438
6439 // ... and fix orientation of lines of face for triangles,
6440 // using an expensive algorithm, quadrilaterals are treated
6441 // a few lines below by a cheaper algorithm
6442 if (reference_face_type == ReferenceCells::Triangle)
6443 {
6444 for (const auto f : new_quad->line_indices())
6445 {
6446 const std::array<unsigned int, 2> vertices_0 = {
6447 {lines[quad_lines[i][f]]->vertex_index(0),
6448 lines[quad_lines[i][f]]->vertex_index(1)}};
6449
6450 const std::array<unsigned int, 2> vertices_1 = {
6451 {vertex_indices[quad_line_vertices_tri[i][f][0]],
6452 vertex_indices[quad_line_vertices_tri[i][f][1]]}};
6453
6454 const auto orientation =
6456 make_array_view(vertices_0),
6457 make_array_view(vertices_1));
6458
6459 if constexpr (library_build_mode ==
6461 {
6462 for (const auto i : vertices_0)
6463 s.insert(i);
6464 for (const auto i : vertices_1)
6465 s.insert(i);
6466 }
6467
6468 new_quad->set_line_orientation(f, orientation);
6469 }
6470 if constexpr (library_build_mode ==
6472 {
6473 AssertDimension(s.size(), 3);
6474 }
6475 }
6476 }
6477
6478 // fix orientation of lines of faces for quadrilaterals with
6479 // cheap algorithm
6480 if (reference_face_type == ReferenceCells::Quadrilateral)
6481 {
6482 static constexpr ::ndarray<unsigned int, 4, 2>
6483 quad_child_boundary_lines{
6484 {{{0, 2}}, {{1, 3}}, {{0, 1}}, {{2, 3}}}};
6485
6486 for (unsigned int i = 0; i < 4; ++i)
6487 for (unsigned int j = 0; j < 2; ++j)
6488 new_quads[quad_child_boundary_lines[i][j]]
6489 ->set_line_orientation(i, quad->line_orientation(i));
6490 }
6491
6492 quad->clear_user_flag();
6493 }
6494 }
6495
6497 cells_with_distorted_children;
6498
6501 for (unsigned int level = 0; level != triangulation.levels.size() - 1;
6502 ++level)
6503 {
6505 next_unused_hex = triangulation.begin_raw_hex(level + 1);
6506 Assert(hex == triangulation.end() ||
6507 hex->level() >= static_cast<int>(level),
6509
6510 for (; hex != triangulation.end() &&
6511 hex->level() == static_cast<int>(level);
6512 ++hex)
6513 {
6514 if (hex->refine_flag_set() ==
6516 continue;
6517
6518 const auto &reference_cell_type = hex->reference_cell();
6519
6520 const RefinementCase<dim> ref_case = hex->refine_flag_set();
6521 hex->clear_refine_flag();
6522 hex->set_refinement_case(ref_case);
6523
6524 unsigned int n_new_lines = 0;
6525 unsigned int n_new_quads = 0;
6526 unsigned int n_new_hexes = 0;
6527
6528 if (reference_cell_type == ReferenceCells::Hexahedron)
6529 {
6530 n_new_lines = 6;
6531 n_new_quads = 12;
6532 n_new_hexes = 8;
6533 }
6534 else if (reference_cell_type == ReferenceCells::Tetrahedron)
6535 {
6536 n_new_lines = 1;
6537 n_new_quads = 8;
6538 n_new_hexes = 8;
6539 }
6540 else
6542
6543 std::array<raw_line_iterator, 6> new_lines;
6544 for (unsigned int i = 0; i < n_new_lines; ++i)
6545 {
6546 new_lines[i] =
6547 triangulation.faces->lines
6548 .template next_free_single_object<1>(triangulation);
6549
6550 AssertIsNotUsed(new_lines[i]);
6551 new_lines[i]->set_used_flag();
6552 new_lines[i]->clear_user_flag();
6553 new_lines[i]->clear_user_data();
6554 new_lines[i]->clear_children();
6555 new_lines[i]->set_boundary_id_internal(
6557 new_lines[i]->set_manifold_id(hex->manifold_id());
6558 }
6559
6560 std::array<raw_quad_iterator, 12> new_quads;
6561 for (unsigned int i = 0; i < n_new_quads; ++i)
6562 {
6563 new_quads[i] =
6564 triangulation.faces->quads
6565 .template next_free_single_object<2>(triangulation);
6566
6567 auto &new_quad = new_quads[i];
6568
6569 // TODO: faces of children have the same type as the faces
6570 // of the parent
6571 triangulation.faces->set_quad_type(
6572 new_quad->index(),
6573 reference_cell_type.face_reference_cell(0));
6574
6575 AssertIsNotUsed(new_quad);
6576 new_quad->set_used_flag();
6577 new_quad->clear_user_flag();
6578 new_quad->clear_user_data();
6579 new_quad->clear_children();
6580 new_quad->set_boundary_id_internal(
6582 new_quad->set_manifold_id(hex->manifold_id());
6583 for (const auto j : new_quads[i]->line_indices())
6584 new_quad->set_line_orientation(
6586 }
6587
6588 // we always get 8 children per refined cell
6589 std::array<
6591 8>
6592 new_hexes;
6593 {
6594 for (unsigned int i = 0; i < n_new_hexes; ++i)
6595 {
6596 if (i % 2 == 0)
6597 next_unused_hex =
6598 triangulation.levels[level + 1]->cells.next_free_hex(
6599 triangulation, level + 1);
6600 else
6601 ++next_unused_hex;
6602
6603 new_hexes[i] = next_unused_hex;
6604
6605 auto &new_hex = new_hexes[i];
6606
6607 // children have the same type as the parent
6608 triangulation.levels[new_hex->level()]
6609 ->reference_cell[new_hex->index()] =
6610 reference_cell_type;
6611
6612 AssertIsNotUsed(new_hex);
6613 new_hex->set_used_flag();
6614 new_hex->clear_user_flag();
6615 new_hex->clear_user_data();
6616 new_hex->clear_children();
6617 new_hex->set_material_id(hex->material_id());
6618 new_hex->set_manifold_id(hex->manifold_id());
6619 new_hex->set_subdomain_id(hex->subdomain_id());
6620
6621 if (i % 2)
6622 new_hex->set_parent(hex->index());
6623
6624 // set the orientation flag to its default state for all
6625 // faces initially. later on go the other way round and
6626 // reset faces that are at the boundary of the mother cube
6627 for (const auto f : new_hex->face_indices())
6628 new_hex->set_combined_face_orientation(
6630 }
6631 for (unsigned int i = 0; i < n_new_hexes / 2; ++i)
6632 hex->set_children(2 * i, new_hexes[2 * i]->index());
6633 }
6634
6635 {
6636 // load vertex indices
6637 std::array<unsigned int, 27> vertex_indices = {};
6638
6639 {
6640 unsigned int k = 0;
6641
6642 // avoid a compiler warning by fixing the max number of
6643 // loop iterations to 8
6644 const unsigned int n_vertices =
6645 std::min(hex->n_vertices(), 8u);
6646 for (unsigned int i = 0; i < n_vertices; ++i)
6647 vertex_indices[k++] = hex->vertex_index(i);
6648
6649 const std::array<unsigned int, 12> line_indices =
6650 TriaAccessorImplementation::Implementation::
6651 get_line_indices_of_cell(*hex);
6652
6653 // For the tetrahedron the parent consists of the vertices
6654 // 0,1,2,3, the new vertices 4-9 are defined as the
6655 // midpoints of the edges: 4 -> (0,1), 5 -> (1,2), 6 ->
6656 // (2,0), 7 -> (0,3), 8 -> (1,3), 9 -> (2,3).
6657 // Order is defined by the reference cell, see
6658 // https://dealii.org/developer/doxygen/deal.II/group__simplex.html#simplex_reference_cells.
6659
6660 // Avoid a compiler warning by fixing the max number of loop
6661 // iterations to 12
6662 const unsigned int n_lines = std::min(hex->n_lines(), 12u);
6663 for (unsigned int l = 0; l < n_lines; ++l)
6664 {
6665 raw_line_iterator line(&triangulation,
6666 0,
6667 line_indices[l]);
6668 vertex_indices[k++] = line->child(0)->vertex_index(1);
6669 }
6670
6671 if (reference_cell_type == ReferenceCells::Hexahedron)
6672 {
6673 for (const unsigned int i : hex->face_indices())
6674 vertex_indices[k++] =
6675 hex->face(i)->child(0)->vertex_index(3);
6676
6677 // Set single new vertex in the center
6678 current_vertex =
6679 get_next_unused_vertex(current_vertex,
6680 triangulation.vertices_used);
6681 vertex_indices[k++] = current_vertex;
6682
6683 triangulation.vertices[current_vertex] =
6684 hex->center(true, true);
6685 }
6686 }
6687
6688 unsigned int chosen_line_tetrahedron = 0;
6689 // set up new lines
6690 if (reference_cell_type == ReferenceCells::Hexahedron)
6691 {
6692 static constexpr ::ndarray<unsigned int, 6, 2>
6693 new_line_vertices = {{{{22, 26}},
6694 {{26, 23}},
6695 {{20, 26}},
6696 {{26, 21}},
6697 {{24, 26}},
6698 {{26, 25}}}};
6699 for (unsigned int i = 0; i < n_new_lines; ++i)
6700 new_lines[i]->set_bounding_object_indices(
6701 {vertex_indices[new_line_vertices[i][0]],
6702 vertex_indices[new_line_vertices[i][1]]});
6703 }
6704 else if (reference_cell_type == ReferenceCells::Tetrahedron)
6705 {
6706 // in the tetrahedron case, we have the three
6707 // possibilities (6,8), (5,7), (4,9) -> pick the
6708 // shortest line to guarantee the best possible aspect
6709 // ratios
6710 static constexpr ::ndarray<unsigned int, 3, 2>
6711 new_line_vertices = {{{{6, 8}}, {{5, 7}}, {{4, 9}}}};
6712
6713 // choose line to cut either by refinement case or by
6714 // shortest distance between edge midpoints
6715 std::uint8_t refinement_choice = hex->refine_choice();
6716 if (refinement_choice ==
6717 static_cast<char>(
6719 {
6720 const auto &vertices = triangulation.get_vertices();
6721 double min_distance =
6722 std::numeric_limits<double>::infinity();
6723 for (unsigned int i = 0; i < new_line_vertices.size();
6724 ++i)
6725 {
6726 const double current_distance =
6727 vertices
6728 [vertex_indices[new_line_vertices[i][0]]]
6729 .distance(
6730 vertices[vertex_indices
6731 [new_line_vertices[i][1]]]);
6732 if (current_distance < min_distance)
6733 {
6734 chosen_line_tetrahedron = i;
6735 min_distance = current_distance;
6736 }
6737 }
6738 }
6739 else if (refinement_choice ==
6740 static_cast<char>(
6742 chosen_line_tetrahedron = 0;
6743 else if (refinement_choice ==
6744 static_cast<char>(
6746 chosen_line_tetrahedron = 1;
6747 else if (refinement_choice ==
6748 static_cast<char>(
6750 chosen_line_tetrahedron = 2;
6751 else
6753
6754 hex->set_refinement_case(
6755 RefinementCase<dim>(chosen_line_tetrahedron + 1));
6756
6757 new_lines[0]->set_bounding_object_indices(
6759 [new_line_vertices[chosen_line_tetrahedron][0]],
6761 [new_line_vertices[chosen_line_tetrahedron][1]]});
6762 }
6763
6764 // set up new quads
6765 {
6766 boost::container::small_vector<raw_line_iterator, 30>
6767 relevant_lines;
6768
6769 if (reference_cell_type == ReferenceCells::Hexahedron)
6770 {
6771 relevant_lines.resize(30);
6772 for (unsigned int f = 0, k = 0; f < 6; ++f)
6773 for (unsigned int c = 0; c < 4; ++c, ++k)
6774 {
6775 static constexpr ::
6776 ndarray<unsigned int, 4, 2>
6777 temp = {
6778 {{{0, 1}}, {{3, 0}}, {{0, 3}}, {{3, 2}}}};
6779
6780 relevant_lines[k] =
6781 hex->face(f)
6782 ->isotropic_child(
6784 standard_to_real_face_vertex(
6785 temp[c][0],
6786 hex->face_orientation(f),
6787 hex->face_flip(f),
6788 hex->face_rotation(f)))
6789 ->line(GeometryInfo<dim>::
6790 standard_to_real_face_line(
6791 temp[c][1],
6792 hex->face_orientation(f),
6793 hex->face_flip(f),
6794 hex->face_rotation(f)));
6795 }
6796
6797 for (unsigned int i = 0, k = 24; i < 6; ++i, ++k)
6798 relevant_lines[k] = new_lines[i];
6799 }
6800 else if (reference_cell_type == ReferenceCells::Tetrahedron)
6801 {
6802 // The order of the lines is defined by the ordering
6803 // of the faces of the reference cell and the ordering
6804 // of the lines within a face.
6805 // Each face is split into 4 child triangles, the
6806 // relevant lines are defined by the vertices of the
6807 // center triangles: 0 -> (4,5), 1 -> (5,6), 2 -> (4,6),
6808 // 3 -> (4,7), 4 -> (7,8), 5 -> (4,8), 6 -> (6,9), 7 ->
6809 // (9,7), 8 -> (6,7), 9 -> (5,8), 10 -> (8,9), 11 ->
6810 // (5,9), Line 12 is determined by
6811 // chosen_line_tetrahedron i.e. (6,8), (5,7) or (4,9)
6812
6813 relevant_lines.resize(13);
6814
6815 unsigned int k = 0;
6816 for (unsigned int f = 0; f < 4; ++f)
6817 for (unsigned int l = 0; l < 3; ++l, ++k)
6818 {
6819 // TODO: add comment
6820 static const std::
6821 array<std::array<unsigned int, 3>, 6>
6822 table = {{{{1, 0, 2}}, // 0
6823 {{0, 1, 2}},
6824 {{0, 2, 1}}, // 2
6825 {{1, 2, 0}},
6826 {{2, 1, 0}}, // 4
6827 {{2, 0, 1}}}};
6828
6829 const auto combined_orientation =
6830 hex->combined_face_orientation(f);
6831 relevant_lines[k] =
6832 hex->face(f)
6833 ->child(3 /*center triangle*/)
6834 ->line(table[combined_orientation][l]);
6835 }
6836
6837 relevant_lines[k++] = new_lines[0];
6838 AssertDimension(k, 13);
6839 }
6840 else
6842
6843 boost::container::small_vector<unsigned int, 30>
6844 relevant_line_indices(relevant_lines.size());
6845 for (unsigned int i = 0; i < relevant_line_indices.size();
6846 ++i)
6847 relevant_line_indices[i] = relevant_lines[i]->index();
6848
6849 // It is easierst to start at table cell_vertices,
6850 // there the vertices are listed which build up the
6851 // 8 child tets. To build the child tets, 8 new faces are
6852 // needed. The the vertices, which define the lines of these
6853 // new faces are listed in table_tet. Now only the
6854 // corresponding index of the lines and quads have to be
6855 // listed in new_quad_lines_tet and cell_quads_tet.
6856 const auto &new_quad_lines =
6857 hex->reference_cell().new_isotropic_child_face_lines(
6858 chosen_line_tetrahedron);
6859
6860 // The first 4 define the faces which cut off the
6861 // parent tetrahedron at the edges. the numbers are the
6862 // index of the relevant_lines defined above the last 4
6863 // faces cut apart the remaining octahedron, such that all
6864 // of these contain line number 12. the ordering of the
6865 // faces is arbitrary, the ordering within the faces has to
6866 // follow the righthand convention for triangles
6867 // The table defines the vertices of the lines above
6868 // see relevant_lines for mapping between line indices and
6869 // vertex numbering
6870 const auto &table =
6871 hex->reference_cell()
6872 .new_isotropic_child_face_line_vertices(
6873 chosen_line_tetrahedron);
6874
6875 static constexpr ::ndarray<unsigned int, 4, 2>
6876 representative_lines{
6877 {{{0, 2}}, {{2, 0}}, {{3, 3}}, {{1, 1}}}};
6878
6879 for (unsigned int q = 0; q < n_new_quads; ++q)
6880 {
6881 auto &new_quad = new_quads[q];
6882
6883 if (new_quad->n_lines() == 3)
6884 new_quad->set_bounding_object_indices(
6885 {relevant_line_indices[new_quad_lines[q][0]],
6886 relevant_line_indices[new_quad_lines[q][1]],
6887 relevant_line_indices[new_quad_lines[q][2]]});
6888 else if (new_quad->n_lines() == 4)
6889 new_quad->set_bounding_object_indices(
6890 {relevant_line_indices[new_quad_lines[q][0]],
6891 relevant_line_indices[new_quad_lines[q][1]],
6892 relevant_line_indices[new_quad_lines[q][2]],
6893 relevant_line_indices[new_quad_lines[q][3]]});
6894 else
6896
6897 // On hexes, we must only determine a single line
6898 // according to the representative_lines array above
6899 // (this saves expensive operations), for tets we do
6900 // all lines manually
6901 const unsigned int n_compute_lines =
6902 reference_cell_type == ReferenceCells::Hexahedron ?
6903 1 :
6904 new_quad->n_lines();
6905 for (unsigned int line = 0; line < n_compute_lines;
6906 ++line)
6907 {
6908 const unsigned int l =
6909 (reference_cell_type ==
6911 representative_lines[q % 4][0] :
6912 line;
6913
6914 const std::array<unsigned int, 2> vertices_0 = {
6915 {relevant_lines[new_quad_lines[q][l]]
6916 ->vertex_index(0),
6917 relevant_lines[new_quad_lines[q][l]]
6918 ->vertex_index(1)}};
6919
6920 const std::array<unsigned int, 2> vertices_1 = {
6921 {vertex_indices[table[q][l][0]],
6922 vertex_indices[table[q][l][1]]}};
6923
6924 const auto orientation =
6926 make_array_view(vertices_0),
6927 make_array_view(vertices_1));
6928
6929 new_quad->set_line_orientation(l, orientation);
6930
6931 // on a hex, inject the status of the current line
6932 // also to the line on the other quad along the
6933 // same direction
6934 if (reference_cell_type ==
6936 new_quads[representative_lines[q % 4][1] + q -
6937 (q % 4)]
6938 ->set_line_orientation(l, orientation);
6939 }
6940 }
6941 }
6942
6943 // set up new hex
6944 {
6945 std::array<int, 36> quad_indices;
6946
6947 if (reference_cell_type == ReferenceCells::Hexahedron)
6948 {
6949 for (unsigned int i = 0; i < n_new_quads; ++i)
6950 quad_indices[i] = new_quads[i]->index();
6951
6952 for (unsigned int f = 0, k = n_new_quads; f < 6; ++f)
6953 for (unsigned int c = 0; c < 4; ++c, ++k)
6954 quad_indices[k] =
6955 hex->face(f)->isotropic_child_index(
6957 c,
6958 hex->face_orientation(f),
6959 hex->face_flip(f),
6960 hex->face_rotation(f)));
6961 }
6962 else if (reference_cell_type == ReferenceCells::Tetrahedron)
6963 {
6964 // list of the indices of the surfaces which define the
6965 // 8 new tets. the indices 0-7 are the new quads defined
6966 // above (so 0-3 cut off the corners and 4-7 separate
6967 // the remaining octahedral), the indices between 8-11
6968 // are the children of the first face, from 12-15 of the
6969 // second, etc.
6970 for (unsigned int i = 0; i < n_new_quads; ++i)
6971 quad_indices[i] = new_quads[i]->index();
6972
6973 for (unsigned int f = 0, k = n_new_quads; f < 4; ++f)
6974 for (unsigned int c = 0; c < 4; ++c, ++k)
6975 {
6976 const auto combined_orientation =
6977 hex->combined_face_orientation(f);
6978 quad_indices[k] = hex->face(f)->child_index(
6979 (c == 3) ? 3 :
6980 reference_cell_type
6981 .standard_to_real_face_vertex(
6982 c, f, combined_orientation));
6983 }
6984 }
6985 else
6986 {
6988 }
6989
6990 // indices of the faces which define the new tets
6991 // the ordering of the tets is arbitrary
6992 // the first 4 determine the tets cutting of the corners
6993 // the last 4 are ordered after their appearance in the
6994 // faces.
6995 // the ordering within the faces is determined by
6996 // convention for the tetrahedron unit cell, see
6997 // cell_vertices_tet below
6998 const auto &cell_quads =
6999 hex->reference_cell().new_isotropic_child_cell_faces(
7000 chosen_line_tetrahedron);
7001
7002 for (unsigned int c = 0;
7003 c < GeometryInfo<dim>::max_children_per_cell;
7004 ++c)
7005 {
7006 auto &new_hex = new_hexes[c];
7007 const auto reference_cell = new_hex->reference_cell();
7008
7009 if (reference_cell == ReferenceCells::Tetrahedron)
7010 {
7011 new_hex->set_bounding_object_indices(
7012 {quad_indices[cell_quads[c][0]],
7013 quad_indices[cell_quads[c][1]],
7014 quad_indices[cell_quads[c][2]],
7015 quad_indices[cell_quads[c][3]]});
7016
7017
7018 // for tets, we need to go through the faces and
7019 // figure the orientation out the hard way
7020 for (const auto f : new_hex->face_indices())
7021 {
7022 const auto &face = new_hex->face(f);
7023
7024 Assert(face->n_vertices() == 3,
7026
7027 const std::array<unsigned int, 3> vertices_0 = {
7028 {face->vertex_index(0),
7029 face->vertex_index(1),
7030 face->vertex_index(2)}};
7031
7032 // the 8 child tets are each defined by 4
7033 // vertices the ordering of the tets has to be
7034 // consistent with above the ordering within the
7035 // tets is given by the reference tet i.e.
7036 // looking at the fifth line the first 3
7037 // vertices are given by face 11, the last
7038 // vertex is the remaining of the tet
7039 const auto new_hex_vertices =
7040 hex->reference_cell()
7041 .new_isotropic_child_cell_vertices(
7042 chosen_line_tetrahedron)[c];
7043
7044 // arrange after vertices of the faces of the
7045 // unit cell
7046 std::array<unsigned int, 3> vertices_1;
7047 for (unsigned int face_vertex_no :
7048 face->vertex_indices())
7049 {
7050 const auto cell_vertex_no =
7051 reference_cell.face_to_cell_vertices(
7052 f,
7053 face_vertex_no,
7055 vertices_1[face_vertex_no] = vertex_indices
7056 [new_hex_vertices[cell_vertex_no]];
7057 }
7058
7059 new_hex->set_combined_face_orientation(
7060 f,
7061 face->reference_cell()
7062 .get_combined_orientation(
7063 make_const_array_view(vertices_1),
7064 make_array_view(vertices_0)));
7065 }
7066 }
7067 else if (new_hex->n_faces() == 6)
7068 new_hex->set_bounding_object_indices(
7069 {quad_indices[cell_quads[c][0]],
7070 quad_indices[cell_quads[c][1]],
7071 quad_indices[cell_quads[c][2]],
7072 quad_indices[cell_quads[c][3]],
7073 quad_indices[cell_quads[c][4]],
7074 quad_indices[cell_quads[c][5]]});
7075 else
7077 }
7078
7079 // for hexes, we can simply inherit the orientation values
7080 // from the parent on the outer faces; the inner faces can
7081 // be skipped as their orientation is always the default
7082 // one set above
7083 static constexpr ::ndarray<unsigned int, 6, 4>
7084 face_to_child_indices_hex{{{{0, 2, 4, 6}},
7085 {{1, 3, 5, 7}},
7086 {{0, 1, 4, 5}},
7087 {{2, 3, 6, 7}},
7088 {{0, 1, 2, 3}},
7089 {{4, 5, 6, 7}}}};
7090 if (hex->n_faces() == 6)
7091 for (const auto f : hex->face_indices())
7092 {
7093 const auto combined_orientation =
7094 hex->combined_face_orientation(f);
7095 for (unsigned int c = 0; c < 4; ++c)
7096 new_hexes[face_to_child_indices_hex[f][c]]
7097 ->set_combined_face_orientation(
7098 f, combined_orientation);
7099 }
7100 }
7101 }
7102
7103 if (check_for_distorted_cells &&
7104 has_distorted_children<dim, spacedim>(hex))
7105 cells_with_distorted_children.distorted_cells.push_back(hex);
7106
7107 triangulation.signals.post_refinement_on_cell(hex);
7108 }
7109 }
7110
7111 triangulation.faces->quads.clear_user_data();
7112
7113 return cells_with_distorted_children;
7114 }
7115
7120 template <int spacedim>
7123 const bool check_for_distorted_cells)
7124 {
7125 const unsigned int dim = 3;
7126
7127 {
7128 bool flag_isotropic_mesh = true;
7130 cell = triangulation.begin(),
7131 endc = triangulation.end();
7132 for (; cell != endc; ++cell)
7133 if (cell->used())
7134 if (triangulation.get_anisotropic_refinement_flag() ||
7135 cell->refine_flag_set() == RefinementCase<dim>::cut_x ||
7136 cell->refine_flag_set() == RefinementCase<dim>::cut_y ||
7137 cell->refine_flag_set() == RefinementCase<dim>::cut_z ||
7138 cell->refine_flag_set() == RefinementCase<dim>::cut_xy ||
7139 cell->refine_flag_set() == RefinementCase<dim>::cut_xz ||
7140 cell->refine_flag_set() == RefinementCase<dim>::cut_yz)
7141 {
7142 flag_isotropic_mesh = false;
7143 break;
7144 }
7145
7146 if (flag_isotropic_mesh)
7147 return execute_refinement_isotropic(triangulation,
7148 check_for_distorted_cells);
7149 }
7150
7151 // this function probably also works for spacedim>3 but it
7152 // isn't tested. it will probably be necessary to pull new
7153 // vertices onto the manifold just as we do for the other
7154 // functions above.
7155 Assert(spacedim == 3, ExcNotImplemented());
7156
7157 // Check whether a new level is needed. We have to check for
7158 // this on the highest level only
7159 for (const auto &cell : triangulation.active_cell_iterators_on_level(
7160 triangulation.levels.size() - 1))
7161 if (cell->refine_flag_set())
7162 {
7163 triangulation.levels.push_back(
7164 std::make_unique<
7166 break;
7167 }
7168
7169
7170 // first clear user flags for quads and lines; we're going to
7171 // use them to flag which lines and quads need refinement
7172 triangulation.faces->quads.clear_user_data();
7173
7176 line != triangulation.end_line();
7177 ++line)
7178 line->clear_user_flag();
7181 quad != triangulation.end_quad();
7182 ++quad)
7183 quad->clear_user_flag();
7184
7185 // create an array of face refine cases. User indices of faces
7186 // will be set to values corresponding with indices in this
7187 // array.
7188 const RefinementCase<dim - 1> face_refinement_cases[4] = {
7189 RefinementCase<dim - 1>::no_refinement,
7190 RefinementCase<dim - 1>::cut_x,
7191 RefinementCase<dim - 1>::cut_y,
7192 RefinementCase<dim - 1>::cut_xy};
7193
7194 // check how much space is needed on every level. We need not
7195 // check the highest level since either
7196 // - on the highest level no cells are flagged for refinement
7197 // - there are, but prepare_refinement added another empty
7198 // level which then is the highest level
7199
7200 // variables to hold the number of newly to be created
7201 // vertices, lines and quads. as these are stored globally,
7202 // declare them outside the loop over al levels. we need lines
7203 // and quads in pairs for refinement of old ones and lines and
7204 // quads, that can be stored as single ones, as they are newly
7205 // created in the inside of an existing cell
7206 unsigned int needed_vertices = 0;
7207 unsigned int needed_lines_single = 0;
7208 unsigned int needed_quads_single = 0;
7209 unsigned int needed_lines_pair = 0;
7210 unsigned int needed_quads_pair = 0;
7211 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
7212 {
7213 // count number of flagged cells on this level and compute
7214 // how many new vertices and new lines will be needed
7215 unsigned int new_cells = 0;
7216
7217 for (const auto &acell :
7218 triangulation.active_cell_iterators_on_level(level))
7219 if (acell->refine_flag_set())
7220 {
7221 RefinementCase<dim> ref_case = acell->refine_flag_set();
7222
7223 // now for interior vertices, lines and quads, which
7224 // are needed in any case
7225 if (ref_case == RefinementCase<dim>::cut_x ||
7226 ref_case == RefinementCase<dim>::cut_y ||
7227 ref_case == RefinementCase<dim>::cut_z)
7228 {
7229 ++needed_quads_single;
7230 new_cells += 2;
7231 triangulation.anisotropic_refinement = true;
7232 }
7233 else if (ref_case == RefinementCase<dim>::cut_xy ||
7234 ref_case == RefinementCase<dim>::cut_xz ||
7235 ref_case == RefinementCase<dim>::cut_yz)
7236 {
7237 ++needed_lines_single;
7238 needed_quads_single += 4;
7239 new_cells += 4;
7240 triangulation.anisotropic_refinement = true;
7241 }
7242 else if (ref_case == RefinementCase<dim>::cut_xyz)
7243 {
7244 ++needed_vertices;
7245 needed_lines_single += 6;
7246 needed_quads_single += 12;
7247 new_cells += 8;
7248 }
7249 else
7250 {
7251 // we should never get here
7253 }
7254
7255 // mark all faces for refinement; checking locally
7256 // if and how the neighbor would like to refine
7257 // these is difficult so we only flag them and after
7258 // visiting all cells, we decide which faces need
7259 // which refinement;
7260 for (const unsigned int face :
7262 {
7264 aface = acell->face(face);
7265 // get the RefineCase this faces has for the
7266 // given RefineCase of the cell
7267 RefinementCase<dim - 1> face_ref_case =
7269 ref_case,
7270 face,
7271 acell->face_orientation(face),
7272 acell->face_flip(face),
7273 acell->face_rotation(face));
7274 // only do something, if this face has to be
7275 // refined
7276 if (face_ref_case)
7277 {
7278 if (face_ref_case ==
7280 {
7281 if (aface->n_active_descendants() < 4)
7282 // we use user_flags to denote needed
7283 // isotropic refinement
7284 aface->set_user_flag();
7285 }
7286 else if (aface->refinement_case() != face_ref_case)
7287 // we use user_indices to denote needed
7288 // anisotropic refinement. note, that we
7289 // can have at most one anisotropic
7290 // refinement case for this face, as
7291 // otherwise prepare_refinement() would
7292 // have changed one of the cells to yield
7293 // isotropic refinement at this
7294 // face. therefore we set the user_index
7295 // uniquely
7296 {
7297 Assert(aface->refinement_case() ==
7299 dim - 1>::isotropic_refinement ||
7300 aface->refinement_case() ==
7303 aface->set_user_index(face_ref_case);
7304 }
7305 }
7306 } // for all faces
7307
7308 // flag all lines, that have to be refined
7309 for (unsigned int line = 0;
7310 line < GeometryInfo<dim>::lines_per_cell;
7311 ++line)
7313 line) &&
7314 !acell->line(line)->has_children())
7315 acell->line(line)->set_user_flag();
7316
7317 } // if refine_flag set and for all cells on this level
7318
7319
7320 // count number of used cells on the next higher level
7321 const unsigned int used_cells =
7322 std::count(triangulation.levels[level + 1]->cells.used.begin(),
7323 triangulation.levels[level + 1]->cells.used.end(),
7324 true);
7325
7326
7327 // reserve space for the used_cells cells already existing
7328 // on the next higher level as well as for the
7329 // 8*flagged_cells that will be created on that level
7330 reserve_space(*triangulation.levels[level + 1],
7331 used_cells + new_cells,
7332 spacedim);
7333 // reserve space for 8*flagged_cells new hexes on the next
7334 // higher level
7335 reserve_space(triangulation.levels[level + 1]->cells, new_cells);
7336 } // for all levels
7337 // now count the quads and lines which were flagged for
7338 // refinement
7341 quad != triangulation.end_quad();
7342 ++quad)
7343 {
7344 if (quad->user_flag_set())
7345 {
7346 // isotropic refinement: 1 interior vertex, 4 quads
7347 // and 4 interior lines. we store the interior lines
7348 // in pairs in case the face is already or will be
7349 // refined anisotropically
7350 needed_quads_pair += 4;
7351 needed_lines_pair += 4;
7352 needed_vertices += 1;
7353 }
7354 if (quad->user_index())
7355 {
7356 // anisotropic refinement: 1 interior
7357 // line and two quads
7358 needed_quads_pair += 2;
7359 needed_lines_single += 1;
7360 // there is a kind of complicated situation here which
7361 // requires our attention. if the quad is refined
7362 // isotropcally, two of the interior lines will get a
7363 // new mother line - the interior line of our
7364 // anisotropically refined quad. if those two lines
7365 // are not consecutive, we cannot do so and have to
7366 // replace them by two lines that are consecutive. we
7367 // try to avoid that situation, but it may happen
7368 // nevertheless through repeated refinement and
7369 // coarsening. thus we have to check here, as we will
7370 // need some additional space to store those new lines
7371 // in case we need them...
7372 if (quad->has_children())
7373 {
7374 Assert(quad->refinement_case() ==
7377 if ((face_refinement_cases[quad->user_index()] ==
7379 (quad->child(0)->line_index(1) + 1 !=
7380 quad->child(2)->line_index(1))) ||
7381 (face_refinement_cases[quad->user_index()] ==
7383 (quad->child(0)->line_index(3) + 1 !=
7384 quad->child(1)->line_index(3))))
7385 needed_lines_pair += 2;
7386 }
7387 }
7388 }
7389
7392 line != triangulation.end_line();
7393 ++line)
7394 if (line->user_flag_set())
7395 {
7396 needed_lines_pair += 2;
7397 needed_vertices += 1;
7398 }
7399
7400 // reserve space for needed_lines new lines stored in pairs
7401 reserve_space(triangulation.faces->lines,
7402 needed_lines_pair,
7403 needed_lines_single);
7404 // reserve space for needed_quads new quads stored in pairs
7406 needed_quads_pair,
7407 needed_quads_single);
7408 reserve_space(triangulation.faces->quads,
7409 needed_quads_pair,
7410 needed_quads_single);
7411
7412
7413 // add to needed vertices how many vertices are already in use
7414 needed_vertices += std::count(triangulation.vertices_used.begin(),
7415 triangulation.vertices_used.end(),
7416 true);
7417 // if we need more vertices: create them, if not: leave the
7418 // array as is, since shrinking is not really possible because
7419 // some of the vertices at the end may be in use
7420 if (needed_vertices > triangulation.vertices.size())
7421 {
7422 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
7423 triangulation.vertices_used.resize(needed_vertices, false);
7424 }
7425
7426
7427 //-----------------------------------------
7428 // Before we start with the actual refinement, we do some
7429 // sanity checks if in debug mode. especially, we try to catch
7430 // the notorious problem with lines being twice refined,
7431 // i.e. there are cells adjacent at one line ("around the
7432 // edge", but not at a face), with two cells differing by more
7433 // than one refinement level
7434 //
7435 // this check is very simple to implement here, since we have
7436 // all lines flagged if they shall be refined
7437 if constexpr (running_in_debug_mode())
7438 {
7439 for (const auto &cell : triangulation.active_cell_iterators())
7440 if (!cell->refine_flag_set())
7441 for (unsigned int line = 0;
7442 line < GeometryInfo<dim>::lines_per_cell;
7443 ++line)
7444 if (cell->line(line)->has_children())
7445 for (unsigned int c = 0; c < 2; ++c)
7446 Assert(cell->line(line)->child(c)->user_flag_set() ==
7447 false,
7449 }
7450
7451 //-----------------------------------------
7452 // Do refinement on every level
7453 //
7454 // To make life a bit easier, we first refine those lines and
7455 // quads that were flagged for refinement and then compose the
7456 // newly to be created cells.
7457 //
7458 // index of next unused vertex
7459 unsigned int next_unused_vertex = 0;
7460
7461 // first for lines
7462 {
7463 // only active objects can be refined further
7466 endl = triangulation.end_line();
7468 next_unused_line = triangulation.begin_raw_line();
7469
7470 for (; line != endl; ++line)
7471 if (line->user_flag_set())
7472 {
7473 // this line needs to be refined
7474
7475 // find the next unused vertex and set it
7476 // appropriately
7477 while (triangulation.vertices_used[next_unused_vertex] == true)
7478 ++next_unused_vertex;
7479 Assert(
7480 next_unused_vertex < triangulation.vertices.size(),
7481 ExcMessage(
7482 "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."));
7483 triangulation.vertices_used[next_unused_vertex] = true;
7484
7485 triangulation.vertices[next_unused_vertex] = line->center(true);
7486
7487 // now that we created the right point, make up the
7488 // two child lines (++ takes care of the end of the
7489 // vector)
7490 next_unused_line =
7491 triangulation.faces->lines.template next_free_pair_object<1>(
7493 Assert(next_unused_line.state() == IteratorState::valid,
7495
7496 // now we found two consecutive unused lines, such
7497 // that the children of a line will be consecutive.
7498 // then set the child pointer of the present line
7499 line->set_children(0, next_unused_line->index());
7500
7501 // set the two new lines
7503 children[2] = {next_unused_line, ++next_unused_line};
7504
7505 // some tests; if any of the iterators should be
7506 // invalid, then already dereferencing will fail
7507 AssertIsNotUsed(children[0]);
7508 AssertIsNotUsed(children[1]);
7509
7510 children[0]->set_bounding_object_indices(
7511 {line->vertex_index(0), next_unused_vertex});
7512 children[1]->set_bounding_object_indices(
7513 {next_unused_vertex, line->vertex_index(1)});
7514
7515 children[0]->set_used_flag();
7516 children[1]->set_used_flag();
7517 children[0]->clear_children();
7518 children[1]->clear_children();
7519 children[0]->clear_user_data();
7520 children[1]->clear_user_data();
7521 children[0]->clear_user_flag();
7522 children[1]->clear_user_flag();
7523
7524 children[0]->set_boundary_id_internal(line->boundary_id());
7525 children[1]->set_boundary_id_internal(line->boundary_id());
7526
7527 children[0]->set_manifold_id(line->manifold_id());
7528 children[1]->set_manifold_id(line->manifold_id());
7529
7530 // finally clear flag
7531 // indicating the need
7532 // for refinement
7533 line->clear_user_flag();
7534 }
7535 }
7536
7537
7538 //-------------------------------------
7539 // now refine marked quads
7540 //-------------------------------------
7541
7542 // here we encounter several cases:
7543
7544 // a) the quad is unrefined and shall be refined isotropically
7545
7546 // b) the quad is unrefined and shall be refined
7547 // anisotropically
7548
7549 // c) the quad is unrefined and shall be refined both
7550 // anisotropically and isotropically (this is reduced to case
7551 // b) and then case b) for the children again)
7552
7553 // d) the quad is refined anisotropically and shall be refined
7554 // isotropically (this is reduced to case b) for the
7555 // anisotropic children)
7556
7557 // e) the quad is refined isotropically and shall be refined
7558 // anisotropically (this is transformed to case c), however we
7559 // might have to renumber/rename children...)
7560
7561 // we need a loop in cases c) and d), as the anisotropic
7562 // children might have a lower index than the mother quad
7563 for (unsigned int loop = 0; loop < 2; ++loop)
7564 {
7565 // usually, only active objects can be refined
7566 // further. however, in cases d) and e) that is not true,
7567 // so we have to use 'normal' iterators here
7569 quad = triangulation.begin_quad(),
7570 endq = triangulation.end_quad();
7572 next_unused_line = triangulation.begin_raw_line();
7574 next_unused_quad = triangulation.begin_raw_quad();
7575
7576 for (; quad != endq; ++quad)
7577 {
7578 if (quad->user_index())
7579 {
7580 RefinementCase<dim - 1> aniso_quad_ref_case =
7581 face_refinement_cases[quad->user_index()];
7582 // there is one unlikely event here, where we
7583 // already have refind the face: if the face was
7584 // refined anisotropically and we want to refine
7585 // it isotropically, both children are flagged for
7586 // anisotropic refinement. however, if those
7587 // children were already flagged for anisotropic
7588 // refinement, they might already be processed and
7589 // refined.
7590 if (aniso_quad_ref_case == quad->refinement_case())
7591 continue;
7592
7593 Assert(quad->refinement_case() ==
7595 quad->refinement_case() ==
7598
7599 // this quad needs to be refined anisotropically
7600 Assert(quad->user_index() ==
7602 quad->user_index() ==
7605
7606 // make the new line interior to the quad
7608 new_line;
7609
7610 new_line =
7611 triangulation.faces->lines
7612 .template next_free_single_object<1>(triangulation);
7613 AssertIsNotUsed(new_line);
7614
7615 // first collect the
7616 // indices of the vertices:
7617 // *--1--*
7618 // | | |
7619 // | | | cut_x
7620 // | | |
7621 // *--0--*
7622 //
7623 // *-----*
7624 // | |
7625 // 0-----1 cut_y
7626 // | |
7627 // *-----*
7628 unsigned int vertex_indices[2];
7629 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
7630 {
7631 vertex_indices[0] =
7632 quad->line(2)->child(0)->vertex_index(1);
7633 vertex_indices[1] =
7634 quad->line(3)->child(0)->vertex_index(1);
7635 }
7636 else
7637 {
7638 vertex_indices[0] =
7639 quad->line(0)->child(0)->vertex_index(1);
7640 vertex_indices[1] =
7641 quad->line(1)->child(0)->vertex_index(1);
7642 }
7643
7644 new_line->set_bounding_object_indices(
7646 new_line->set_used_flag();
7647 new_line->clear_user_flag();
7648 new_line->clear_user_data();
7649 new_line->clear_children();
7650 new_line->set_boundary_id_internal(quad->boundary_id());
7651 new_line->set_manifold_id(quad->manifold_id());
7652
7653 // find some space (consecutive) for the two newly
7654 // to be created quads.
7656 new_quads[2];
7657
7658 next_unused_quad =
7659 triangulation.faces->quads
7660 .template next_free_pair_object<2>(triangulation);
7661 new_quads[0] = next_unused_quad;
7662 AssertIsNotUsed(new_quads[0]);
7663
7664 ++next_unused_quad;
7665 new_quads[1] = next_unused_quad;
7666 AssertIsNotUsed(new_quads[1]);
7667
7668 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
7669 {
7670 new_quads[0]->set_bounding_object_indices(
7671 {static_cast<int>(quad->line_index(0)),
7672 new_line->index(),
7673 quad->line(2)
7674 ->child(
7675 child_line_index(0, quad->line_orientation(2)))
7676 ->index(),
7677 quad->line(3)
7678 ->child(
7679 child_line_index(0, quad->line_orientation(3)))
7680 ->index()});
7681 new_quads[1]->set_bounding_object_indices(
7682 {new_line->index(),
7683 static_cast<int>(quad->line_index(1)),
7684 quad->line(2)
7685 ->child(
7686 child_line_index(1, quad->line_orientation(2)))
7687 ->index(),
7688 quad->line(3)
7689 ->child(
7690 child_line_index(1, quad->line_orientation(3)))
7691 ->index()});
7692 }
7693 else
7694 {
7695 new_quads[0]->set_bounding_object_indices(
7696 {quad->line(0)
7697 ->child(
7698 child_line_index(0, quad->line_orientation(0)))
7699 ->index(),
7700 quad->line(1)
7701 ->child(
7702 child_line_index(0, quad->line_orientation(1)))
7703 ->index(),
7704 static_cast<int>(quad->line_index(2)),
7705 new_line->index()});
7706 new_quads[1]->set_bounding_object_indices(
7707 {quad->line(0)
7708 ->child(
7709 child_line_index(1, quad->line_orientation(0)))
7710 ->index(),
7711 quad->line(1)
7712 ->child(
7713 child_line_index(1, quad->line_orientation(1)))
7714 ->index(),
7715 new_line->index(),
7716 static_cast<int>(quad->line_index(3))});
7717 }
7718
7719 for (const auto &new_quad : new_quads)
7720 {
7721 new_quad->set_used_flag();
7722 new_quad->clear_user_flag();
7723 new_quad->clear_user_data();
7724 new_quad->clear_children();
7725 new_quad->set_boundary_id_internal(quad->boundary_id());
7726 new_quad->set_manifold_id(quad->manifold_id());
7727 // set all line orientations to true, change
7728 // this after the loop, as we have to consider
7729 // different lines for each child
7730 for (unsigned int j = 0;
7731 j < GeometryInfo<dim>::lines_per_face;
7732 ++j)
7733 new_quad->set_line_orientation(
7735 }
7736 // now set the line orientation of children of
7737 // outer lines correctly, the lines in the
7738 // interior of the refined quad are automatically
7739 // oriented conforming to the standard
7740 new_quads[0]->set_line_orientation(
7741 0, quad->line_orientation(0));
7742 new_quads[0]->set_line_orientation(
7743 2, quad->line_orientation(2));
7744 new_quads[1]->set_line_orientation(
7745 1, quad->line_orientation(1));
7746 new_quads[1]->set_line_orientation(
7747 3, quad->line_orientation(3));
7748 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
7749 {
7750 new_quads[0]->set_line_orientation(
7751 3, quad->line_orientation(3));
7752 new_quads[1]->set_line_orientation(
7753 2, quad->line_orientation(2));
7754 }
7755 else
7756 {
7757 new_quads[0]->set_line_orientation(
7758 1, quad->line_orientation(1));
7759 new_quads[1]->set_line_orientation(
7760 0, quad->line_orientation(0));
7761 }
7762
7763 // test, whether this face is refined
7764 // isotropically already. if so, set the correct
7765 // children pointers.
7766 if (quad->refinement_case() ==
7767 RefinementCase<dim - 1>::cut_xy)
7768 {
7769 // we will put a new refinemnt level of
7770 // anisotropic refinement between the
7771 // unrefined and isotropically refined quad
7772 // ending up with the same fine quads but
7773 // introducing anisotropically refined ones as
7774 // children of the unrefined quad and mother
7775 // cells of the original fine ones.
7776
7777 // this process includes the creation of a new
7778 // middle line which we will assign as the
7779 // mother line of two of the existing inner
7780 // lines. If those inner lines are not
7781 // consecutive in memory, we won't find them
7782 // later on, so we have to create new ones
7783 // instead and replace all occurrences of the
7784 // old ones with those new ones. As this is
7785 // kind of ugly, we hope we don't have to do
7786 // it often...
7788 old_child[2];
7789 if (aniso_quad_ref_case ==
7791 {
7792 old_child[0] = quad->child(0)->line(1);
7793 old_child[1] = quad->child(2)->line(1);
7794 }
7795 else
7796 {
7797 Assert(aniso_quad_ref_case ==
7800
7801 old_child[0] = quad->child(0)->line(3);
7802 old_child[1] = quad->child(1)->line(3);
7803 }
7804
7805 if (old_child[0]->index() + 1 != old_child[1]->index())
7806 {
7807 // this is exactly the ugly case we talked
7808 // about. so, no complaining, lets get
7809 // two new lines and copy all info
7810 typename Triangulation<dim,
7811 spacedim>::raw_line_iterator
7812 new_child[2];
7813
7814 new_child[0] = new_child[1] =
7815 triangulation.faces->lines
7816 .template next_free_pair_object<1>(
7818 ++new_child[1];
7819
7820 new_child[0]->set_used_flag();
7821 new_child[1]->set_used_flag();
7822
7823 const int old_index_0 = old_child[0]->index(),
7824 old_index_1 = old_child[1]->index(),
7825 new_index_0 = new_child[0]->index(),
7826 new_index_1 = new_child[1]->index();
7827
7828 // loop over all quads and replace the old
7829 // lines
7830 for (unsigned int q = 0;
7831 q < triangulation.faces->quads.n_objects();
7832 ++q)
7833 for (unsigned int l = 0;
7834 l < GeometryInfo<dim>::lines_per_face;
7835 ++l)
7836 {
7837 const int this_index =
7838 triangulation.faces->quads
7839 .get_bounding_object_indices(q)[l];
7840 if (this_index == old_index_0)
7841 triangulation.faces->quads
7842 .get_bounding_object_indices(q)[l] =
7843 new_index_0;
7844 else if (this_index == old_index_1)
7845 triangulation.faces->quads
7846 .get_bounding_object_indices(q)[l] =
7847 new_index_1;
7848 }
7849 // now we have to copy all information of
7850 // the two lines
7851 for (unsigned int i = 0; i < 2; ++i)
7852 {
7853 Assert(!old_child[i]->has_children(),
7855
7856 new_child[i]->set_bounding_object_indices(
7857 {old_child[i]->vertex_index(0),
7858 old_child[i]->vertex_index(1)});
7859 new_child[i]->set_boundary_id_internal(
7860 old_child[i]->boundary_id());
7861 new_child[i]->set_manifold_id(
7862 old_child[i]->manifold_id());
7863 new_child[i]->set_user_index(
7864 old_child[i]->user_index());
7865 if (old_child[i]->user_flag_set())
7866 new_child[i]->set_user_flag();
7867 else
7868 new_child[i]->clear_user_flag();
7869
7870 new_child[i]->clear_children();
7871
7872 old_child[i]->clear_user_flag();
7873 old_child[i]->clear_user_index();
7874 old_child[i]->clear_used_flag();
7875 }
7876 }
7877 // now that we cared about the lines, go on
7878 // with the quads themselves, where we might
7879 // encounter similar situations...
7880 if (aniso_quad_ref_case ==
7882 {
7883 new_line->set_children(
7884 0, quad->child(0)->line_index(1));
7885 Assert(new_line->child(1) ==
7886 quad->child(2)->line(1),
7888 // now evereything is quite
7889 // complicated. we have the children
7890 // numbered according to
7891 //
7892 // *---*---*
7893 // |n+2|n+3|
7894 // *---*---*
7895 // | n |n+1|
7896 // *---*---*
7897 //
7898 // from the original isotropic
7899 // refinement. we have to reorder them as
7900 //
7901 // *---*---*
7902 // |n+1|n+3|
7903 // *---*---*
7904 // | n |n+2|
7905 // *---*---*
7906 //
7907 // such that n and n+1 are consecutive
7908 // children of m and n+2 and n+3 are
7909 // consecutive children of m+1, where m
7910 // and m+1 are given as in
7911 //
7912 // *---*---*
7913 // | | |
7914 // | m |m+1|
7915 // | | |
7916 // *---*---*
7917 //
7918 // this is a bit ugly, of course: loop
7919 // over all cells on all levels and look
7920 // for faces n+1 (switch_1) and n+2
7921 // (switch_2).
7922 const typename Triangulation<dim, spacedim>::
7923 quad_iterator switch_1 = quad->child(1),
7924 switch_2 = quad->child(2);
7925 const int switch_1_index = switch_1->index();
7926 const int switch_2_index = switch_2->index();
7927 for (unsigned int l = 0;
7928 l < triangulation.levels.size();
7929 ++l)
7930 for (unsigned int h = 0;
7931 h <
7932 triangulation.levels[l]->cells.n_objects();
7933 ++h)
7934 for (const unsigned int q :
7936 {
7937 const int face_index =
7939 ->cells.get_bounding_object_indices(
7940 h)[q];
7941 if (face_index == switch_1_index)
7942 triangulation.levels[l]
7943 ->cells.get_bounding_object_indices(
7944 h)[q] = switch_2_index;
7945 else if (face_index == switch_2_index)
7946 triangulation.levels[l]
7947 ->cells.get_bounding_object_indices(
7948 h)[q] = switch_1_index;
7949 }
7950 // now we have to copy all information of
7951 // the two quads
7952 const unsigned int switch_1_lines[4] = {
7953 switch_1->line_index(0),
7954 switch_1->line_index(1),
7955 switch_1->line_index(2),
7956 switch_1->line_index(3)};
7958 switch_1_line_orientations[4] = {
7959 switch_1->line_orientation(0),
7960 switch_1->line_orientation(1),
7961 switch_1->line_orientation(2),
7962 switch_1->line_orientation(3)};
7963 const types::boundary_id switch_1_boundary_id =
7964 switch_1->boundary_id();
7965 const unsigned int switch_1_user_index =
7966 switch_1->user_index();
7967 const bool switch_1_user_flag =
7968 switch_1->user_flag_set();
7969 const RefinementCase<dim - 1>
7970 switch_1_refinement_case =
7971 switch_1->refinement_case();
7972 const int switch_1_first_child_pair =
7973 (switch_1_refinement_case ?
7974 switch_1->child_index(0) :
7975 -1);
7976 const int switch_1_second_child_pair =
7977 (switch_1_refinement_case ==
7978 RefinementCase<dim - 1>::cut_xy ?
7979 switch_1->child_index(2) :
7980 -1);
7981
7982 switch_1->set_bounding_object_indices(
7983 {switch_2->line_index(0),
7984 switch_2->line_index(1),
7985 switch_2->line_index(2),
7986 switch_2->line_index(3)});
7987 switch_1->set_line_orientation(
7988 0, switch_2->line_orientation(0));
7989 switch_1->set_line_orientation(
7990 1, switch_2->line_orientation(1));
7991 switch_1->set_line_orientation(
7992 2, switch_2->line_orientation(2));
7993 switch_1->set_line_orientation(
7994 3, switch_2->line_orientation(3));
7995 switch_1->set_boundary_id_internal(
7996 switch_2->boundary_id());
7997 switch_1->set_manifold_id(switch_2->manifold_id());
7998 switch_1->set_user_index(switch_2->user_index());
7999 if (switch_2->user_flag_set())
8000 switch_1->set_user_flag();
8001 else
8002 switch_1->clear_user_flag();
8003 switch_1->clear_refinement_case();
8004 switch_1->set_refinement_case(
8005 switch_2->refinement_case());
8006 switch_1->clear_children();
8007 if (switch_2->refinement_case())
8008 switch_1->set_children(0,
8009 switch_2->child_index(0));
8010 if (switch_2->refinement_case() ==
8011 RefinementCase<dim - 1>::cut_xy)
8012 switch_1->set_children(2,
8013 switch_2->child_index(2));
8014
8015 switch_2->set_bounding_object_indices(
8016 {switch_1_lines[0],
8017 switch_1_lines[1],
8018 switch_1_lines[2],
8019 switch_1_lines[3]});
8020 switch_2->set_line_orientation(
8021 0, switch_1_line_orientations[0]);
8022 switch_2->set_line_orientation(
8023 1, switch_1_line_orientations[1]);
8024 switch_2->set_line_orientation(
8025 2, switch_1_line_orientations[2]);
8026 switch_2->set_line_orientation(
8027 3, switch_1_line_orientations[3]);
8028 switch_2->set_boundary_id_internal(
8029 switch_1_boundary_id);
8030 switch_2->set_manifold_id(switch_1->manifold_id());
8031 switch_2->set_user_index(switch_1_user_index);
8032 if (switch_1_user_flag)
8033 switch_2->set_user_flag();
8034 else
8035 switch_2->clear_user_flag();
8036 switch_2->clear_refinement_case();
8037 switch_2->set_refinement_case(
8038 switch_1_refinement_case);
8039 switch_2->clear_children();
8040 switch_2->set_children(0,
8041 switch_1_first_child_pair);
8042 switch_2->set_children(2,
8043 switch_1_second_child_pair);
8044
8045 new_quads[0]->set_refinement_case(
8047 new_quads[0]->set_children(0, quad->child_index(0));
8048 new_quads[1]->set_refinement_case(
8050 new_quads[1]->set_children(0, quad->child_index(2));
8051 }
8052 else
8053 {
8054 new_quads[0]->set_refinement_case(
8056 new_quads[0]->set_children(0, quad->child_index(0));
8057 new_quads[1]->set_refinement_case(
8059 new_quads[1]->set_children(0, quad->child_index(2));
8060 new_line->set_children(
8061 0, quad->child(0)->line_index(3));
8062 Assert(new_line->child(1) ==
8063 quad->child(1)->line(3),
8065 }
8066 quad->clear_children();
8067 }
8068
8069 // note these quads as children to the present one
8070 quad->set_children(0, new_quads[0]->index());
8071
8072 quad->set_refinement_case(aniso_quad_ref_case);
8073
8074 // finally clear flag indicating the need for
8075 // refinement
8076 quad->clear_user_data();
8077 } // if (anisotropic refinement)
8078
8079 if (quad->user_flag_set())
8080 {
8081 // this quad needs to be refined isotropically
8082
8083 // first of all: we only get here in the first run
8084 // of the loop
8085 Assert(loop == 0, ExcInternalError());
8086
8087 // find the next unused vertex. we'll need this in
8088 // any case
8089 while (triangulation.vertices_used[next_unused_vertex] ==
8090 true)
8091 ++next_unused_vertex;
8092 Assert(
8093 next_unused_vertex < triangulation.vertices.size(),
8094 ExcMessage(
8095 "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."));
8096
8097 // now: if the quad is refined anisotropically
8098 // already, set the anisotropic refinement flag
8099 // for both children. Additionally, we have to
8100 // refine the inner line, as it is an outer line
8101 // of the two (anisotropic) children
8102 const RefinementCase<dim - 1> quad_ref_case =
8103 quad->refinement_case();
8104
8105 if (quad_ref_case == RefinementCase<dim - 1>::cut_x ||
8106 quad_ref_case == RefinementCase<dim - 1>::cut_y)
8107 {
8108 // set the 'opposite' refine case for children
8109 quad->child(0)->set_user_index(
8110 RefinementCase<dim - 1>::cut_xy - quad_ref_case);
8111 quad->child(1)->set_user_index(
8112 RefinementCase<dim - 1>::cut_xy - quad_ref_case);
8113 // refine the inner line
8115 middle_line;
8116 if (quad_ref_case == RefinementCase<dim - 1>::cut_x)
8117 middle_line = quad->child(0)->line(1);
8118 else
8119 middle_line = quad->child(0)->line(3);
8120
8121 // if the face has been refined
8122 // anisotropically in the last refinement step
8123 // it might be, that it is flagged already and
8124 // that the middle line is thus refined
8125 // already. if not create children.
8126 if (!middle_line->has_children())
8127 {
8128 // set the middle vertex
8129 // appropriately. double refinement of
8130 // quads can only happen in the interior
8131 // of the domain, so we need not care
8132 // about boundary quads here
8133 triangulation.vertices[next_unused_vertex] =
8134 middle_line->center(true);
8135 triangulation.vertices_used[next_unused_vertex] =
8136 true;
8137
8138 // now search a slot for the two
8139 // child lines
8140 next_unused_line =
8141 triangulation.faces->lines
8142 .template next_free_pair_object<1>(
8144
8145 // set the child pointer of the present
8146 // line
8147 middle_line->set_children(
8148 0, next_unused_line->index());
8149
8150 // set the two new lines
8151 const typename Triangulation<dim, spacedim>::
8152 raw_line_iterator children[2] = {
8153 next_unused_line, ++next_unused_line};
8154
8155 // some tests; if any of the iterators
8156 // should be invalid, then already
8157 // dereferencing will fail
8158 AssertIsNotUsed(children[0]);
8159 AssertIsNotUsed(children[1]);
8160
8161 children[0]->set_bounding_object_indices(
8162 {middle_line->vertex_index(0),
8163 next_unused_vertex});
8164 children[1]->set_bounding_object_indices(
8165 {next_unused_vertex,
8166 middle_line->vertex_index(1)});
8167
8168 children[0]->set_used_flag();
8169 children[1]->set_used_flag();
8170 children[0]->clear_children();
8171 children[1]->clear_children();
8172 children[0]->clear_user_data();
8173 children[1]->clear_user_data();
8174 children[0]->clear_user_flag();
8175 children[1]->clear_user_flag();
8176
8177 children[0]->set_boundary_id_internal(
8178 middle_line->boundary_id());
8179 children[1]->set_boundary_id_internal(
8180 middle_line->boundary_id());
8181
8182 children[0]->set_manifold_id(
8183 middle_line->manifold_id());
8184 children[1]->set_manifold_id(
8185 middle_line->manifold_id());
8186 }
8187 // now remove the flag from the quad and go to
8188 // the next quad, the actual refinement of the
8189 // quad takes place later on in this pass of
8190 // the loop or in the next one
8191 quad->clear_user_flag();
8192 continue;
8193 } // if (several refinement cases)
8194
8195 // if we got here, we have an unrefined quad and
8196 // have to do the usual work like in an purely
8197 // isotropic refinement
8198 Assert(quad_ref_case ==
8201
8202 // set the middle vertex appropriately: it might be that
8203 // the quad itself is not at the boundary, but that one of
8204 // its lines actually is. in this case, the newly created
8205 // vertices at the centers of the lines are not
8206 // necessarily the mean values of the adjacent vertices,
8207 // so do not compute the new vertex as the mean value of
8208 // the 4 vertices of the face, but rather as a weighted
8209 // mean value of the 8 vertices which we already have (the
8210 // four old ones, and the four ones inserted as middle
8211 // points for the four lines). summing up some more points
8212 // is generally cheaper than first asking whether one of
8213 // the lines is at the boundary
8214 //
8215 // note that the exact weights are chosen such as to
8216 // minimize the distortion of the four new quads from the
8217 // optimal shape. their description uses the formulas
8218 // underlying the TransfiniteInterpolationManifold
8219 // implementation
8220 triangulation.vertices[next_unused_vertex] =
8221 quad->center(true, true);
8222 triangulation.vertices_used[next_unused_vertex] = true;
8223
8224 // now that we created the right point, make up
8225 // the four lines interior to the quad (++ takes
8226 // care of the end of the vector)
8228 new_lines[4];
8229
8230 for (unsigned int i = 0; i < 4; ++i)
8231 {
8232 if (i % 2 == 0)
8233 // search a free pair of lines for 0. and
8234 // 2. line, so that two of them end up
8235 // together, which is necessary if later on
8236 // we want to refine the quad
8237 // anisotropically and the two lines end up
8238 // as children of new line
8239 next_unused_line =
8240 triangulation.faces->lines
8241 .template next_free_pair_object<1>(triangulation);
8242
8243 new_lines[i] = next_unused_line;
8244 ++next_unused_line;
8245
8246 AssertIsNotUsed(new_lines[i]);
8247 }
8248
8249 // set the data of the four lines. first collect
8250 // the indices of the five vertices:
8251 //
8252 // *--3--*
8253 // | | |
8254 // 0--4--1
8255 // | | |
8256 // *--2--*
8257 //
8258 // the lines are numbered as follows:
8259 //
8260 // *--*--*
8261 // | 1 |
8262 // *2-*-3*
8263 // | 0 |
8264 // *--*--*
8265
8266 const unsigned int vertex_indices[5] = {
8267 quad->line(0)->child(0)->vertex_index(1),
8268 quad->line(1)->child(0)->vertex_index(1),
8269 quad->line(2)->child(0)->vertex_index(1),
8270 quad->line(3)->child(0)->vertex_index(1),
8271 next_unused_vertex};
8272
8273 new_lines[0]->set_bounding_object_indices(
8275 new_lines[1]->set_bounding_object_indices(
8277 new_lines[2]->set_bounding_object_indices(
8279 new_lines[3]->set_bounding_object_indices(
8281
8282 for (const auto &new_line : new_lines)
8283 {
8284 new_line->set_used_flag();
8285 new_line->clear_user_flag();
8286 new_line->clear_user_data();
8287 new_line->clear_children();
8288 new_line->set_boundary_id_internal(quad->boundary_id());
8289 new_line->set_manifold_id(quad->manifold_id());
8290 }
8291
8292 // now for the quads. again, first collect some
8293 // data about the indices of the lines, with the
8294 // following numbering:
8295 //
8296 // .-6-.-7-.
8297 // 1 9 3
8298 // .-10.11-.
8299 // 0 8 2
8300 // .-4-.-5-.
8301
8302 const int line_indices[12] = {
8303 quad->line(0)
8304 ->child(child_line_index(0, quad->line_orientation(0)))
8305 ->index(),
8306 quad->line(0)
8307 ->child(child_line_index(1, quad->line_orientation(0)))
8308 ->index(),
8309 quad->line(1)
8310 ->child(child_line_index(0, quad->line_orientation(1)))
8311 ->index(),
8312 quad->line(1)
8313 ->child(child_line_index(1, quad->line_orientation(1)))
8314 ->index(),
8315 quad->line(2)
8316 ->child(child_line_index(0, quad->line_orientation(2)))
8317 ->index(),
8318 quad->line(2)
8319 ->child(child_line_index(1, quad->line_orientation(2)))
8320 ->index(),
8321 quad->line(3)
8322 ->child(child_line_index(0, quad->line_orientation(3)))
8323 ->index(),
8324 quad->line(3)
8325 ->child(child_line_index(1, quad->line_orientation(3)))
8326 ->index(),
8327 new_lines[0]->index(),
8328 new_lines[1]->index(),
8329 new_lines[2]->index(),
8330 new_lines[3]->index()};
8331
8332 // find some space (consecutive)
8333 // for the first two newly to be
8334 // created quads.
8336 new_quads[4];
8337
8338 next_unused_quad =
8339 triangulation.faces->quads
8340 .template next_free_pair_object<2>(triangulation);
8341
8342 new_quads[0] = next_unused_quad;
8343 AssertIsNotUsed(new_quads[0]);
8344
8345 ++next_unused_quad;
8346 new_quads[1] = next_unused_quad;
8347 AssertIsNotUsed(new_quads[1]);
8348
8349 next_unused_quad =
8350 triangulation.faces->quads
8351 .template next_free_pair_object<2>(triangulation);
8352 new_quads[2] = next_unused_quad;
8353 AssertIsNotUsed(new_quads[2]);
8354
8355 ++next_unused_quad;
8356 new_quads[3] = next_unused_quad;
8357 AssertIsNotUsed(new_quads[3]);
8358
8359 // note these quads as children to the present one
8360 quad->set_children(0, new_quads[0]->index());
8361 quad->set_children(2, new_quads[2]->index());
8362 quad->set_refinement_case(RefinementCase<2>::cut_xy);
8363
8364 new_quads[0]->set_bounding_object_indices(
8365 {line_indices[0],
8366 line_indices[8],
8367 line_indices[4],
8368 line_indices[10]});
8369 new_quads[1]->set_bounding_object_indices(
8370 {line_indices[8],
8371 line_indices[2],
8372 line_indices[5],
8373 line_indices[11]});
8374 new_quads[2]->set_bounding_object_indices(
8375 {line_indices[1],
8376 line_indices[9],
8377 line_indices[10],
8378 line_indices[6]});
8379 new_quads[3]->set_bounding_object_indices(
8380 {line_indices[9],
8381 line_indices[3],
8382 line_indices[11],
8383 line_indices[7]});
8384 for (const auto &new_quad : new_quads)
8385 {
8386 new_quad->set_used_flag();
8387 new_quad->clear_user_flag();
8388 new_quad->clear_user_data();
8389 new_quad->clear_children();
8390 new_quad->set_boundary_id_internal(quad->boundary_id());
8391 new_quad->set_manifold_id(quad->manifold_id());
8392 // set all line orientations to true, change
8393 // this after the loop, as we have to consider
8394 // different lines for each child
8395 for (unsigned int j = 0;
8396 j < GeometryInfo<dim>::lines_per_face;
8397 ++j)
8398 new_quad->set_line_orientation(
8400 }
8401 // now set the line orientation of children of
8402 // outer lines correctly, the lines in the
8403 // interior of the refined quad are automatically
8404 // oriented conforming to the standard
8405 new_quads[0]->set_line_orientation(
8406 0, quad->line_orientation(0));
8407 new_quads[0]->set_line_orientation(
8408 2, quad->line_orientation(2));
8409 new_quads[1]->set_line_orientation(
8410 1, quad->line_orientation(1));
8411 new_quads[1]->set_line_orientation(
8412 2, quad->line_orientation(2));
8413 new_quads[2]->set_line_orientation(
8414 0, quad->line_orientation(0));
8415 new_quads[2]->set_line_orientation(
8416 3, quad->line_orientation(3));
8417 new_quads[3]->set_line_orientation(
8418 1, quad->line_orientation(1));
8419 new_quads[3]->set_line_orientation(
8420 3, quad->line_orientation(3));
8421
8422 // finally clear flag indicating the need for
8423 // refinement
8424 quad->clear_user_flag();
8425 } // if (isotropic refinement)
8426 } // for all quads
8427 } // looped two times over all quads, all quads refined now
8428
8429 //---------------------------------
8430 // Now, finally, set up the new
8431 // cells
8432 //---------------------------------
8433
8435 cells_with_distorted_children;
8436
8437 for (unsigned int level = 0; level != triangulation.levels.size() - 1;
8438 ++level)
8439 {
8440 // only active objects can be refined further; remember
8441 // that we won't operate on the finest level, so
8442 // triangulation.begin_*(level+1) is allowed
8445 endh = triangulation.begin_active_hex(level + 1);
8447 next_unused_hex = triangulation.begin_raw_hex(level + 1);
8448
8449 for (; hex != endh; ++hex)
8450 if (hex->refine_flag_set())
8451 {
8452 // this hex needs to be refined
8453
8454 // clear flag indicating the need for refinement. do
8455 // it here already, since we can't do it anymore
8456 // once the cell has children
8457 const RefinementCase<dim> ref_case = hex->refine_flag_set();
8458 hex->clear_refine_flag();
8459 hex->set_refinement_case(ref_case);
8460
8461 // depending on the refine case we might have to
8462 // create additional vertices, lines and quads
8463 // interior of the hex before the actual children
8464 // can be set up.
8465
8466 // in a first step: reserve the needed space for
8467 // lines, quads and hexes and initialize them
8468 // correctly
8469
8470 unsigned int n_new_lines = 0;
8471 unsigned int n_new_quads = 0;
8472 unsigned int n_new_hexes = 0;
8473 switch (ref_case)
8474 {
8478 n_new_lines = 0;
8479 n_new_quads = 1;
8480 n_new_hexes = 2;
8481 break;
8485 n_new_lines = 1;
8486 n_new_quads = 4;
8487 n_new_hexes = 4;
8488 break;
8490 n_new_lines = 6;
8491 n_new_quads = 12;
8492 n_new_hexes = 8;
8493 break;
8494 default:
8496 break;
8497 }
8498
8499 // find some space for the newly to be created
8500 // interior lines and initialize them.
8501 std::vector<
8503 new_lines(n_new_lines);
8504 for (unsigned int i = 0; i < n_new_lines; ++i)
8505 {
8506 new_lines[i] =
8507 triangulation.faces->lines
8508 .template next_free_single_object<1>(triangulation);
8509
8510 AssertIsNotUsed(new_lines[i]);
8511 new_lines[i]->set_used_flag();
8512 new_lines[i]->clear_user_flag();
8513 new_lines[i]->clear_user_data();
8514 new_lines[i]->clear_children();
8515 // interior line
8516 new_lines[i]->set_boundary_id_internal(
8518 // they inherit geometry description of the hex they
8519 // belong to
8520 new_lines[i]->set_manifold_id(hex->manifold_id());
8521 }
8522
8523 // find some space for the newly to be created
8524 // interior quads and initialize them.
8525 std::vector<
8527 new_quads(n_new_quads);
8528 for (unsigned int i = 0; i < n_new_quads; ++i)
8529 {
8530 new_quads[i] =
8531 triangulation.faces->quads
8532 .template next_free_single_object<2>(triangulation);
8533
8534 AssertIsNotUsed(new_quads[i]);
8535 new_quads[i]->set_used_flag();
8536 new_quads[i]->clear_user_flag();
8537 new_quads[i]->clear_user_data();
8538 new_quads[i]->clear_children();
8539 // interior quad
8540 new_quads[i]->set_boundary_id_internal(
8542 // they inherit geometry description of the hex they
8543 // belong to
8544 new_quads[i]->set_manifold_id(hex->manifold_id());
8545 // set all line orientation flags to true by
8546 // default, change this afterwards, if necessary
8547 for (unsigned int j = 0;
8548 j < GeometryInfo<dim>::lines_per_face;
8549 ++j)
8550 new_quads[i]->set_line_orientation(
8552 }
8553
8554 types::subdomain_id subdomainid = hex->subdomain_id();
8555
8556 // find some space for the newly to be created hexes
8557 // and initialize them.
8558 std::vector<
8560 new_hexes(n_new_hexes);
8561 for (unsigned int i = 0; i < n_new_hexes; ++i)
8562 {
8563 if (i % 2 == 0)
8564 next_unused_hex =
8565 triangulation.levels[level + 1]->cells.next_free_hex(
8566 triangulation, level + 1);
8567 else
8568 ++next_unused_hex;
8569
8570 new_hexes[i] = next_unused_hex;
8571
8572 AssertIsNotUsed(new_hexes[i]);
8573 new_hexes[i]->set_used_flag();
8574 new_hexes[i]->clear_user_flag();
8575 new_hexes[i]->clear_user_data();
8576 new_hexes[i]->clear_children();
8577 // inherit material
8578 // properties
8579 new_hexes[i]->set_material_id(hex->material_id());
8580 new_hexes[i]->set_manifold_id(hex->manifold_id());
8581 new_hexes[i]->set_subdomain_id(subdomainid);
8582
8583 if (i % 2)
8584 new_hexes[i]->set_parent(hex->index());
8585 // set the face_orientation flag to true for all
8586 // faces initially, as this is the default value
8587 // which is true for all faces interior to the
8588 // hex. later on go the other way round and
8589 // reset faces that are at the boundary of the
8590 // mother cube
8591 //
8592 // the same is true for the face_flip and
8593 // face_rotation flags. however, the latter two
8594 // are set to false by default as this is the
8595 // standard value
8596 for (const unsigned int f :
8598 new_hexes[i]->set_combined_face_orientation(
8600 }
8601 // note these hexes as children to the present cell
8602 for (unsigned int i = 0; i < n_new_hexes / 2; ++i)
8603 hex->set_children(2 * i, new_hexes[2 * i]->index());
8604
8605 // we have to take into account whether the
8606 // different faces are oriented correctly or in the
8607 // opposite direction, so store that up front
8608
8609 // face_orientation
8610 const bool f_or[6] = {hex->face_orientation(0),
8611 hex->face_orientation(1),
8612 hex->face_orientation(2),
8613 hex->face_orientation(3),
8614 hex->face_orientation(4),
8615 hex->face_orientation(5)};
8616
8617 // face_flip
8618 const bool f_fl[6] = {hex->face_flip(0),
8619 hex->face_flip(1),
8620 hex->face_flip(2),
8621 hex->face_flip(3),
8622 hex->face_flip(4),
8623 hex->face_flip(5)};
8624
8625 // face_rotation
8626 const bool f_ro[6] = {hex->face_rotation(0),
8627 hex->face_rotation(1),
8628 hex->face_rotation(2),
8629 hex->face_rotation(3),
8630 hex->face_rotation(4),
8631 hex->face_rotation(5)};
8632
8633 // combined orientation
8634 const types::geometric_orientation f_co[6] = {
8635 hex->combined_face_orientation(0),
8636 hex->combined_face_orientation(1),
8637 hex->combined_face_orientation(2),
8638 hex->combined_face_orientation(3),
8639 hex->combined_face_orientation(4),
8640 hex->combined_face_orientation(5)};
8641
8642 // little helper table, indicating, whether the
8643 // child with index 0 or with index 1 can be found
8644 // at the standard origin of an anisotropically
8645 // refined quads in real orientation index 1:
8646 // (RefineCase - 1) index 2: face_flip
8647
8648 // index 3: face rotation
8649 // note: face orientation has no influence
8650 const unsigned int child_at_origin[2][2][2] = {
8651 {{0, 0}, // RefinementCase<dim>::cut_x, face_flip=false,
8652 // face_rotation=false and true
8653 {1, 1}}, // RefinementCase<dim>::cut_x, face_flip=true,
8654 // face_rotation=false and true
8655 {{0, 1}, // RefinementCase<dim>::cut_y, face_flip=false,
8656 // face_rotation=false and true
8657 {1, 0}}}; // RefinementCase<dim>::cut_y, face_flip=true,
8658 // face_rotation=false and true
8659
8660 //-------------------------------------
8661 //
8662 // in the following we will do the same thing for
8663 // each refinement case: create a new vertex (if
8664 // needed), create new interior lines (if needed),
8665 // create new interior quads and afterwards build
8666 // the children hexes out of these and the existing
8667 // subfaces of the outer quads (which have been
8668 // created above). However, even if the steps are
8669 // quite similar, the actual work strongly depends
8670 // on the actual refinement case. therefore, we use
8671 // separate blocks of code for each of these cases,
8672 // which hopefully increases the readability to some
8673 // extend.
8674
8675 switch (ref_case)
8676 {
8678 {
8679 //----------------------------
8680 //
8681 // RefinementCase<dim>::cut_x
8682 //
8683 // the refined cube will look
8684 // like this:
8685 //
8686 // *----*----*
8687 // / / /|
8688 // / / / |
8689 // / / / |
8690 // *----*----* |
8691 // | | | |
8692 // | | | *
8693 // | | | /
8694 // | | | /
8695 // | | |/
8696 // *----*----*
8697 //
8698 // again, first collect some data about the
8699 // indices of the lines, with the following
8700 // numbering:
8701
8702 // face 2: front plane
8703 // (note: x,y exchanged)
8704 // *---*---*
8705 // | | |
8706 // | 0 |
8707 // | | |
8708 // *---*---*
8709 // m0
8710 // face 3: back plane
8711 // (note: x,y exchanged)
8712 // m1
8713 // *---*---*
8714 // | | |
8715 // | 1 |
8716 // | | |
8717 // *---*---*
8718 // face 4: bottom plane
8719 // *---*---*
8720 // / / /
8721 // / 2 /
8722 // / / /
8723 // *---*---*
8724 // m0
8725 // face 5: top plane
8726 // m1
8727 // *---*---*
8728 // / / /
8729 // / 3 /
8730 // / / /
8731 // *---*---*
8732
8733 // set up a list of line iterators first. from
8734 // this, construct lists of line_indices and
8735 // line orientations later on
8736 const typename Triangulation<dim, spacedim>::
8737 raw_line_iterator lines[4] = {
8738 hex->face(2)->child(0)->line(
8739 (hex->face(2)->refinement_case() ==
8741 1 :
8742 3), // 0
8743 hex->face(3)->child(0)->line(
8744 (hex->face(3)->refinement_case() ==
8746 1 :
8747 3), // 1
8748 hex->face(4)->child(0)->line(
8749 (hex->face(4)->refinement_case() ==
8751 1 :
8752 3), // 2
8753 hex->face(5)->child(0)->line(
8754 (hex->face(5)->refinement_case() ==
8756 1 :
8757 3) // 3
8758 };
8759
8760 unsigned int line_indices[4];
8761 for (unsigned int i = 0; i < 4; ++i)
8762 line_indices[i] = lines[i]->index();
8763
8764 // the orientation of lines for the inner quads
8765 // is quite tricky. as these lines are newly
8766 // created ones and thus have no parents, they
8767 // cannot inherit this property. set up an array
8768 // and fill it with the respective values
8769 types::geometric_orientation line_orientation[4]{};
8770
8771 // the middle vertex marked as m0 above is the
8772 // start vertex for lines 0 and 2 in standard
8773 // orientation, whereas m1 is the end vertex of
8774 // lines 1 and 3 in standard orientation
8775 const unsigned int middle_vertices[2] = {
8776 hex->line(2)->child(0)->vertex_index(1),
8777 hex->line(7)->child(0)->vertex_index(1)};
8778
8779 for (unsigned int i = 0; i < 4; ++i)
8780 if (lines[i]->vertex_index(i % 2) ==
8781 middle_vertices[i % 2])
8782 line_orientation[i] =
8784 else
8785 {
8786 // it must be the other way round then
8787 Assert(lines[i]->vertex_index((i + 1) % 2) ==
8788 middle_vertices[i % 2],
8790 line_orientation[i] =
8792 }
8793
8794 // set up the new quad, line numbering is as
8795 // indicated above
8796 new_quads[0]->set_bounding_object_indices(
8797 {line_indices[0],
8798 line_indices[1],
8799 line_indices[2],
8800 line_indices[3]});
8801
8802 new_quads[0]->set_line_orientation(
8803 0, line_orientation[0]);
8804 new_quads[0]->set_line_orientation(
8805 1, line_orientation[1]);
8806 new_quads[0]->set_line_orientation(
8807 2, line_orientation[2]);
8808 new_quads[0]->set_line_orientation(
8809 3, line_orientation[3]);
8810
8811 // the quads are numbered as follows:
8812 //
8813 // planes in the interior of the old hex:
8814 //
8815 // *
8816 // /|
8817 // / | x
8818 // / | *-------* *---------*
8819 // * | | | / /
8820 // | 0 | | | / /
8821 // | * | | / /
8822 // | / *-------*y *---------*x
8823 // | /
8824 // |/
8825 // *
8826 //
8827 // children of the faces of the old hex
8828 //
8829 // *---*---* *---*---*
8830 // /| | | / / /|
8831 // / | | | / 9 / 10/ |
8832 // / | 5 | 6 | / / / |
8833 // * | | | *---*---* |
8834 // | 1 *---*---* | | | 2 *
8835 // | / / / | | | /
8836 // | / 7 / 8 / | 3 | 4 | /
8837 // |/ / / | | |/
8838 // *---*---* *---*---*
8839 //
8840 // note that we have to take care of the
8841 // orientation of faces.
8842 const int quad_indices[11] = {
8843 new_quads[0]->index(), // 0
8844
8845 hex->face(0)->index(), // 1
8846
8847 hex->face(1)->index(), // 2
8848
8849 hex->face(2)->child_index(
8850 child_at_origin[hex->face(2)->refinement_case() -
8851 1][f_fl[2]][f_ro[2]]), // 3
8852 hex->face(2)->child_index(
8853 1 -
8854 child_at_origin[hex->face(2)->refinement_case() -
8855 1][f_fl[2]][f_ro[2]]),
8856
8857 hex->face(3)->child_index(
8858 child_at_origin[hex->face(3)->refinement_case() -
8859 1][f_fl[3]][f_ro[3]]), // 5
8860 hex->face(3)->child_index(
8861 1 -
8862 child_at_origin[hex->face(3)->refinement_case() -
8863 1][f_fl[3]][f_ro[3]]),
8864
8865 hex->face(4)->child_index(
8866 child_at_origin[hex->face(4)->refinement_case() -
8867 1][f_fl[4]][f_ro[4]]), // 7
8868 hex->face(4)->child_index(
8869 1 -
8870 child_at_origin[hex->face(4)->refinement_case() -
8871 1][f_fl[4]][f_ro[4]]),
8872
8873 hex->face(5)->child_index(
8874 child_at_origin[hex->face(5)->refinement_case() -
8875 1][f_fl[5]][f_ro[5]]), // 9
8876 hex->face(5)->child_index(
8877 1 -
8878 child_at_origin[hex->face(5)->refinement_case() -
8879 1][f_fl[5]][f_ro[5]])
8880
8881 };
8882
8883 new_hexes[0]->set_bounding_object_indices(
8884 {quad_indices[1],
8885 quad_indices[0],
8886 quad_indices[3],
8887 quad_indices[5],
8888 quad_indices[7],
8889 quad_indices[9]});
8890 new_hexes[1]->set_bounding_object_indices(
8891 {quad_indices[0],
8892 quad_indices[2],
8893 quad_indices[4],
8894 quad_indices[6],
8895 quad_indices[8],
8896 quad_indices[10]});
8897 break;
8898 }
8899
8901 {
8902 //----------------------------
8903 //
8904 // RefinementCase<dim>::cut_y
8905 //
8906 // the refined cube will look like this:
8907 //
8908 // *---------*
8909 // / /|
8910 // *---------* |
8911 // / /| |
8912 // *---------* | |
8913 // | | | |
8914 // | | | *
8915 // | | |/
8916 // | | *
8917 // | |/
8918 // *---------*
8919 //
8920 // again, first collect some data about the
8921 // indices of the lines, with the following
8922 // numbering:
8923
8924 // face 0: left plane
8925 // *
8926 // /|
8927 // * |
8928 // /| |
8929 // * | |
8930 // | 0 |
8931 // | | *
8932 // | |/
8933 // | *m0
8934 // |/
8935 // *
8936 // face 1: right plane
8937 // *
8938 // /|
8939 // m1* |
8940 // /| |
8941 // * | |
8942 // | 1 |
8943 // | | *
8944 // | |/
8945 // | *
8946 // |/
8947 // *
8948 // face 4: bottom plane
8949 // *-------*
8950 // / /
8951 // m0*---2---*
8952 // / /
8953 // *-------*
8954 // face 5: top plane
8955 // *-------*
8956 // / /
8957 // *---3---*m1
8958 // / /
8959 // *-------*
8960
8961 // set up a list of line iterators first. from
8962 // this, construct lists of line_indices and
8963 // line orientations later on
8964 const typename Triangulation<dim, spacedim>::
8965 raw_line_iterator lines[4] = {
8966 hex->face(0)->child(0)->line(
8967 (hex->face(0)->refinement_case() ==
8969 1 :
8970 3), // 0
8971 hex->face(1)->child(0)->line(
8972 (hex->face(1)->refinement_case() ==
8974 1 :
8975 3), // 1
8976 hex->face(4)->child(0)->line(
8977 (hex->face(4)->refinement_case() ==
8979 1 :
8980 3), // 2
8981 hex->face(5)->child(0)->line(
8982 (hex->face(5)->refinement_case() ==
8984 1 :
8985 3) // 3
8986 };
8987
8988 unsigned int line_indices[4];
8989 for (unsigned int i = 0; i < 4; ++i)
8990 line_indices[i] = lines[i]->index();
8991
8992 // the orientation of lines for the inner quads
8993 // is quite tricky. as these lines are newly
8994 // created ones and thus have no parents, they
8995 // cannot inherit this property. set up an array
8996 // and fill it with the respective values
8997 types::geometric_orientation line_orientation[4]{};
8998
8999 // the middle vertex marked as m0 above is the
9000 // start vertex for lines 0 and 2 in standard
9001 // orientation, whereas m1 is the end vertex of
9002 // lines 1 and 3 in standard orientation
9003 const unsigned int middle_vertices[2] = {
9004 hex->line(0)->child(0)->vertex_index(1),
9005 hex->line(5)->child(0)->vertex_index(1)};
9006
9007 for (unsigned int i = 0; i < 4; ++i)
9008 if (lines[i]->vertex_index(i % 2) ==
9009 middle_vertices[i % 2])
9010 line_orientation[i] =
9012 else
9013 {
9014 // it must be the other way round then
9015 Assert(lines[i]->vertex_index((i + 1) % 2) ==
9016 middle_vertices[i % 2],
9018 line_orientation[i] =
9020 }
9021
9022 // set up the new quad, line numbering is as
9023 // indicated above
9024 new_quads[0]->set_bounding_object_indices(
9025 {line_indices[2],
9026 line_indices[3],
9027 line_indices[0],
9028 line_indices[1]});
9029
9030 new_quads[0]->set_line_orientation(
9031 0, line_orientation[2]);
9032 new_quads[0]->set_line_orientation(
9033 1, line_orientation[3]);
9034 new_quads[0]->set_line_orientation(
9035 2, line_orientation[0]);
9036 new_quads[0]->set_line_orientation(
9037 3, line_orientation[1]);
9038
9039 // the quads are numbered as follows:
9040 //
9041 // planes in the interior of the old hex:
9042 //
9043 // *
9044 // /|
9045 // / | x
9046 // / | *-------* *---------*
9047 // * | | | / /
9048 // | | | 0 | / /
9049 // | * | | / /
9050 // | / *-------*y *---------*x
9051 // | /
9052 // |/
9053 // *
9054 //
9055 // children of the faces of the old hex
9056 //
9057 // *-------* *-------*
9058 // /| | / 10 /|
9059 // * | | *-------* |
9060 // /| | 6 | / 9 /| |
9061 // * |2| | *-------* |4|
9062 // | | *-------* | | | *
9063 // |1|/ 8 / | |3|/
9064 // | *-------* | 5 | *
9065 // |/ 7 / | |/
9066 // *-------* *-------*
9067 //
9068 // note that we have to take care of the
9069 // orientation of faces.
9070 const int quad_indices[11] = {
9071 new_quads[0]->index(), // 0
9072
9073 hex->face(0)->child_index(
9074 child_at_origin[hex->face(0)->refinement_case() -
9075 1][f_fl[0]][f_ro[0]]), // 1
9076 hex->face(0)->child_index(
9077 1 -
9078 child_at_origin[hex->face(0)->refinement_case() -
9079 1][f_fl[0]][f_ro[0]]),
9080
9081 hex->face(1)->child_index(
9082 child_at_origin[hex->face(1)->refinement_case() -
9083 1][f_fl[1]][f_ro[1]]), // 3
9084 hex->face(1)->child_index(
9085 1 -
9086 child_at_origin[hex->face(1)->refinement_case() -
9087 1][f_fl[1]][f_ro[1]]),
9088
9089 hex->face(2)->index(), // 5
9090
9091 hex->face(3)->index(), // 6
9092
9093 hex->face(4)->child_index(
9094 child_at_origin[hex->face(4)->refinement_case() -
9095 1][f_fl[4]][f_ro[4]]), // 7
9096 hex->face(4)->child_index(
9097 1 -
9098 child_at_origin[hex->face(4)->refinement_case() -
9099 1][f_fl[4]][f_ro[4]]),
9100
9101 hex->face(5)->child_index(
9102 child_at_origin[hex->face(5)->refinement_case() -
9103 1][f_fl[5]][f_ro[5]]), // 9
9104 hex->face(5)->child_index(
9105 1 -
9106 child_at_origin[hex->face(5)->refinement_case() -
9107 1][f_fl[5]][f_ro[5]])
9108
9109 };
9110
9111 new_hexes[0]->set_bounding_object_indices(
9112 {quad_indices[1],
9113 quad_indices[3],
9114 quad_indices[5],
9115 quad_indices[0],
9116 quad_indices[7],
9117 quad_indices[9]});
9118 new_hexes[1]->set_bounding_object_indices(
9119 {quad_indices[2],
9120 quad_indices[4],
9121 quad_indices[0],
9122 quad_indices[6],
9123 quad_indices[8],
9124 quad_indices[10]});
9125 break;
9126 }
9127
9129 {
9130 //----------------------------
9131 //
9132 // RefinementCase<dim>::cut_z
9133 //
9134 // the refined cube will look like this:
9135 //
9136 // *---------*
9137 // / /|
9138 // / / |
9139 // / / *
9140 // *---------* /|
9141 // | | / |
9142 // | |/ *
9143 // *---------* /
9144 // | | /
9145 // | |/
9146 // *---------*
9147 //
9148 // again, first collect some data about the
9149 // indices of the lines, with the following
9150 // numbering:
9151
9152 // face 0: left plane
9153 // *
9154 // /|
9155 // / |
9156 // / *
9157 // * /|
9158 // | 0 |
9159 // |/ *
9160 // m0* /
9161 // | /
9162 // |/
9163 // *
9164 // face 1: right plane
9165 // *
9166 // /|
9167 // / |
9168 // / *m1
9169 // * /|
9170 // | 1 |
9171 // |/ *
9172 // * /
9173 // | /
9174 // |/
9175 // *
9176 // face 2: front plane
9177 // (note: x,y exchanged)
9178 // *-------*
9179 // | |
9180 // m0*---2---*
9181 // | |
9182 // *-------*
9183 // face 3: back plane
9184 // (note: x,y exchanged)
9185 // *-------*
9186 // | |
9187 // *---3---*m1
9188 // | |
9189 // *-------*
9190
9191 // set up a list of line iterators first. from
9192 // this, construct lists of line_indices and
9193 // line orientations later on
9194 const typename Triangulation<dim, spacedim>::
9195 raw_line_iterator lines[4] = {
9196 hex->face(0)->child(0)->line(
9197 (hex->face(0)->refinement_case() ==
9199 1 :
9200 3), // 0
9201 hex->face(1)->child(0)->line(
9202 (hex->face(1)->refinement_case() ==
9204 1 :
9205 3), // 1
9206 hex->face(2)->child(0)->line(
9207 (hex->face(2)->refinement_case() ==
9209 1 :
9210 3), // 2
9211 hex->face(3)->child(0)->line(
9212 (hex->face(3)->refinement_case() ==
9214 1 :
9215 3) // 3
9216 };
9217
9218 unsigned int line_indices[4];
9219 for (unsigned int i = 0; i < 4; ++i)
9220 line_indices[i] = lines[i]->index();
9221
9222 // the orientation of lines for the inner quads
9223 // is quite tricky. as these lines are newly
9224 // created ones and thus have no parents, they
9225 // cannot inherit this property. set up an array
9226 // and fill it with the respective values
9227 types::geometric_orientation line_orientation[4]{};
9228
9229 // the middle vertex marked as m0 above is the
9230 // start vertex for lines 0 and 2 in standard
9231 // orientation, whereas m1 is the end vertex of
9232 // lines 1 and 3 in standard orientation
9233 const unsigned int middle_vertices[2] = {
9234 middle_vertex_index<dim, spacedim>(hex->line(8)),
9235 middle_vertex_index<dim, spacedim>(hex->line(11))};
9236
9237 for (unsigned int i = 0; i < 4; ++i)
9238 if (lines[i]->vertex_index(i % 2) ==
9239 middle_vertices[i % 2])
9240 line_orientation[i] =
9242 else
9243 {
9244 // it must be the other way round then
9245 Assert(lines[i]->vertex_index((i + 1) % 2) ==
9246 middle_vertices[i % 2],
9248 line_orientation[i] =
9250 }
9251
9252 // set up the new quad, line numbering is as
9253 // indicated above
9254 new_quads[0]->set_bounding_object_indices(
9255 {line_indices[0],
9256 line_indices[1],
9257 line_indices[2],
9258 line_indices[3]});
9259
9260 new_quads[0]->set_line_orientation(
9261 0, line_orientation[0]);
9262 new_quads[0]->set_line_orientation(
9263 1, line_orientation[1]);
9264 new_quads[0]->set_line_orientation(
9265 2, line_orientation[2]);
9266 new_quads[0]->set_line_orientation(
9267 3, line_orientation[3]);
9268
9269 // the quads are numbered as follows:
9270 //
9271 // planes in the interior of the old hex:
9272 //
9273 // *
9274 // /|
9275 // / | x
9276 // / | *-------* *---------*
9277 // * | | | / /
9278 // | | | | / 0 /
9279 // | * | | / /
9280 // | / *-------*y *---------*x
9281 // | /
9282 // |/
9283 // *
9284 //
9285 // children of the faces of the old hex
9286 //
9287 // *---*---* *-------*
9288 // /| 8 | / /|
9289 // / | | / 10 / |
9290 // / *-------* / / *
9291 // * 2/| | *-------* 4/|
9292 // | / | 7 | | 6 | / |
9293 // |/1 *-------* | |/3 *
9294 // * / / *-------* /
9295 // | / 9 / | | /
9296 // |/ / | 5 |/
9297 // *-------* *---*---*
9298 //
9299 // note that we have to take care of the
9300 // orientation of faces.
9301 const int quad_indices[11] = {
9302 new_quads[0]->index(), // 0
9303
9304 hex->face(0)->child_index(
9305 child_at_origin[hex->face(0)->refinement_case() -
9306 1][f_fl[0]][f_ro[0]]), // 1
9307 hex->face(0)->child_index(
9308 1 -
9309 child_at_origin[hex->face(0)->refinement_case() -
9310 1][f_fl[0]][f_ro[0]]),
9311
9312 hex->face(1)->child_index(
9313 child_at_origin[hex->face(1)->refinement_case() -
9314 1][f_fl[1]][f_ro[1]]), // 3
9315 hex->face(1)->child_index(
9316 1 -
9317 child_at_origin[hex->face(1)->refinement_case() -
9318 1][f_fl[1]][f_ro[1]]),
9319
9320 hex->face(2)->child_index(
9321 child_at_origin[hex->face(2)->refinement_case() -
9322 1][f_fl[2]][f_ro[2]]), // 5
9323 hex->face(2)->child_index(
9324 1 -
9325 child_at_origin[hex->face(2)->refinement_case() -
9326 1][f_fl[2]][f_ro[2]]),
9327
9328 hex->face(3)->child_index(
9329 child_at_origin[hex->face(3)->refinement_case() -
9330 1][f_fl[3]][f_ro[3]]), // 7
9331 hex->face(3)->child_index(
9332 1 -
9333 child_at_origin[hex->face(3)->refinement_case() -
9334 1][f_fl[3]][f_ro[3]]),
9335
9336 hex->face(4)->index(), // 9
9337
9338 hex->face(5)->index() // 10
9339 };
9340
9341 new_hexes[0]->set_bounding_object_indices(
9342 {quad_indices[1],
9343 quad_indices[3],
9344 quad_indices[5],
9345 quad_indices[7],
9346 quad_indices[9],
9347 quad_indices[0]});
9348 new_hexes[1]->set_bounding_object_indices(
9349 {quad_indices[2],
9350 quad_indices[4],
9351 quad_indices[6],
9352 quad_indices[8],
9353 quad_indices[0],
9354 quad_indices[10]});
9355 break;
9356 }
9357
9359 {
9360 //----------------------------
9361 //
9362 // RefinementCase<dim>::cut_xy
9363 //
9364 // the refined cube will look like this:
9365 //
9366 // *----*----*
9367 // / / /|
9368 // *----*----* |
9369 // / / /| |
9370 // *----*----* | |
9371 // | | | | |
9372 // | | | | *
9373 // | | | |/
9374 // | | | *
9375 // | | |/
9376 // *----*----*
9377 //
9378
9379 // first, create the new internal line
9380 new_lines[0]->set_bounding_object_indices(
9381 {middle_vertex_index<dim, spacedim>(hex->face(4)),
9382 middle_vertex_index<dim, spacedim>(hex->face(5))});
9383
9384 // again, first collect some data about the
9385 // indices of the lines, with the following
9386 // numbering:
9387
9388 // face 0: left plane
9389 // *
9390 // /|
9391 // * |
9392 // /| |
9393 // * | |
9394 // | 0 |
9395 // | | *
9396 // | |/
9397 // | *
9398 // |/
9399 // *
9400 // face 1: right plane
9401 // *
9402 // /|
9403 // * |
9404 // /| |
9405 // * | |
9406 // | 1 |
9407 // | | *
9408 // | |/
9409 // | *
9410 // |/
9411 // *
9412 // face 2: front plane
9413 // (note: x,y exchanged)
9414 // *---*---*
9415 // | | |
9416 // | 2 |
9417 // | | |
9418 // *-------*
9419 // face 3: back plane
9420 // (note: x,y exchanged)
9421 // *---*---*
9422 // | | |
9423 // | 3 |
9424 // | | |
9425 // *---*---*
9426 // face 4: bottom plane
9427 // *---*---*
9428 // / 5 /
9429 // *-6-*-7-*
9430 // / 4 /
9431 // *---*---*
9432 // face 5: top plane
9433 // *---*---*
9434 // / 9 /
9435 // *10-*-11*
9436 // / 8 /
9437 // *---*---*
9438 // middle planes
9439 // *-------* *---*---*
9440 // / / | | |
9441 // / / | 12 |
9442 // / / | | |
9443 // *-------* *---*---*
9444
9445 // set up a list of line iterators first. from
9446 // this, construct lists of line_indices and
9447 // line orientations later on
9448 const typename Triangulation<
9449 dim,
9450 spacedim>::raw_line_iterator lines[13] = {
9451 hex->face(0)->child(0)->line(
9452 (hex->face(0)->refinement_case() ==
9454 1 :
9455 3), // 0
9456 hex->face(1)->child(0)->line(
9457 (hex->face(1)->refinement_case() ==
9459 1 :
9460 3), // 1
9461 hex->face(2)->child(0)->line(
9462 (hex->face(2)->refinement_case() ==
9464 1 :
9465 3), // 2
9466 hex->face(3)->child(0)->line(
9467 (hex->face(3)->refinement_case() ==
9469 1 :
9470 3), // 3
9471
9472 hex->face(4)
9473 ->isotropic_child(
9475 0, f_or[4], f_fl[4], f_ro[4]))
9476 ->line(
9478 1, f_or[4], f_fl[4], f_ro[4])), // 4
9479 hex->face(4)
9480 ->isotropic_child(
9482 3, f_or[4], f_fl[4], f_ro[4]))
9483 ->line(
9485 0, f_or[4], f_fl[4], f_ro[4])), // 5
9486 hex->face(4)
9487 ->isotropic_child(
9489 0, f_or[4], f_fl[4], f_ro[4]))
9490 ->line(
9492 3, f_or[4], f_fl[4], f_ro[4])), // 6
9493 hex->face(4)
9494 ->isotropic_child(
9496 3, f_or[4], f_fl[4], f_ro[4]))
9497 ->line(
9499 2, f_or[4], f_fl[4], f_ro[4])), // 7
9500
9501 hex->face(5)
9502 ->isotropic_child(
9504 0, f_or[5], f_fl[5], f_ro[5]))
9505 ->line(
9507 1, f_or[5], f_fl[5], f_ro[5])), // 8
9508 hex->face(5)
9509 ->isotropic_child(
9511 3, f_or[5], f_fl[5], f_ro[5]))
9512 ->line(
9514 0, f_or[5], f_fl[5], f_ro[5])), // 9
9515 hex->face(5)
9516 ->isotropic_child(
9518 0, f_or[5], f_fl[5], f_ro[5]))
9519 ->line(
9521 3, f_or[5], f_fl[5], f_ro[5])), // 10
9522 hex->face(5)
9523 ->isotropic_child(
9525 3, f_or[5], f_fl[5], f_ro[5]))
9526 ->line(
9528 2, f_or[5], f_fl[5], f_ro[5])), // 11
9529
9530 new_lines[0] // 12
9531 };
9532
9533 unsigned int line_indices[13];
9534 for (unsigned int i = 0; i < 13; ++i)
9535 line_indices[i] = lines[i]->index();
9536
9537 // the orientation of lines for the inner quads
9538 // is quite tricky. as these lines are newly
9539 // created ones and thus have no parents, they
9540 // cannot inherit this property. set up an array
9541 // and fill it with the respective values
9542 types::geometric_orientation line_orientation[13]{};
9543
9544 // the middle vertices of the lines of our
9545 // bottom face
9546 const unsigned int middle_vertices[4] = {
9547 hex->line(0)->child(0)->vertex_index(1),
9548 hex->line(1)->child(0)->vertex_index(1),
9549 hex->line(2)->child(0)->vertex_index(1),
9550 hex->line(3)->child(0)->vertex_index(1),
9551 };
9552
9553 // note: for lines 0 to 3 the orientation of the
9554 // line is 'true', if vertex 0 is on the bottom
9555 // face
9556 for (unsigned int i = 0; i < 4; ++i)
9557 if (lines[i]->vertex_index(0) == middle_vertices[i])
9558 line_orientation[i] =
9560 else
9561 {
9562 // it must be the other way round then
9563 Assert(lines[i]->vertex_index(1) ==
9564 middle_vertices[i],
9566 line_orientation[i] =
9568 }
9569
9570 // note: for lines 4 to 11 (inner lines of the
9571 // outer quads) the following holds: the second
9572 // vertex of the even lines in standard
9573 // orientation is the vertex in the middle of
9574 // the quad, whereas for odd lines the first
9575 // vertex is the same middle vertex.
9576 for (unsigned int i = 4; i < 12; ++i)
9577 if (lines[i]->vertex_index((i + 1) % 2) ==
9578 middle_vertex_index<dim, spacedim>(
9579 hex->face(3 + i / 4)))
9580 line_orientation[i] =
9582 else
9583 {
9584 // it must be the other way round then
9585 Assert(lines[i]->vertex_index(i % 2) ==
9586 (middle_vertex_index<dim, spacedim>(
9587 hex->face(3 + i / 4))),
9589 line_orientation[i] =
9591 }
9592 // for the last line the line orientation is
9593 // always true, since it was just constructed
9594 // that way
9595 line_orientation[12] =
9597
9598 // set up the 4 quads, numbered as follows (left
9599 // quad numbering, right line numbering
9600 // extracted from above)
9601 //
9602 // * *
9603 // /| 9|
9604 // * | * |
9605 // y/| | 8| 3
9606 // * |1| * | |
9607 // | | |x | 12|
9608 // |0| * | | *
9609 // | |/ 2 |5
9610 // | * | *
9611 // |/ |4
9612 // * *
9613 //
9614 // x
9615 // *---*---* *10-*-11*
9616 // | | | | | |
9617 // | 2 | 3 | 0 12 1
9618 // | | | | | |
9619 // *---*---*y *-6-*-7-*
9620
9621 new_quads[0]->set_bounding_object_indices(
9622 {line_indices[2],
9623 line_indices[12],
9624 line_indices[4],
9625 line_indices[8]});
9626 new_quads[1]->set_bounding_object_indices(
9627 {line_indices[12],
9628 line_indices[3],
9629 line_indices[5],
9630 line_indices[9]});
9631 new_quads[2]->set_bounding_object_indices(
9632 {line_indices[6],
9633 line_indices[10],
9634 line_indices[0],
9635 line_indices[12]});
9636 new_quads[3]->set_bounding_object_indices(
9637 {line_indices[7],
9638 line_indices[11],
9639 line_indices[12],
9640 line_indices[1]});
9641
9642 new_quads[0]->set_line_orientation(
9643 0, line_orientation[2]);
9644 new_quads[0]->set_line_orientation(
9645 2, line_orientation[4]);
9646 new_quads[0]->set_line_orientation(
9647 3, line_orientation[8]);
9648
9649 new_quads[1]->set_line_orientation(
9650 1, line_orientation[3]);
9651 new_quads[1]->set_line_orientation(
9652 2, line_orientation[5]);
9653 new_quads[1]->set_line_orientation(
9654 3, line_orientation[9]);
9655
9656 new_quads[2]->set_line_orientation(
9657 0, line_orientation[6]);
9658 new_quads[2]->set_line_orientation(
9659 1, line_orientation[10]);
9660 new_quads[2]->set_line_orientation(
9661 2, line_orientation[0]);
9662
9663 new_quads[3]->set_line_orientation(
9664 0, line_orientation[7]);
9665 new_quads[3]->set_line_orientation(
9666 1, line_orientation[11]);
9667 new_quads[3]->set_line_orientation(
9668 3, line_orientation[1]);
9669
9670 // the quads are numbered as follows:
9671 //
9672 // planes in the interior of the old hex:
9673 //
9674 // *
9675 // /|
9676 // * | x
9677 // /| | *---*---* *---------*
9678 // * |1| | | | / /
9679 // | | | | 2 | 3 | / /
9680 // |0| * | | | / /
9681 // | |/ *---*---*y *---------*x
9682 // | *
9683 // |/
9684 // *
9685 //
9686 // children of the faces of the old hex
9687 //
9688 // *---*---* *---*---*
9689 // /| | | /18 / 19/|
9690 // * |10 | 11| /---/---* |
9691 // /| | | | /16 / 17/| |
9692 // * |5| | | *---*---* |7|
9693 // | | *---*---* | | | | *
9694 // |4|/14 / 15/ | | |6|/
9695 // | *---/---/ | 8 | 9 | *
9696 // |/12 / 13/ | | |/
9697 // *---*---* *---*---*
9698 //
9699 // note that we have to take care of the
9700 // orientation of faces.
9701 const int quad_indices[20] = {
9702 new_quads[0]->index(), // 0
9703 new_quads[1]->index(),
9704 new_quads[2]->index(),
9705 new_quads[3]->index(),
9706
9707 hex->face(0)->child_index(
9708 child_at_origin[hex->face(0)->refinement_case() -
9709 1][f_fl[0]][f_ro[0]]), // 4
9710 hex->face(0)->child_index(
9711 1 -
9712 child_at_origin[hex->face(0)->refinement_case() -
9713 1][f_fl[0]][f_ro[0]]),
9714
9715 hex->face(1)->child_index(
9716 child_at_origin[hex->face(1)->refinement_case() -
9717 1][f_fl[1]][f_ro[1]]), // 6
9718 hex->face(1)->child_index(
9719 1 -
9720 child_at_origin[hex->face(1)->refinement_case() -
9721 1][f_fl[1]][f_ro[1]]),
9722
9723 hex->face(2)->child_index(
9724 child_at_origin[hex->face(2)->refinement_case() -
9725 1][f_fl[2]][f_ro[2]]), // 8
9726 hex->face(2)->child_index(
9727 1 -
9728 child_at_origin[hex->face(2)->refinement_case() -
9729 1][f_fl[2]][f_ro[2]]),
9730
9731 hex->face(3)->child_index(
9732 child_at_origin[hex->face(3)->refinement_case() -
9733 1][f_fl[3]][f_ro[3]]), // 10
9734 hex->face(3)->child_index(
9735 1 -
9736 child_at_origin[hex->face(3)->refinement_case() -
9737 1][f_fl[3]][f_ro[3]]),
9738
9739 hex->face(4)->isotropic_child_index(
9741 0, f_or[4], f_fl[4], f_ro[4])), // 12
9742 hex->face(4)->isotropic_child_index(
9744 1, f_or[4], f_fl[4], f_ro[4])),
9745 hex->face(4)->isotropic_child_index(
9747 2, f_or[4], f_fl[4], f_ro[4])),
9748 hex->face(4)->isotropic_child_index(
9750 3, f_or[4], f_fl[4], f_ro[4])),
9751
9752 hex->face(5)->isotropic_child_index(
9754 0, f_or[5], f_fl[5], f_ro[5])), // 16
9755 hex->face(5)->isotropic_child_index(
9757 1, f_or[5], f_fl[5], f_ro[5])),
9758 hex->face(5)->isotropic_child_index(
9760 2, f_or[5], f_fl[5], f_ro[5])),
9761 hex->face(5)->isotropic_child_index(
9763 3, f_or[5], f_fl[5], f_ro[5]))};
9764
9765 new_hexes[0]->set_bounding_object_indices(
9766 {quad_indices[4],
9767 quad_indices[0],
9768 quad_indices[8],
9769 quad_indices[2],
9770 quad_indices[12],
9771 quad_indices[16]});
9772 new_hexes[1]->set_bounding_object_indices(
9773 {quad_indices[0],
9774 quad_indices[6],
9775 quad_indices[9],
9776 quad_indices[3],
9777 quad_indices[13],
9778 quad_indices[17]});
9779 new_hexes[2]->set_bounding_object_indices(
9780 {quad_indices[5],
9781 quad_indices[1],
9782 quad_indices[2],
9783 quad_indices[10],
9784 quad_indices[14],
9785 quad_indices[18]});
9786 new_hexes[3]->set_bounding_object_indices(
9787 {quad_indices[1],
9788 quad_indices[7],
9789 quad_indices[3],
9790 quad_indices[11],
9791 quad_indices[15],
9792 quad_indices[19]});
9793 break;
9794 }
9795
9797 {
9798 //----------------------------
9799 //
9800 // RefinementCase<dim>::cut_xz
9801 //
9802 // the refined cube will look like this:
9803 //
9804 // *----*----*
9805 // / / /|
9806 // / / / |
9807 // / / / *
9808 // *----*----* /|
9809 // | | | / |
9810 // | | |/ *
9811 // *----*----* /
9812 // | | | /
9813 // | | |/
9814 // *----*----*
9815 //
9816
9817 // first, create the new internal line
9818 new_lines[0]->set_bounding_object_indices(
9819 {middle_vertex_index<dim, spacedim>(hex->face(2)),
9820 middle_vertex_index<dim, spacedim>(hex->face(3))});
9821
9822 // again, first collect some data about the
9823 // indices of the lines, with the following
9824 // numbering:
9825
9826 // face 0: left plane
9827 // *
9828 // /|
9829 // / |
9830 // / *
9831 // * /|
9832 // | 0 |
9833 // |/ *
9834 // * /
9835 // | /
9836 // |/
9837 // *
9838 // face 1: right plane
9839 // *
9840 // /|
9841 // / |
9842 // / *
9843 // * /|
9844 // | 1 |
9845 // |/ *
9846 // * /
9847 // | /
9848 // |/
9849 // *
9850 // face 2: front plane
9851 // (note: x,y exchanged)
9852 // *---*---*
9853 // | 5 |
9854 // *-6-*-7-*
9855 // | 4 |
9856 // *---*---*
9857 // face 3: back plane
9858 // (note: x,y exchanged)
9859 // *---*---*
9860 // | 9 |
9861 // *10-*-11*
9862 // | 8 |
9863 // *---*---*
9864 // face 4: bottom plane
9865 // *---*---*
9866 // / / /
9867 // / 2 /
9868 // / / /
9869 // *---*---*
9870 // face 5: top plane
9871 // *---*---*
9872 // / / /
9873 // / 3 /
9874 // / / /
9875 // *---*---*
9876 // middle planes
9877 // *---*---* *-------*
9878 // / / / | |
9879 // / 12 / | |
9880 // / / / | |
9881 // *---*---* *-------*
9882
9883 // set up a list of line iterators first. from
9884 // this, construct lists of line_indices and
9885 // line orientations later on
9886 const typename Triangulation<
9887 dim,
9888 spacedim>::raw_line_iterator lines[13] = {
9889 hex->face(0)->child(0)->line(
9890 (hex->face(0)->refinement_case() ==
9892 1 :
9893 3), // 0
9894 hex->face(1)->child(0)->line(
9895 (hex->face(1)->refinement_case() ==
9897 1 :
9898 3), // 1
9899 hex->face(4)->child(0)->line(
9900 (hex->face(4)->refinement_case() ==
9902 1 :
9903 3), // 2
9904 hex->face(5)->child(0)->line(
9905 (hex->face(5)->refinement_case() ==
9907 1 :
9908 3), // 3
9909
9910 hex->face(2)
9911 ->isotropic_child(
9913 0, f_or[2], f_fl[2], f_ro[2]))
9914 ->line(
9916 3, f_or[2], f_fl[2], f_ro[2])), // 4
9917 hex->face(2)
9918 ->isotropic_child(
9920 3, f_or[2], f_fl[2], f_ro[2]))
9921 ->line(
9923 2, f_or[2], f_fl[2], f_ro[2])), // 5
9924 hex->face(2)
9925 ->isotropic_child(
9927 0, f_or[2], f_fl[2], f_ro[2]))
9928 ->line(
9930 1, f_or[2], f_fl[2], f_ro[2])), // 6
9931 hex->face(2)
9932 ->isotropic_child(
9934 3, f_or[2], f_fl[2], f_ro[2]))
9935 ->line(
9937 0, f_or[2], f_fl[2], f_ro[2])), // 7
9938
9939 hex->face(3)
9940 ->isotropic_child(
9942 0, f_or[3], f_fl[3], f_ro[3]))
9943 ->line(
9945 3, f_or[3], f_fl[3], f_ro[3])), // 8
9946 hex->face(3)
9947 ->isotropic_child(
9949 3, f_or[3], f_fl[3], f_ro[3]))
9950 ->line(
9952 2, f_or[3], f_fl[3], f_ro[3])), // 9
9953 hex->face(3)
9954 ->isotropic_child(
9956 0, f_or[3], f_fl[3], f_ro[3]))
9957 ->line(
9959 1, f_or[3], f_fl[3], f_ro[3])), // 10
9960 hex->face(3)
9961 ->isotropic_child(
9963 3, f_or[3], f_fl[3], f_ro[3]))
9964 ->line(
9966 0, f_or[3], f_fl[3], f_ro[3])), // 11
9967
9968 new_lines[0] // 12
9969 };
9970
9971 unsigned int line_indices[13];
9972 for (unsigned int i = 0; i < 13; ++i)
9973 line_indices[i] = lines[i]->index();
9974
9975 // the orientation of lines for the inner quads
9976 // is quite tricky. as these lines are newly
9977 // created ones and thus have no parents, they
9978 // cannot inherit this property. set up an array
9979 // and fill it with the respective values
9980 types::geometric_orientation line_orientation[13]{};
9981
9982 // the middle vertices of the
9983 // lines of our front face
9984 const unsigned int middle_vertices[4] = {
9985 hex->line(8)->child(0)->vertex_index(1),
9986 hex->line(9)->child(0)->vertex_index(1),
9987 hex->line(2)->child(0)->vertex_index(1),
9988 hex->line(6)->child(0)->vertex_index(1),
9989 };
9990
9991 // note: for lines 0 to 3 the orientation of the
9992 // line is 'true', if vertex 0 is on the front
9993 for (unsigned int i = 0; i < 4; ++i)
9994 if (lines[i]->vertex_index(0) == middle_vertices[i])
9995 line_orientation[i] =
9997 else
9998 {
9999 // it must be the other way round then
10000 Assert(lines[i]->vertex_index(1) ==
10001 middle_vertices[i],
10003 line_orientation[i] =
10005 }
10006
10007 // note: for lines 4 to 11 (inner lines of the
10008 // outer quads) the following holds: the second
10009 // vertex of the even lines in standard
10010 // orientation is the vertex in the middle of
10011 // the quad, whereas for odd lines the first
10012 // vertex is the same middle vertex.
10013 for (unsigned int i = 4; i < 12; ++i)
10014 if (lines[i]->vertex_index((i + 1) % 2) ==
10015 middle_vertex_index<dim, spacedim>(
10016 hex->face(1 + i / 4)))
10017 line_orientation[i] =
10019 else
10020 {
10021 // it must be the other way
10022 // round then
10023 Assert(lines[i]->vertex_index(i % 2) ==
10024 (middle_vertex_index<dim, spacedim>(
10025 hex->face(1 + i / 4))),
10027 line_orientation[i] =
10029 }
10030 // for the last line the line orientation is
10031 // always true, since it was just constructed
10032 // that way
10033 line_orientation[12] =
10035
10036 // set up the 4 quads, numbered as follows (left
10037 // quad numbering, right line numbering
10038 // extracted from above), the drawings denote
10039 // middle planes
10040 //
10041 // * *
10042 // /| /|
10043 // / | 3 9
10044 // y/ * / *
10045 // * 3/| * /|
10046 // | / |x 5 12|8
10047 // |/ * |/ *
10048 // * 2/ * /
10049 // | / 4 2
10050 // |/ |/
10051 // * *
10052 //
10053 // y
10054 // *----*----* *-10-*-11-*
10055 // / / / / / /
10056 // / 0 / 1 / 0 12 1
10057 // / / / / / /
10058 // *----*----*x *--6-*--7-*
10059
10060 new_quads[0]->set_bounding_object_indices(
10061 {line_indices[0],
10062 line_indices[12],
10063 line_indices[6],
10064 line_indices[10]});
10065 new_quads[1]->set_bounding_object_indices(
10066 {line_indices[12],
10067 line_indices[1],
10068 line_indices[7],
10069 line_indices[11]});
10070 new_quads[2]->set_bounding_object_indices(
10071 {line_indices[4],
10072 line_indices[8],
10073 line_indices[2],
10074 line_indices[12]});
10075 new_quads[3]->set_bounding_object_indices(
10076 {line_indices[5],
10077 line_indices[9],
10078 line_indices[12],
10079 line_indices[3]});
10080
10081 new_quads[0]->set_line_orientation(
10082 0, line_orientation[0]);
10083 new_quads[0]->set_line_orientation(
10084 2, line_orientation[6]);
10085 new_quads[0]->set_line_orientation(
10086 3, line_orientation[10]);
10087
10088 new_quads[1]->set_line_orientation(
10089 1, line_orientation[1]);
10090 new_quads[1]->set_line_orientation(
10091 2, line_orientation[7]);
10092 new_quads[1]->set_line_orientation(
10093 3, line_orientation[11]);
10094
10095 new_quads[2]->set_line_orientation(
10096 0, line_orientation[4]);
10097 new_quads[2]->set_line_orientation(
10098 1, line_orientation[8]);
10099 new_quads[2]->set_line_orientation(
10100 2, line_orientation[2]);
10101
10102 new_quads[3]->set_line_orientation(
10103 0, line_orientation[5]);
10104 new_quads[3]->set_line_orientation(
10105 1, line_orientation[9]);
10106 new_quads[3]->set_line_orientation(
10107 3, line_orientation[3]);
10108
10109 // the quads are numbered as follows:
10110 //
10111 // planes in the interior of the old hex:
10112 //
10113 // *
10114 // /|
10115 // / | x
10116 // /3 * *-------* *----*----*
10117 // * /| | | / / /
10118 // | / | | | / 0 / 1 /
10119 // |/ * | | / / /
10120 // * 2/ *-------*y *----*----*x
10121 // | /
10122 // |/
10123 // *
10124 //
10125 // children of the faces
10126 // of the old hex
10127 // *---*---* *---*---*
10128 // /|13 | 15| / / /|
10129 // / | | | /18 / 19/ |
10130 // / *---*---* / / / *
10131 // * 5/| | | *---*---* 7/|
10132 // | / |12 | 14| | 9 | 11| / |
10133 // |/4 *---*---* | | |/6 *
10134 // * / / / *---*---* /
10135 // | /16 / 17/ | | | /
10136 // |/ / / | 8 | 10|/
10137 // *---*---* *---*---*
10138 //
10139 // note that we have to take care of the
10140 // orientation of faces.
10141 const int quad_indices[20] = {
10142 new_quads[0]->index(), // 0
10143 new_quads[1]->index(),
10144 new_quads[2]->index(),
10145 new_quads[3]->index(),
10146
10147 hex->face(0)->child_index(
10148 child_at_origin[hex->face(0)->refinement_case() -
10149 1][f_fl[0]][f_ro[0]]), // 4
10150 hex->face(0)->child_index(
10151 1 -
10152 child_at_origin[hex->face(0)->refinement_case() -
10153 1][f_fl[0]][f_ro[0]]),
10154
10155 hex->face(1)->child_index(
10156 child_at_origin[hex->face(1)->refinement_case() -
10157 1][f_fl[1]][f_ro[1]]), // 6
10158 hex->face(1)->child_index(
10159 1 -
10160 child_at_origin[hex->face(1)->refinement_case() -
10161 1][f_fl[1]][f_ro[1]]),
10162
10163 hex->face(2)->isotropic_child_index(
10165 0, f_or[2], f_fl[2], f_ro[2])), // 8
10166 hex->face(2)->isotropic_child_index(
10168 1, f_or[2], f_fl[2], f_ro[2])),
10169 hex->face(2)->isotropic_child_index(
10171 2, f_or[2], f_fl[2], f_ro[2])),
10172 hex->face(2)->isotropic_child_index(
10174 3, f_or[2], f_fl[2], f_ro[2])),
10175
10176 hex->face(3)->isotropic_child_index(
10178 0, f_or[3], f_fl[3], f_ro[3])), // 12
10179 hex->face(3)->isotropic_child_index(
10181 1, f_or[3], f_fl[3], f_ro[3])),
10182 hex->face(3)->isotropic_child_index(
10184 2, f_or[3], f_fl[3], f_ro[3])),
10185 hex->face(3)->isotropic_child_index(
10187 3, f_or[3], f_fl[3], f_ro[3])),
10188
10189 hex->face(4)->child_index(
10190 child_at_origin[hex->face(4)->refinement_case() -
10191 1][f_fl[4]][f_ro[4]]), // 16
10192 hex->face(4)->child_index(
10193 1 -
10194 child_at_origin[hex->face(4)->refinement_case() -
10195 1][f_fl[4]][f_ro[4]]),
10196
10197 hex->face(5)->child_index(
10198 child_at_origin[hex->face(5)->refinement_case() -
10199 1][f_fl[5]][f_ro[5]]), // 18
10200 hex->face(5)->child_index(
10201 1 -
10202 child_at_origin[hex->face(5)->refinement_case() -
10203 1][f_fl[5]][f_ro[5]])};
10204
10205 // due to the exchange of x and y for the front
10206 // and back face, we order the children
10207 // according to
10208 //
10209 // *---*---*
10210 // | 1 | 3 |
10211 // *---*---*
10212 // | 0 | 2 |
10213 // *---*---*
10214 new_hexes[0]->set_bounding_object_indices(
10215 {quad_indices[4],
10216 quad_indices[2],
10217 quad_indices[8],
10218 quad_indices[12],
10219 quad_indices[16],
10220 quad_indices[0]});
10221 new_hexes[1]->set_bounding_object_indices(
10222 {quad_indices[5],
10223 quad_indices[3],
10224 quad_indices[9],
10225 quad_indices[13],
10226 quad_indices[0],
10227 quad_indices[18]});
10228 new_hexes[2]->set_bounding_object_indices(
10229 {quad_indices[2],
10230 quad_indices[6],
10231 quad_indices[10],
10232 quad_indices[14],
10233 quad_indices[17],
10234 quad_indices[1]});
10235 new_hexes[3]->set_bounding_object_indices(
10236 {quad_indices[3],
10237 quad_indices[7],
10238 quad_indices[11],
10239 quad_indices[15],
10240 quad_indices[1],
10241 quad_indices[19]});
10242 break;
10243 }
10244
10246 {
10247 //----------------------------
10248 //
10249 // RefinementCase<dim>::cut_yz
10250 //
10251 // the refined cube will look like this:
10252 //
10253 // *---------*
10254 // / /|
10255 // *---------* |
10256 // / /| |
10257 // *---------* |/|
10258 // | | * |
10259 // | |/| *
10260 // *---------* |/
10261 // | | *
10262 // | |/
10263 // *---------*
10264 //
10265
10266 // first, create the new
10267 // internal line
10268 new_lines[0]->set_bounding_object_indices(
10269
10270 {middle_vertex_index<dim, spacedim>(hex->face(0)),
10271 middle_vertex_index<dim, spacedim>(hex->face(1))});
10272
10273 // again, first collect some data about the
10274 // indices of the lines, with the following
10275 // numbering: (note that face 0 and 1 each are
10276 // shown twice for better readability)
10277
10278 // face 0: left plane
10279 // * *
10280 // /| /|
10281 // * | * |
10282 // /| * /| *
10283 // * 5/| * |7|
10284 // | * | | * |
10285 // |/| * |6| *
10286 // * 4/ * |/
10287 // | * | *
10288 // |/ |/
10289 // * *
10290 // face 1: right plane
10291 // * *
10292 // /| /|
10293 // * | * |
10294 // /| * /| *
10295 // * 9/| * |11
10296 // | * | | * |
10297 // |/| * |10 *
10298 // * 8/ * |/
10299 // | * | *
10300 // |/ |/
10301 // * *
10302 // face 2: front plane
10303 // (note: x,y exchanged)
10304 // *-------*
10305 // | |
10306 // *---0---*
10307 // | |
10308 // *-------*
10309 // face 3: back plane
10310 // (note: x,y exchanged)
10311 // *-------*
10312 // | |
10313 // *---1---*
10314 // | |
10315 // *-------*
10316 // face 4: bottom plane
10317 // *-------*
10318 // / /
10319 // *---2---*
10320 // / /
10321 // *-------*
10322 // face 5: top plane
10323 // *-------*
10324 // / /
10325 // *---3---*
10326 // / /
10327 // *-------*
10328 // middle planes
10329 // *-------* *-------*
10330 // / / | |
10331 // *---12--* | |
10332 // / / | |
10333 // *-------* *-------*
10334
10335 // set up a list of line iterators first. from
10336 // this, construct lists of line_indices and
10337 // line orientations later on
10338 const typename Triangulation<
10339 dim,
10340 spacedim>::raw_line_iterator lines[13] = {
10341 hex->face(2)->child(0)->line(
10342 (hex->face(2)->refinement_case() ==
10344 1 :
10345 3), // 0
10346 hex->face(3)->child(0)->line(
10347 (hex->face(3)->refinement_case() ==
10349 1 :
10350 3), // 1
10351 hex->face(4)->child(0)->line(
10352 (hex->face(4)->refinement_case() ==
10354 1 :
10355 3), // 2
10356 hex->face(5)->child(0)->line(
10357 (hex->face(5)->refinement_case() ==
10359 1 :
10360 3), // 3
10361
10362 hex->face(0)
10363 ->isotropic_child(
10365 0, f_or[0], f_fl[0], f_ro[0]))
10366 ->line(
10368 1, f_or[0], f_fl[0], f_ro[0])), // 4
10369 hex->face(0)
10370 ->isotropic_child(
10372 3, f_or[0], f_fl[0], f_ro[0]))
10373 ->line(
10375 0, f_or[0], f_fl[0], f_ro[0])), // 5
10376 hex->face(0)
10377 ->isotropic_child(
10379 0, f_or[0], f_fl[0], f_ro[0]))
10380 ->line(
10382 3, f_or[0], f_fl[0], f_ro[0])), // 6
10383 hex->face(0)
10384 ->isotropic_child(
10386 3, f_or[0], f_fl[0], f_ro[0]))
10387 ->line(
10389 2, f_or[0], f_fl[0], f_ro[0])), // 7
10390
10391 hex->face(1)
10392 ->isotropic_child(
10394 0, f_or[1], f_fl[1], f_ro[1]))
10395 ->line(
10397 1, f_or[1], f_fl[1], f_ro[1])), // 8
10398 hex->face(1)
10399 ->isotropic_child(
10401 3, f_or[1], f_fl[1], f_ro[1]))
10402 ->line(
10404 0, f_or[1], f_fl[1], f_ro[1])), // 9
10405 hex->face(1)
10406 ->isotropic_child(
10408 0, f_or[1], f_fl[1], f_ro[1]))
10409 ->line(
10411 3, f_or[1], f_fl[1], f_ro[1])), // 10
10412 hex->face(1)
10413 ->isotropic_child(
10415 3, f_or[1], f_fl[1], f_ro[1]))
10416 ->line(
10418 2, f_or[1], f_fl[1], f_ro[1])), // 11
10419
10420 new_lines[0] // 12
10421 };
10422
10423 unsigned int line_indices[13];
10424
10425 for (unsigned int i = 0; i < 13; ++i)
10426 line_indices[i] = lines[i]->index();
10427
10428 // the orientation of lines for the inner quads
10429 // is quite tricky. as these lines are newly
10430 // created ones and thus have no parents, they
10431 // cannot inherit this property. set up an array
10432 // and fill it with the respective values
10433 types::geometric_orientation line_orientation[13]{};
10434
10435 // the middle vertices of the lines of our front
10436 // face
10437 const unsigned int middle_vertices[4] = {
10438 hex->line(8)->child(0)->vertex_index(1),
10439 hex->line(10)->child(0)->vertex_index(1),
10440 hex->line(0)->child(0)->vertex_index(1),
10441 hex->line(4)->child(0)->vertex_index(1),
10442 };
10443
10444 // note: for lines 0 to 3 the orientation of the
10445 // line is 'true', if vertex 0 is on the front
10446 for (unsigned int i = 0; i < 4; ++i)
10447 if (lines[i]->vertex_index(0) == middle_vertices[i])
10448 line_orientation[i] =
10450 else
10451 {
10452 // it must be the other way round then
10453 Assert(lines[i]->vertex_index(1) ==
10454 middle_vertices[i],
10456 line_orientation[i] =
10458 }
10459
10460 // note: for lines 4 to 11 (inner lines of the
10461 // outer quads) the following holds: the second
10462 // vertex of the even lines in standard
10463 // orientation is the vertex in the middle of
10464 // the quad, whereas for odd lines the first
10465 // vertex is the same middle vertex.
10466 for (unsigned int i = 4; i < 12; ++i)
10467 if (lines[i]->vertex_index((i + 1) % 2) ==
10468 middle_vertex_index<dim, spacedim>(
10469 hex->face(i / 4 - 1)))
10470 line_orientation[i] =
10472 else
10473 {
10474 // it must be the other way round then
10475 Assert(lines[i]->vertex_index(i % 2) ==
10476 (middle_vertex_index<dim, spacedim>(
10477 hex->face(i / 4 - 1))),
10479 line_orientation[i] =
10481 }
10482 // for the last line the line orientation is always
10483 // the default, since it was just constructed that way
10484 line_orientation[12] =
10486
10487 // set up the 4 quads, numbered as follows (left
10488 // quad numbering, right line numbering
10489 // extracted from above)
10490 //
10491 // x
10492 // *-------* *---3---*
10493 // | 3 | 5 9
10494 // *-------* *---12--*
10495 // | 2 | 4 8
10496 // *-------*y *---2---*
10497 //
10498 // y
10499 // *---------* *----1----*
10500 // / 1 / 7 11
10501 // *---------* *----12---*
10502 // / 0 / 6 10
10503 // *---------*x *----0----*
10504
10505 new_quads[0]->set_bounding_object_indices(
10506 {line_indices[6],
10507 line_indices[10],
10508 line_indices[0],
10509 line_indices[12]});
10510 new_quads[1]->set_bounding_object_indices(
10511 {line_indices[7],
10512 line_indices[11],
10513 line_indices[12],
10514 line_indices[1]});
10515 new_quads[2]->set_bounding_object_indices(
10516 {line_indices[2],
10517 line_indices[12],
10518 line_indices[4],
10519 line_indices[8]});
10520 new_quads[3]->set_bounding_object_indices(
10521 {line_indices[12],
10522 line_indices[3],
10523 line_indices[5],
10524 line_indices[9]});
10525
10526 new_quads[0]->set_line_orientation(
10527 0, line_orientation[6]);
10528 new_quads[0]->set_line_orientation(
10529 1, line_orientation[10]);
10530 new_quads[0]->set_line_orientation(
10531 2, line_orientation[0]);
10532
10533 new_quads[1]->set_line_orientation(
10534 0, line_orientation[7]);
10535 new_quads[1]->set_line_orientation(
10536 1, line_orientation[11]);
10537 new_quads[1]->set_line_orientation(
10538 3, line_orientation[1]);
10539
10540 new_quads[2]->set_line_orientation(
10541 0, line_orientation[2]);
10542 new_quads[2]->set_line_orientation(
10543 2, line_orientation[4]);
10544 new_quads[2]->set_line_orientation(
10545 3, line_orientation[8]);
10546
10547 new_quads[3]->set_line_orientation(
10548 1, line_orientation[3]);
10549 new_quads[3]->set_line_orientation(
10550 2, line_orientation[5]);
10551 new_quads[3]->set_line_orientation(
10552 3, line_orientation[9]);
10553
10554 // the quads are numbered as follows:
10555 //
10556 // planes in the interior of the old hex:
10557 //
10558 // *
10559 // /|
10560 // / | x
10561 // / | *-------* *---------*
10562 // * | | 3 | / 1 /
10563 // | | *-------* *---------*
10564 // | * | 2 | / 0 /
10565 // | / *-------*y *---------*x
10566 // | /
10567 // |/
10568 // *
10569 //
10570 // children of the faces
10571 // of the old hex
10572 // *-------* *-------*
10573 // /| | / 19 /|
10574 // * | 15 | *-------* |
10575 // /|7*-------* / 18 /|11
10576 // * |/| | *-------* |/|
10577 // |6* | 14 | | 10* |
10578 // |/|5*-------* | 13 |/|9*
10579 // * |/ 17 / *-------* |/
10580 // |4*-------* | |8*
10581 // |/ 16 / | 12 |/
10582 // *-------* *-------*
10583 //
10584 // note that we have to take care of the
10585 // orientation of faces.
10586 const int quad_indices[20] = {
10587 new_quads[0]->index(), // 0
10588 new_quads[1]->index(),
10589 new_quads[2]->index(),
10590 new_quads[3]->index(),
10591
10592 hex->face(0)->isotropic_child_index(
10594 0, f_or[0], f_fl[0], f_ro[0])), // 4
10595 hex->face(0)->isotropic_child_index(
10597 1, f_or[0], f_fl[0], f_ro[0])),
10598 hex->face(0)->isotropic_child_index(
10600 2, f_or[0], f_fl[0], f_ro[0])),
10601 hex->face(0)->isotropic_child_index(
10603 3, f_or[0], f_fl[0], f_ro[0])),
10604
10605 hex->face(1)->isotropic_child_index(
10607 0, f_or[1], f_fl[1], f_ro[1])), // 8
10608 hex->face(1)->isotropic_child_index(
10610 1, f_or[1], f_fl[1], f_ro[1])),
10611 hex->face(1)->isotropic_child_index(
10613 2, f_or[1], f_fl[1], f_ro[1])),
10614 hex->face(1)->isotropic_child_index(
10616 3, f_or[1], f_fl[1], f_ro[1])),
10617
10618 hex->face(2)->child_index(
10619 child_at_origin[hex->face(2)->refinement_case() -
10620 1][f_fl[2]][f_ro[2]]), // 12
10621 hex->face(2)->child_index(
10622 1 -
10623 child_at_origin[hex->face(2)->refinement_case() -
10624 1][f_fl[2]][f_ro[2]]),
10625
10626 hex->face(3)->child_index(
10627 child_at_origin[hex->face(3)->refinement_case() -
10628 1][f_fl[3]][f_ro[3]]), // 14
10629 hex->face(3)->child_index(
10630 1 -
10631 child_at_origin[hex->face(3)->refinement_case() -
10632 1][f_fl[3]][f_ro[3]]),
10633
10634 hex->face(4)->child_index(
10635 child_at_origin[hex->face(4)->refinement_case() -
10636 1][f_fl[4]][f_ro[4]]), // 16
10637 hex->face(4)->child_index(
10638 1 -
10639 child_at_origin[hex->face(4)->refinement_case() -
10640 1][f_fl[4]][f_ro[4]]),
10641
10642 hex->face(5)->child_index(
10643 child_at_origin[hex->face(5)->refinement_case() -
10644 1][f_fl[5]][f_ro[5]]), // 18
10645 hex->face(5)->child_index(
10646 1 -
10647 child_at_origin[hex->face(5)->refinement_case() -
10648 1][f_fl[5]][f_ro[5]])};
10649
10650 new_hexes[0]->set_bounding_object_indices(
10651 {quad_indices[4],
10652 quad_indices[8],
10653 quad_indices[12],
10654 quad_indices[2],
10655 quad_indices[16],
10656 quad_indices[0]});
10657 new_hexes[1]->set_bounding_object_indices(
10658 {quad_indices[5],
10659 quad_indices[9],
10660 quad_indices[2],
10661 quad_indices[14],
10662 quad_indices[17],
10663 quad_indices[1]});
10664 new_hexes[2]->set_bounding_object_indices(
10665 {quad_indices[6],
10666 quad_indices[10],
10667 quad_indices[13],
10668 quad_indices[3],
10669 quad_indices[0],
10670 quad_indices[18]});
10671 new_hexes[3]->set_bounding_object_indices(
10672 {quad_indices[7],
10673 quad_indices[11],
10674 quad_indices[3],
10675 quad_indices[15],
10676 quad_indices[1],
10677 quad_indices[19]});
10678 break;
10679 }
10680
10682 {
10683 //----------------------------
10684 //
10685 // RefinementCase<dim>::cut_xyz
10686 // isotropic refinement
10687 //
10688 // the refined cube will look
10689 // like this:
10690 //
10691 // *----*----*
10692 // / / /|
10693 // *----*----* |
10694 // / / /| *
10695 // *----*----* |/|
10696 // | | | * |
10697 // | | |/| *
10698 // *----*----* |/
10699 // | | | *
10700 // | | |/
10701 // *----*----*
10702 //
10703
10704 // find the next unused vertex and set it
10705 // appropriately
10706 while (
10707 triangulation.vertices_used[next_unused_vertex] ==
10708 true)
10709 ++next_unused_vertex;
10710 Assert(
10711 next_unused_vertex < triangulation.vertices.size(),
10712 ExcMessage(
10713 "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."));
10714 triangulation.vertices_used[next_unused_vertex] =
10715 true;
10716
10717 // the new vertex is definitely in the interior,
10718 // so we need not worry about the
10719 // boundary. However we need to worry about
10720 // Manifolds. Let the cell compute its own
10721 // center, by querying the underlying manifold
10722 // object.
10723 triangulation.vertices[next_unused_vertex] =
10724 hex->center(true, true);
10725
10726 // set the data of the six lines. first collect
10727 // the indices of the seven vertices (consider
10728 // the two planes to be crossed to form the
10729 // planes cutting the hex in two vertically and
10730 // horizontally)
10731 //
10732 // *--3--* *--5--*
10733 // / / / | | |
10734 // 0--6--1 0--6--1
10735 // / / / | | |
10736 // *--2--* *--4--*
10737 // the lines are numbered
10738 // as follows:
10739 // *--*--* *--*--*
10740 // / 1 / | 5 |
10741 // *2-*-3* *2-*-3*
10742 // / 0 / | 4 |
10743 // *--*--* *--*--*
10744 //
10745 const unsigned int vertex_indices[7] = {
10746 middle_vertex_index<dim, spacedim>(hex->face(0)),
10747 middle_vertex_index<dim, spacedim>(hex->face(1)),
10748 middle_vertex_index<dim, spacedim>(hex->face(2)),
10749 middle_vertex_index<dim, spacedim>(hex->face(3)),
10750 middle_vertex_index<dim, spacedim>(hex->face(4)),
10751 middle_vertex_index<dim, spacedim>(hex->face(5)),
10752 next_unused_vertex};
10753
10754 new_lines[0]->set_bounding_object_indices(
10756 new_lines[1]->set_bounding_object_indices(
10758 new_lines[2]->set_bounding_object_indices(
10760 new_lines[3]->set_bounding_object_indices(
10762 new_lines[4]->set_bounding_object_indices(
10764 new_lines[5]->set_bounding_object_indices(
10766
10767 // again, first collect some data about the
10768 // indices of the lines, with the following
10769 // numbering: (note that face 0 and 1 each are
10770 // shown twice for better readability)
10771
10772 // face 0: left plane
10773 // * *
10774 // /| /|
10775 // * | * |
10776 // /| * /| *
10777 // * 1/| * |3|
10778 // | * | | * |
10779 // |/| * |2| *
10780 // * 0/ * |/
10781 // | * | *
10782 // |/ |/
10783 // * *
10784 // face 1: right plane
10785 // * *
10786 // /| /|
10787 // * | * |
10788 // /| * /| *
10789 // * 5/| * |7|
10790 // | * | | * |
10791 // |/| * |6| *
10792 // * 4/ * |/
10793 // | * | *
10794 // |/ |/
10795 // * *
10796 // face 2: front plane
10797 // (note: x,y exchanged)
10798 // *---*---*
10799 // | 11 |
10800 // *-8-*-9-*
10801 // | 10 |
10802 // *---*---*
10803 // face 3: back plane
10804 // (note: x,y exchanged)
10805 // *---*---*
10806 // | 15 |
10807 // *12-*-13*
10808 // | 14 |
10809 // *---*---*
10810 // face 4: bottom plane
10811 // *---*---*
10812 // / 17 /
10813 // *18-*-19*
10814 // / 16 /
10815 // *---*---*
10816 // face 5: top plane
10817 // *---*---*
10818 // / 21 /
10819 // *22-*-23*
10820 // / 20 /
10821 // *---*---*
10822 // middle planes
10823 // *---*---* *---*---*
10824 // / 25 / | 29 |
10825 // *26-*-27* *26-*-27*
10826 // / 24 / | 28 |
10827 // *---*---* *---*---*
10828
10829 // set up a list of line iterators first. from
10830 // this, construct lists of line_indices and
10831 // line orientations later on
10832 const typename Triangulation<
10833 dim,
10834 spacedim>::raw_line_iterator lines[30] = {
10835 hex->face(0)
10836 ->isotropic_child(
10838 0, f_or[0], f_fl[0], f_ro[0]))
10839 ->line(
10841 1, f_or[0], f_fl[0], f_ro[0])), // 0
10842 hex->face(0)
10843 ->isotropic_child(
10845 3, f_or[0], f_fl[0], f_ro[0]))
10846 ->line(
10848 0, f_or[0], f_fl[0], f_ro[0])), // 1
10849 hex->face(0)
10850 ->isotropic_child(
10852 0, f_or[0], f_fl[0], f_ro[0]))
10853 ->line(
10855 3, f_or[0], f_fl[0], f_ro[0])), // 2
10856 hex->face(0)
10857 ->isotropic_child(
10859 3, f_or[0], f_fl[0], f_ro[0]))
10860 ->line(
10862 2, f_or[0], f_fl[0], f_ro[0])), // 3
10863
10864 hex->face(1)
10865 ->isotropic_child(
10867 0, f_or[1], f_fl[1], f_ro[1]))
10868 ->line(
10870 1, f_or[1], f_fl[1], f_ro[1])), // 4
10871 hex->face(1)
10872 ->isotropic_child(
10874 3, f_or[1], f_fl[1], f_ro[1]))
10875 ->line(
10877 0, f_or[1], f_fl[1], f_ro[1])), // 5
10878 hex->face(1)
10879 ->isotropic_child(
10881 0, f_or[1], f_fl[1], f_ro[1]))
10882 ->line(
10884 3, f_or[1], f_fl[1], f_ro[1])), // 6
10885 hex->face(1)
10886 ->isotropic_child(
10888 3, f_or[1], f_fl[1], f_ro[1]))
10889 ->line(
10891 2, f_or[1], f_fl[1], f_ro[1])), // 7
10892
10893 hex->face(2)
10894 ->isotropic_child(
10896 0, f_or[2], f_fl[2], f_ro[2]))
10897 ->line(
10899 1, f_or[2], f_fl[2], f_ro[2])), // 8
10900 hex->face(2)
10901 ->isotropic_child(
10903 3, f_or[2], f_fl[2], f_ro[2]))
10904 ->line(
10906 0, f_or[2], f_fl[2], f_ro[2])), // 9
10907 hex->face(2)
10908 ->isotropic_child(
10910 0, f_or[2], f_fl[2], f_ro[2]))
10911 ->line(
10913 3, f_or[2], f_fl[2], f_ro[2])), // 10
10914 hex->face(2)
10915 ->isotropic_child(
10917 3, f_or[2], f_fl[2], f_ro[2]))
10918 ->line(
10920 2, f_or[2], f_fl[2], f_ro[2])), // 11
10921
10922 hex->face(3)
10923 ->isotropic_child(
10925 0, f_or[3], f_fl[3], f_ro[3]))
10926 ->line(
10928 1, f_or[3], f_fl[3], f_ro[3])), // 12
10929 hex->face(3)
10930 ->isotropic_child(
10932 3, f_or[3], f_fl[3], f_ro[3]))
10933 ->line(
10935 0, f_or[3], f_fl[3], f_ro[3])), // 13
10936 hex->face(3)
10937 ->isotropic_child(
10939 0, f_or[3], f_fl[3], f_ro[3]))
10940 ->line(
10942 3, f_or[3], f_fl[3], f_ro[3])), // 14
10943 hex->face(3)
10944 ->isotropic_child(
10946 3, f_or[3], f_fl[3], f_ro[3]))
10947 ->line(
10949 2, f_or[3], f_fl[3], f_ro[3])), // 15
10950
10951 hex->face(4)
10952 ->isotropic_child(
10954 0, f_or[4], f_fl[4], f_ro[4]))
10955 ->line(
10957 1, f_or[4], f_fl[4], f_ro[4])), // 16
10958 hex->face(4)
10959 ->isotropic_child(
10961 3, f_or[4], f_fl[4], f_ro[4]))
10962 ->line(
10964 0, f_or[4], f_fl[4], f_ro[4])), // 17
10965 hex->face(4)
10966 ->isotropic_child(
10968 0, f_or[4], f_fl[4], f_ro[4]))
10969 ->line(
10971 3, f_or[4], f_fl[4], f_ro[4])), // 18
10972 hex->face(4)
10973 ->isotropic_child(
10975 3, f_or[4], f_fl[4], f_ro[4]))
10976 ->line(
10978 2, f_or[4], f_fl[4], f_ro[4])), // 19
10979
10980 hex->face(5)
10981 ->isotropic_child(
10983 0, f_or[5], f_fl[5], f_ro[5]))
10984 ->line(
10986 1, f_or[5], f_fl[5], f_ro[5])), // 20
10987 hex->face(5)
10988 ->isotropic_child(
10990 3, f_or[5], f_fl[5], f_ro[5]))
10991 ->line(
10993 0, f_or[5], f_fl[5], f_ro[5])), // 21
10994 hex->face(5)
10995 ->isotropic_child(
10997 0, f_or[5], f_fl[5], f_ro[5]))
10998 ->line(
11000 3, f_or[5], f_fl[5], f_ro[5])), // 22
11001 hex->face(5)
11002 ->isotropic_child(
11004 3, f_or[5], f_fl[5], f_ro[5]))
11005 ->line(
11007 2, f_or[5], f_fl[5], f_ro[5])), // 23
11008
11009 new_lines[0], // 24
11010 new_lines[1], // 25
11011 new_lines[2], // 26
11012 new_lines[3], // 27
11013 new_lines[4], // 28
11014 new_lines[5] // 29
11015 };
11016
11017 unsigned int line_indices[30];
11018 for (unsigned int i = 0; i < 30; ++i)
11019 line_indices[i] = lines[i]->index();
11020
11021 // the orientation of lines for the inner quads
11022 // is quite tricky. as these lines are newly
11023 // created ones and thus have no parents, they
11024 // cannot inherit this property. set up an array
11025 // and fill it with the respective values
11026 types::geometric_orientation line_orientation[30]{};
11027
11028 // note: for the first 24 lines (inner lines of
11029 // the outer quads) the following holds: the
11030 // second vertex of the even lines in standard
11031 // orientation is the vertex in the middle of
11032 // the quad, whereas for odd lines the first
11033 // vertex is the same middle vertex.
11034 for (unsigned int i = 0; i < 24; ++i)
11035 if (lines[i]->vertex_index((i + 1) % 2) ==
11036 vertex_indices[i / 4])
11037 line_orientation[i] =
11039 else
11040 {
11041 // it must be the other way
11042 // round then
11043 Assert(lines[i]->vertex_index(i % 2) ==
11044 vertex_indices[i / 4],
11046 line_orientation[i] =
11048 }
11049 // for the last 6 lines the line orientation is
11050 // always true, since they were just constructed
11051 // that way
11052 for (unsigned int i = 24; i < 30; ++i)
11053 line_orientation[i] =
11055
11056 // set up the 12 quads, numbered as follows
11057 // (left quad numbering, right line numbering
11058 // extracted from above)
11059 //
11060 // * *
11061 // /| 21|
11062 // * | * 15
11063 // y/|3* 20| *
11064 // * |/| * |/|
11065 // |2* |x 11 * 14
11066 // |/|1* |/| *
11067 // * |/ * |17
11068 // |0* 10 *
11069 // |/ |16
11070 // * *
11071 //
11072 // x
11073 // *---*---* *22-*-23*
11074 // | 5 | 7 | 1 29 5
11075 // *---*---* *26-*-27*
11076 // | 4 | 6 | 0 28 4
11077 // *---*---*y *18-*-19*
11078 //
11079 // y
11080 // *----*----* *-12-*-13-*
11081 // / 10 / 11 / 3 25 7
11082 // *----*----* *-26-*-27-*
11083 // / 8 / 9 / 2 24 6
11084 // *----*----*x *--8-*--9-*
11085
11086 new_quads[0]->set_bounding_object_indices(
11087 {line_indices[10],
11088 line_indices[28],
11089 line_indices[16],
11090 line_indices[24]});
11091 new_quads[1]->set_bounding_object_indices(
11092 {line_indices[28],
11093 line_indices[14],
11094 line_indices[17],
11095 line_indices[25]});
11096 new_quads[2]->set_bounding_object_indices(
11097 {line_indices[11],
11098 line_indices[29],
11099 line_indices[24],
11100 line_indices[20]});
11101 new_quads[3]->set_bounding_object_indices(
11102 {line_indices[29],
11103 line_indices[15],
11104 line_indices[25],
11105 line_indices[21]});
11106 new_quads[4]->set_bounding_object_indices(
11107 {line_indices[18],
11108 line_indices[26],
11109 line_indices[0],
11110 line_indices[28]});
11111 new_quads[5]->set_bounding_object_indices(
11112 {line_indices[26],
11113 line_indices[22],
11114 line_indices[1],
11115 line_indices[29]});
11116 new_quads[6]->set_bounding_object_indices(
11117 {line_indices[19],
11118 line_indices[27],
11119 line_indices[28],
11120 line_indices[4]});
11121 new_quads[7]->set_bounding_object_indices(
11122 {line_indices[27],
11123 line_indices[23],
11124 line_indices[29],
11125 line_indices[5]});
11126 new_quads[8]->set_bounding_object_indices(
11127 {line_indices[2],
11128 line_indices[24],
11129 line_indices[8],
11130 line_indices[26]});
11131 new_quads[9]->set_bounding_object_indices(
11132 {line_indices[24],
11133 line_indices[6],
11134 line_indices[9],
11135 line_indices[27]});
11136 new_quads[10]->set_bounding_object_indices(
11137 {line_indices[3],
11138 line_indices[25],
11139 line_indices[26],
11140 line_indices[12]});
11141 new_quads[11]->set_bounding_object_indices(
11142 {line_indices[25],
11143 line_indices[7],
11144 line_indices[27],
11145 line_indices[13]});
11146
11147 // now reset the line_orientation flags of outer
11148 // lines as they cannot be set in a loop (at
11149 // least not easily)
11150 new_quads[0]->set_line_orientation(
11151 0, line_orientation[10]);
11152 new_quads[0]->set_line_orientation(
11153 2, line_orientation[16]);
11154
11155 new_quads[1]->set_line_orientation(
11156 1, line_orientation[14]);
11157 new_quads[1]->set_line_orientation(
11158 2, line_orientation[17]);
11159
11160 new_quads[2]->set_line_orientation(
11161 0, line_orientation[11]);
11162 new_quads[2]->set_line_orientation(
11163 3, line_orientation[20]);
11164
11165 new_quads[3]->set_line_orientation(
11166 1, line_orientation[15]);
11167 new_quads[3]->set_line_orientation(
11168 3, line_orientation[21]);
11169
11170 new_quads[4]->set_line_orientation(
11171 0, line_orientation[18]);
11172 new_quads[4]->set_line_orientation(
11173 2, line_orientation[0]);
11174
11175 new_quads[5]->set_line_orientation(
11176 1, line_orientation[22]);
11177 new_quads[5]->set_line_orientation(
11178 2, line_orientation[1]);
11179
11180 new_quads[6]->set_line_orientation(
11181 0, line_orientation[19]);
11182 new_quads[6]->set_line_orientation(
11183 3, line_orientation[4]);
11184
11185 new_quads[7]->set_line_orientation(
11186 1, line_orientation[23]);
11187 new_quads[7]->set_line_orientation(
11188 3, line_orientation[5]);
11189
11190 new_quads[8]->set_line_orientation(
11191 0, line_orientation[2]);
11192 new_quads[8]->set_line_orientation(
11193 2, line_orientation[8]);
11194
11195 new_quads[9]->set_line_orientation(
11196 1, line_orientation[6]);
11197 new_quads[9]->set_line_orientation(
11198 2, line_orientation[9]);
11199
11200 new_quads[10]->set_line_orientation(
11201 0, line_orientation[3]);
11202 new_quads[10]->set_line_orientation(
11203 3, line_orientation[12]);
11204
11205 new_quads[11]->set_line_orientation(
11206 1, line_orientation[7]);
11207 new_quads[11]->set_line_orientation(
11208 3, line_orientation[13]);
11209
11210 //-------------------------------
11211 // create the eight new hexes
11212 //
11213 // again first collect some data. here, we need
11214 // the indices of a whole lotta quads.
11215
11216 // the quads are numbered as follows:
11217 //
11218 // planes in the interior of the old hex:
11219 //
11220 // *
11221 // /|
11222 // * |
11223 // /|3* *---*---* *----*----*
11224 // * |/| | 5 | 7 | / 10 / 11 /
11225 // |2* | *---*---* *----*----*
11226 // |/|1* | 4 | 6 | / 8 / 9 /
11227 // * |/ *---*---*y *----*----*x
11228 // |0*
11229 // |/
11230 // *
11231 //
11232 // children of the faces
11233 // of the old hex
11234 // *-------* *-------*
11235 // /|25 27| /34 35/|
11236 // 15| | / /19
11237 // / | | /32 33/ |
11238 // * |24 26| *-------*18 |
11239 // 1413*-------* |21 23| 17*
11240 // | /30 31/ | | /
11241 // 12/ / | |16
11242 // |/28 29/ |20 22|/
11243 // *-------* *-------*
11244 //
11245 // note that we have to
11246 // take care of the
11247 // orientation of
11248 // faces.
11249 const int quad_indices[36] = {
11250 new_quads[0]->index(), // 0
11251 new_quads[1]->index(),
11252 new_quads[2]->index(),
11253 new_quads[3]->index(),
11254 new_quads[4]->index(),
11255 new_quads[5]->index(),
11256 new_quads[6]->index(),
11257 new_quads[7]->index(),
11258 new_quads[8]->index(),
11259 new_quads[9]->index(),
11260 new_quads[10]->index(),
11261 new_quads[11]->index(), // 11
11262
11263 hex->face(0)->isotropic_child_index(
11265 0, f_or[0], f_fl[0], f_ro[0])), // 12
11266 hex->face(0)->isotropic_child_index(
11268 1, f_or[0], f_fl[0], f_ro[0])),
11269 hex->face(0)->isotropic_child_index(
11271 2, f_or[0], f_fl[0], f_ro[0])),
11272 hex->face(0)->isotropic_child_index(
11274 3, f_or[0], f_fl[0], f_ro[0])),
11275
11276 hex->face(1)->isotropic_child_index(
11278 0, f_or[1], f_fl[1], f_ro[1])), // 16
11279 hex->face(1)->isotropic_child_index(
11281 1, f_or[1], f_fl[1], f_ro[1])),
11282 hex->face(1)->isotropic_child_index(
11284 2, f_or[1], f_fl[1], f_ro[1])),
11285 hex->face(1)->isotropic_child_index(
11287 3, f_or[1], f_fl[1], f_ro[1])),
11288
11289 hex->face(2)->isotropic_child_index(
11291 0, f_or[2], f_fl[2], f_ro[2])), // 20
11292 hex->face(2)->isotropic_child_index(
11294 1, f_or[2], f_fl[2], f_ro[2])),
11295 hex->face(2)->isotropic_child_index(
11297 2, f_or[2], f_fl[2], f_ro[2])),
11298 hex->face(2)->isotropic_child_index(
11300 3, f_or[2], f_fl[2], f_ro[2])),
11301
11302 hex->face(3)->isotropic_child_index(
11304 0, f_or[3], f_fl[3], f_ro[3])), // 24
11305 hex->face(3)->isotropic_child_index(
11307 1, f_or[3], f_fl[3], f_ro[3])),
11308 hex->face(3)->isotropic_child_index(
11310 2, f_or[3], f_fl[3], f_ro[3])),
11311 hex->face(3)->isotropic_child_index(
11313 3, f_or[3], f_fl[3], f_ro[3])),
11314
11315 hex->face(4)->isotropic_child_index(
11317 0, f_or[4], f_fl[4], f_ro[4])), // 28
11318 hex->face(4)->isotropic_child_index(
11320 1, f_or[4], f_fl[4], f_ro[4])),
11321 hex->face(4)->isotropic_child_index(
11323 2, f_or[4], f_fl[4], f_ro[4])),
11324 hex->face(4)->isotropic_child_index(
11326 3, f_or[4], f_fl[4], f_ro[4])),
11327
11328 hex->face(5)->isotropic_child_index(
11330 0, f_or[5], f_fl[5], f_ro[5])), // 32
11331 hex->face(5)->isotropic_child_index(
11333 1, f_or[5], f_fl[5], f_ro[5])),
11334 hex->face(5)->isotropic_child_index(
11336 2, f_or[5], f_fl[5], f_ro[5])),
11337 hex->face(5)->isotropic_child_index(
11339 3, f_or[5], f_fl[5], f_ro[5]))};
11340
11341 // bottom children
11342 new_hexes[0]->set_bounding_object_indices(
11343 {quad_indices[12],
11344 quad_indices[0],
11345 quad_indices[20],
11346 quad_indices[4],
11347 quad_indices[28],
11348 quad_indices[8]});
11349 new_hexes[1]->set_bounding_object_indices(
11350 {quad_indices[0],
11351 quad_indices[16],
11352 quad_indices[22],
11353 quad_indices[6],
11354 quad_indices[29],
11355 quad_indices[9]});
11356 new_hexes[2]->set_bounding_object_indices(
11357 {quad_indices[13],
11358 quad_indices[1],
11359 quad_indices[4],
11360 quad_indices[24],
11361 quad_indices[30],
11362 quad_indices[10]});
11363 new_hexes[3]->set_bounding_object_indices(
11364 {quad_indices[1],
11365 quad_indices[17],
11366 quad_indices[6],
11367 quad_indices[26],
11368 quad_indices[31],
11369 quad_indices[11]});
11370
11371 // top children
11372 new_hexes[4]->set_bounding_object_indices(
11373 {quad_indices[14],
11374 quad_indices[2],
11375 quad_indices[21],
11376 quad_indices[5],
11377 quad_indices[8],
11378 quad_indices[32]});
11379 new_hexes[5]->set_bounding_object_indices(
11380 {quad_indices[2],
11381 quad_indices[18],
11382 quad_indices[23],
11383 quad_indices[7],
11384 quad_indices[9],
11385 quad_indices[33]});
11386 new_hexes[6]->set_bounding_object_indices(
11387 {quad_indices[15],
11388 quad_indices[3],
11389 quad_indices[5],
11390 quad_indices[25],
11391 quad_indices[10],
11392 quad_indices[34]});
11393 new_hexes[7]->set_bounding_object_indices(
11394 {quad_indices[3],
11395 quad_indices[19],
11396 quad_indices[7],
11397 quad_indices[27],
11398 quad_indices[11],
11399 quad_indices[35]});
11400 break;
11401 }
11402 default:
11403 // all refinement cases have been treated, there
11404 // only remains
11405 // RefinementCase<dim>::no_refinement as
11406 // untreated enumeration value. However, in that
11407 // case we should have aborted much
11408 // earlier. thus we should never get here
11410 break;
11411 } // switch (ref_case)
11412
11413 // and set face orientation flags. note that new
11414 // faces in the interior of the mother cell always
11415 // have a correctly oriented face, but the ones on
11416 // the outer faces will inherit this flag
11417 //
11418 // the flag have been set to true for all faces
11419 // initially, now go the other way round and reset
11420 // faces that are at the boundary of the mother cube
11421 //
11422 // the same is true for the face_flip and
11423 // face_rotation flags. however, the latter two are
11424 // set to false by default as this is the standard
11425 // value
11426
11427 // loop over all faces and all (relevant) subfaces
11428 // of that in order to set the correct values for
11429 // face_orientation, face_flip and face_rotation,
11430 // which are inherited from the corresponding face
11431 // of the mother cube
11432 for (const unsigned int f : GeometryInfo<dim>::face_indices())
11433 for (unsigned int s = 0;
11436 ref_case, f)),
11437 1U);
11438 ++s)
11439 {
11440 const unsigned int current_child =
11442 ref_case,
11443 f,
11444 s,
11445 f_or[f],
11446 f_fl[f],
11447 f_ro[f],
11449 ref_case, f, f_or[f], f_fl[f], f_ro[f]));
11450 new_hexes[current_child]->set_combined_face_orientation(
11451 f, f_co[f]);
11452 }
11453
11454 // now see if we have created cells that are
11455 // distorted and if so add them to our list
11456 if (check_for_distorted_cells &&
11457 has_distorted_children<dim, spacedim>(hex))
11458 cells_with_distorted_children.distorted_cells.push_back(
11459 hex);
11460
11461 // note that the refinement flag was already cleared
11462 // at the beginning of this loop
11463
11464 // inform all listeners that cell refinement is done
11465 triangulation.signals.post_refinement_on_cell(hex);
11466 }
11467 }
11468
11469 // clear user data on quads. we used some of this data to
11470 // indicate anisotropic refinemnt cases on faces. all data
11471 // should be cleared by now, but the information whether we
11472 // used indices or pointers is still present. reset it now to
11473 // enable the user to use whichever they like later on.
11474 triangulation.faces->quads.clear_user_data();
11475
11476 // return the list with distorted children
11477 return cells_with_distorted_children;
11478 }
11479
11480
11493 template <int spacedim>
11494 static void
11497
11498
11499
11500 template <int dim, int spacedim>
11501 static void
11504 {
11505 // If the codimension is one, we cannot perform this check
11506 // yet.
11507 if (spacedim > dim)
11508 return;
11509
11510 for (const auto &cell : triangulation.cell_iterators())
11511 if (cell->at_boundary() && cell->refine_flag_set() &&
11512 cell->refine_flag_set() !=
11514 {
11515 // The cell is at the boundary and it is flagged for
11516 // anisotropic refinement. Therefore, we have a closer
11517 // look
11518 const RefinementCase<dim> ref_case = cell->refine_flag_set();
11519 for (const unsigned int face_no :
11521 if (cell->face(face_no)->at_boundary())
11522 {
11523 // this is the critical face at the boundary.
11525 face_no) !=
11527 {
11528 // up to now, we do not want to refine this
11529 // cell along the face under consideration
11530 // here.
11531 const typename Triangulation<dim,
11532 spacedim>::face_iterator
11533 face = cell->face(face_no);
11534 // the new point on the boundary would be this
11535 // one.
11536 const Point<spacedim> new_bound = face->center(true);
11537 // to check it, transform to the unit cell
11538 // with a linear mapping
11539 const Point<dim> new_unit =
11540 cell->reference_cell()
11541 .template get_default_linear_mapping<dim,
11542 spacedim>()
11543 .transform_real_to_unit_cell(cell, new_bound);
11544
11545 // Now, we have to calculate the distance from
11546 // the face in the unit cell.
11547
11548 // take the correct coordinate direction (0
11549 // for faces 0 and 1, 1 for faces 2 and 3, 2
11550 // for faces 4 and 5) and subtract the correct
11551 // boundary value of the face (0 for faces 0,
11552 // 2, and 4; 1 for faces 1, 3 and 5)
11553 const double dist =
11554 std::fabs(new_unit[face_no / 2] - face_no % 2);
11555
11556 // compare this with the empirical value
11557 // allowed. if it is too big, flag the face
11558 // for isotropic refinement
11559 const double allowed = 0.25;
11560
11561 if (dist > allowed)
11562 cell->flag_for_face_refinement(face_no);
11563 } // if flagged for anistropic refinement
11564 } // if (cell->face(face)->at_boundary())
11565 } // for all cells
11566 }
11567
11568
11581 template <int dim, int spacedim>
11582 static void
11584 {
11585 Assert(dim < 3,
11586 ExcMessage("Wrong function called -- there should "
11587 "be a specialization."));
11588 }
11589
11590
11591 template <int spacedim>
11592 static void
11595 {
11596 const unsigned int dim = 3;
11597 using raw_line_iterator =
11599
11600 // variable to store whether the mesh was changed in the
11601 // present loop and in the whole process
11602 bool mesh_changed = false;
11603
11604 do
11605 {
11606 mesh_changed = false;
11607
11608 // for this following, we need to know which cells are
11609 // going to be coarsened, if we had to make a
11610 // decision. the following function sets these flags:
11611 triangulation.fix_coarsen_flags();
11612
11613 // first clear flags on lines, since we need them to determine
11614 // which lines will be refined
11615 triangulation.clear_user_flags_line();
11616
11617 // flag those lines that are refined and will not be
11618 // coarsened and those that will be refined
11619 for (const auto &cell : triangulation.cell_iterators())
11620 if (cell->refine_flag_set())
11621 {
11622 const std::array<unsigned int, 12> line_indices =
11623 TriaAccessorImplementation::Implementation::
11624 get_line_indices_of_cell(*cell);
11625 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11627 cell->refine_flag_set(), l) ==
11629 {
11630 raw_line_iterator line(&triangulation,
11631 0,
11632 line_indices[l]);
11633 // flag a line, that will be refined
11634 line->set_user_flag();
11635 }
11636 }
11637 else if (cell->has_children() &&
11638 !cell->child(0)->coarsen_flag_set())
11639 {
11640 const std::array<unsigned int, 12> line_indices =
11641 TriaAccessorImplementation::Implementation::
11642 get_line_indices_of_cell(*cell);
11643 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11645 cell->refinement_case(), l) ==
11647 {
11648 raw_line_iterator line(&triangulation,
11649 0,
11650 line_indices[l]);
11651 // flag a line, that is refined and will stay so
11652 line->set_user_flag();
11653 }
11654 }
11655 else if (cell->has_children() &&
11656 cell->child(0)->coarsen_flag_set())
11657 cell->set_user_flag();
11658
11659
11660 // now check whether there are cells with lines that are
11661 // more than once refined or that will be more than once
11662 // refined. The first thing should never be the case, in
11663 // the second case we flag the cell for refinement
11665 cell = triangulation.last_active();
11666 cell != triangulation.end();
11667 --cell)
11668 {
11669 const std::array<unsigned int, 12> line_indices =
11670 TriaAccessorImplementation::Implementation::
11671 get_line_indices_of_cell(*cell);
11672 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11673 {
11674 raw_line_iterator line(&triangulation, 0, line_indices[l]);
11675 if (line->has_children())
11676 {
11677 // if this line is refined, its children should
11678 // not have further children
11679 //
11680 // however, if any of the children is flagged
11681 // for further refinement, we need to refine
11682 // this cell also (at least, if the cell is not
11683 // already flagged)
11684 bool offending_line_found = false;
11685
11686 for (unsigned int c = 0; c < 2; ++c)
11687 {
11688 Assert(line->child(c)->has_children() == false,
11690
11691 if (line->child(c)->user_flag_set() &&
11693 cell->refine_flag_set(), l) ==
11695 {
11696 // tag this cell for refinement
11697 cell->clear_coarsen_flag();
11698 // if anisotropic coarsening is allowed:
11699 // extend the refine_flag in the needed
11700 // direction, else set refine_flag
11701 // (isotropic)
11702 if (triangulation.smooth_grid &
11704 allow_anisotropic_smoothing)
11705 cell->flag_for_line_refinement(l);
11706 else
11707 cell->set_refine_flag();
11708
11709 for (unsigned int k = 0; k < cell->n_lines();
11710 ++k)
11712 cell->refine_flag_set(), l) ==
11714 // flag a line, that will be refined
11715 raw_line_iterator(&triangulation,
11716 0,
11717 line_indices[k])
11718 ->set_user_flag();
11719
11720 // note that we have changed the grid
11721 offending_line_found = true;
11722
11723 // it may save us several loop
11724 // iterations if we flag all lines of
11725 // this cell now (and not at the outset
11726 // of the next iteration) for refinement
11727 for (unsigned int k = 0; k < cell->n_lines();
11728 ++k)
11729 {
11730 const auto line =
11731 raw_line_iterator(&triangulation,
11732 0,
11733 line_indices[k]);
11734 if (!line->has_children() &&
11736 line_refinement_case(
11737 cell->refine_flag_set(), k) !=
11739 line->set_user_flag();
11740 }
11741
11742 break;
11743 }
11744 }
11745
11746 if (offending_line_found)
11747 {
11748 mesh_changed = true;
11749 break;
11750 }
11751 }
11752 }
11753 }
11754
11755
11756 // there is another thing here: if any of the lines will
11757 // be refined, then we may not coarsen the present cell
11758 // similarly, if any of the lines *is* already refined, we
11759 // may not coarsen the current cell. however, there's a
11760 // catch: if the line is refined, but the cell behind it
11761 // is going to be coarsened, then the situation
11762 // changes. if we forget this second condition, the
11763 // refine_and_coarsen_3d test will start to fail. note
11764 // that to know which cells are going to be coarsened, the
11765 // call for fix_coarsen_flags above is necessary
11767 triangulation.last();
11768 cell != triangulation.end();
11769 --cell)
11770 if (cell->user_flag_set())
11771 {
11772 const std::array<unsigned int, 12> line_indices =
11773 TriaAccessorImplementation::Implementation::
11774 get_line_indices_of_cell(*cell);
11775 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11776 {
11777 raw_line_iterator line(&triangulation,
11778 0,
11779 line_indices[l]);
11780 if (line->has_children() &&
11781 (line->child(0)->user_flag_set() ||
11782 line->child(1)->user_flag_set()))
11783 {
11784 for (unsigned int c = 0; c < cell->n_children(); ++c)
11785 cell->child(c)->clear_coarsen_flag();
11786 cell->clear_user_flag();
11787 for (unsigned int k = 0; k < cell->n_lines(); ++k)
11789 cell->refinement_case(), k) ==
11791 // flag a line, that is refined and will
11792 // stay so
11793 raw_line_iterator(&triangulation,
11794 0,
11795 line_indices[k])
11796 ->set_user_flag();
11797 mesh_changed = true;
11798 break;
11799 }
11800 }
11801 }
11802 }
11803 while (mesh_changed == true);
11804 }
11805
11806
11807
11814 template <int dim, int spacedim>
11815 static bool
11818 {
11819 // in 1d, coarsening is always allowed since we don't enforce
11820 // the 2:1 constraint there
11821 if (dim == 1)
11822 return true;
11823
11824 const RefinementCase<dim> ref_case = cell->refinement_case();
11825 for (const unsigned int n : GeometryInfo<dim>::face_indices())
11826 {
11827 // if the cell is not refined along that face, coarsening
11828 // will not change anything, so do nothing. the same
11829 // applies, if the face is at the boundary
11830 const RefinementCase<dim - 1> face_ref_case =
11831 GeometryInfo<dim>::face_refinement_case(cell->refinement_case(),
11832 n);
11833
11834 const unsigned int n_subfaces =
11835 GeometryInfo<dim - 1>::n_children(face_ref_case);
11836
11837 if (n_subfaces == 0 || cell->at_boundary(n))
11838 continue;
11839 for (unsigned int c = 0; c < n_subfaces; ++c)
11840 {
11842 child = cell->child(
11844
11846 child_neighbor = child->neighbor(n);
11847 if (!child->neighbor_is_coarser(n))
11848 {
11849 // in 2d, if the child's neighbor is coarser, then it has
11850 // no children. however, in 3d it might be
11851 // otherwise. consider for example, that our face might be
11852 // refined with cut_x, but the neighbor is refined with
11853 // cut_xy at that face. then the neighbor pointers of the
11854 // children of our cell will point to the common neighbor
11855 // cell, not to its children. what we really want to know
11856 // in the following is, whether the neighbor cell is
11857 // refined twice with reference to our cell. that only
11858 // has to be asked, if the child's neighbor is not a
11859 // coarser one. we check whether some of the children on
11860 // the neighbor are not flagged for coarsening, in that
11861 // case we may not coarsen. it is enough to check the
11862 // first child because we have already fixed the coarsen
11863 // flags on finer levels
11864 if (child_neighbor->has_children() &&
11865 !(child_neighbor->child(0)->is_active() &&
11866 child_neighbor->child(0)->coarsen_flag_set()))
11867 return false;
11868
11869 // the same applies, if the neighbors children are not
11870 // refined but will be after refinement
11871 if (child_neighbor->refine_flag_set())
11872 return false;
11873 }
11874 }
11875 }
11876 return true;
11877 }
11878 };
11879
11880
11885 {
11886 template <int spacedim>
11887 static void
11890
11891 template <int dim, int spacedim>
11893 {
11894 std::vector<std::pair<unsigned int, unsigned int>> adjacent_cells(
11895 2 * triangulation.n_raw_faces(),
11896 {numbers::invalid_unsigned_int, numbers::invalid_unsigned_int});
11897
11898 const auto set_entry = [&](const auto &face_index, const auto &cell) {
11899 const std::pair<unsigned int, unsigned int> cell_pair = {
11900 cell->level(), cell->index()};
11901 unsigned int index;
11902
11903 if (adjacent_cells[2 * face_index].first ==
11905 adjacent_cells[2 * face_index].second ==
11907 {
11908 index = 2 * face_index + 0;
11909 }
11910 else
11911 {
11912 Assert(((adjacent_cells[2 * face_index + 1].first ==
11914 (adjacent_cells[2 * face_index + 1].second ==
11917 index = 2 * face_index + 1;
11918 }
11919
11920 adjacent_cells[index] = cell_pair;
11921 };
11922
11923 const auto get_entry =
11924 [&](const auto &face_index,
11925 const auto &cell) -> TriaIterator<CellAccessor<dim, spacedim>> {
11926 auto test = adjacent_cells[2 * face_index];
11927
11928 if (test == std::pair<unsigned int, unsigned int>(cell->level(),
11929 cell->index()))
11930 test = adjacent_cells[2 * face_index + 1];
11931
11932 if ((test.first != numbers::invalid_unsigned_int) &&
11933 (test.second != numbers::invalid_unsigned_int))
11935 test.first,
11936 test.second);
11937 else
11939 };
11940
11941 for (const auto &cell : triangulation.cell_iterators())
11942 for (const auto &face : cell->face_iterators())
11943 {
11944 set_entry(face->index(), cell);
11945
11946 if (cell->is_active() && face->has_children())
11947 for (unsigned int c = 0; c < face->n_children(); ++c)
11948 set_entry(face->child(c)->index(), cell);
11949 }
11950
11951 for (const auto &cell : triangulation.cell_iterators())
11952 for (auto f : cell->face_indices())
11953 cell->set_neighbor(f, get_entry(cell->face(f)->index(), cell));
11954 }
11955
11956 template <int dim, int spacedim>
11957 static void
11959 Triangulation<dim, spacedim> & /*triangulation*/,
11961 std::vector<unsigned int> & /*line_cell_count*/,
11962 std::vector<unsigned int> & /*quad_cell_count*/)
11963 {
11965 }
11966
11967 template <int dim, int spacedim>
11970 const bool check_for_distorted_cells)
11971 {
11972 return Implementation::execute_refinement_isotropic(
11973 triangulation, check_for_distorted_cells);
11974 }
11975
11976 template <int dim, int spacedim>
11977 static void
11979 Triangulation<dim, spacedim> & /*triangulation*/)
11980 {
11981 // nothing to do since anisotropy is not supported
11982 }
11983
11984 template <int dim, int spacedim>
11985 static void
11988 {
11989 Implementation::prepare_refinement_dim_dependent(triangulation);
11990 }
11991
11992 template <int dim, int spacedim>
11993 static bool
11996 {
11998
11999 return false;
12000 }
12001 };
12002
12003
12004 template <int dim, int spacedim>
12007 {
12008 static const FlatManifold<dim, spacedim> flat_manifold;
12009 return flat_manifold;
12010 }
12011 } // namespace TriangulationImplementation
12012} // namespace internal
12013
12014#ifndef DOXYGEN
12015
12016template <int dim, int spacedim>
12019
12020
12021
12022template <int dim, int spacedim>
12025 const MeshSmoothing smooth_grid,
12026 const bool check_for_distorted_cells)
12027 : cell_attached_data({0, 0, {}, {}})
12028 , smooth_grid(smooth_grid)
12029 , anisotropic_refinement(false)
12030 , check_for_distorted_cells(check_for_distorted_cells)
12031{
12032 if (dim == 1)
12033 {
12034 vertex_to_boundary_id_map_1d =
12035 std::make_unique<std::map<unsigned int, types::boundary_id>>();
12036 vertex_to_manifold_id_map_1d =
12037 std::make_unique<std::map<unsigned int, types::manifold_id>>();
12038 }
12039
12040 // connect the any_change signal to the other top level signals
12041 signals.create.connect(signals.any_change);
12042 signals.post_refinement.connect(signals.any_change);
12043 signals.clear.connect(signals.any_change);
12044 signals.mesh_movement.connect(signals.any_change);
12045}
12046
12047
12048
12049template <int dim, int spacedim>
12052 Triangulation<dim, spacedim> &&tria) noexcept
12053 : EnableObserverPointer(std::move(tria))
12054 , smooth_grid(tria.smooth_grid)
12055 , reference_cells(std::move(tria.reference_cells))
12056 , periodic_face_pairs_level_0(std::move(tria.periodic_face_pairs_level_0))
12057 , periodic_face_map(std::move(tria.periodic_face_map))
12058 , levels(std::move(tria.levels))
12059 , faces(std::move(tria.faces))
12060 , vertices(std::move(tria.vertices))
12061 , vertices_used(std::move(tria.vertices_used))
12062 , manifolds(std::move(tria.manifolds))
12063 , anisotropic_refinement(tria.anisotropic_refinement)
12064 , check_for_distorted_cells(tria.check_for_distorted_cells)
12065 , number_cache(std::move(tria.number_cache))
12066 , vertex_to_boundary_id_map_1d(std::move(tria.vertex_to_boundary_id_map_1d))
12067 , vertex_to_manifold_id_map_1d(std::move(tria.vertex_to_manifold_id_map_1d))
12068{
12070
12071 if (tria.policy)
12072 this->policy = tria.policy->clone();
12073}
12074
12075
12076template <int dim, int spacedim>
12079 Triangulation<dim, spacedim> &&tria) noexcept
12080{
12081 EnableObserverPointer::operator=(std::move(tria));
12082
12083 smooth_grid = tria.smooth_grid;
12084 reference_cells = std::move(tria.reference_cells);
12085 periodic_face_pairs_level_0 = std::move(tria.periodic_face_pairs_level_0);
12086 periodic_face_map = std::move(tria.periodic_face_map);
12087 levels = std::move(tria.levels);
12088 faces = std::move(tria.faces);
12089 vertices = std::move(tria.vertices);
12090 vertices_used = std::move(tria.vertices_used);
12091 manifolds = std::move(tria.manifolds);
12092 anisotropic_refinement = tria.anisotropic_refinement;
12093 number_cache = tria.number_cache;
12094 vertex_to_boundary_id_map_1d = std::move(tria.vertex_to_boundary_id_map_1d);
12095 vertex_to_manifold_id_map_1d = std::move(tria.vertex_to_manifold_id_map_1d);
12096
12098
12099 if (tria.policy)
12100 this->policy = tria.policy->clone();
12101
12102 return *this;
12103}
12104
12105
12106
12107template <int dim, int spacedim>
12110{
12111 // notify listeners that the triangulation is going down...
12112 try
12113 {
12114 signals.clear();
12115 }
12116 catch (...)
12117 {}
12118
12119 levels.clear();
12120
12121 // the vertex_to_boundary_id_map_1d field should be unused except in
12122 // 1d. double check this here, as destruction is a good place to
12123 // ensure that what we've done over the course of the lifetime of
12124 // this object makes sense
12125 AssertNothrow((dim == 1) || (vertex_to_boundary_id_map_1d == nullptr),
12127
12128 // the vertex_to_manifold_id_map_1d field should be also unused
12129 // except in 1d. check this as well
12130 AssertNothrow((dim == 1) || (vertex_to_manifold_id_map_1d == nullptr),
12132}
12133
12134
12135
12136template <int dim, int spacedim>
12139{
12140 // notify listeners that the triangulation is going down...
12141 signals.clear();
12142
12143 // ...and then actually clear all content of it
12144 clear_despite_subscriptions();
12145 periodic_face_pairs_level_0.clear();
12146 periodic_face_map.clear();
12147 reference_cells.clear();
12148
12149 cell_attached_data = {0, 0, {}, {}};
12150 data_serializer.clear();
12151}
12152
12153template <int dim, int spacedim>
12156{
12157 return MPI_COMM_SELF;
12158}
12159
12160
12161
12162template <int dim, int spacedim>
12165{
12166 return get_mpi_communicator();
12167}
12168
12169
12170
12171template <int dim, int spacedim>
12173std::weak_ptr<const Utilities::MPI::Partitioner> Triangulation<dim, spacedim>::
12175{
12176 return number_cache.active_cell_index_partitioner;
12177}
12178
12179
12180
12181template <int dim, int spacedim>
12183std::weak_ptr<const Utilities::MPI::Partitioner> Triangulation<dim, spacedim>::
12184 global_level_cell_index_partitioner(const unsigned int level) const
12185{
12186 AssertIndexRange(level, this->n_levels());
12187
12188 return number_cache.level_cell_index_partitioners[level];
12189}
12190
12191
12192
12193template <int dim, int spacedim>
12196 const MeshSmoothing mesh_smoothing)
12197{
12198 smooth_grid = mesh_smoothing;
12199}
12200
12201
12202
12203template <int dim, int spacedim>
12207{
12208 return smooth_grid;
12209}
12210
12211
12212
12213template <int dim, int spacedim>
12216 const types::manifold_id m_number,
12217 const Manifold<dim, spacedim> &manifold_object)
12218{
12220
12221 manifolds[m_number] = manifold_object.clone();
12222}
12223
12224
12225
12226template <int dim, int spacedim>
12229 const types::manifold_id m_number)
12230{
12232
12233 // delete the entry located at number.
12234 manifolds[m_number] =
12236 spacedim>()
12237 .clone();
12238}
12239
12240
12241template <int dim, int spacedim>
12244{
12245 for (auto &m : manifolds)
12246 m.second = internal::TriangulationImplementation::
12247 get_default_flat_manifold<dim, spacedim>()
12248 .clone();
12249}
12250
12251
12252template <int dim, int spacedim>
12255 const types::manifold_id m_number)
12256{
12257 Assert(
12258 n_cells() > 0,
12259 ExcMessage(
12260 "Error: set_all_manifold_ids() can not be called on an empty Triangulation."));
12261
12262 for (const auto &cell : this->active_cell_iterators())
12263 cell->set_all_manifold_ids(m_number);
12264}
12265
12266
12267template <int dim, int spacedim>
12270 const types::manifold_id m_number)
12271{
12272 Assert(
12273 n_cells() > 0,
12274 ExcMessage(
12275 "Error: set_all_manifold_ids_on_boundary() can not be called on an empty Triangulation."));
12276
12277 for (const auto &cell : this->active_cell_iterators())
12278 for (auto f : GeometryInfo<dim>::face_indices())
12279 if (cell->face(f)->at_boundary())
12280 cell->face(f)->set_all_manifold_ids(m_number);
12281}
12282
12283
12284template <int dim, int spacedim>
12287 const types::boundary_id b_id,
12288 const types::manifold_id m_number)
12289{
12290 Assert(
12291 n_cells() > 0,
12292 ExcMessage(
12293 "Error: set_all_manifold_ids_on_boundary() can not be called on an empty Triangulation."));
12294
12295 [[maybe_unused]] bool boundary_found = false;
12296
12297 for (const auto &cell : this->active_cell_iterators())
12298 {
12299 // loop on faces
12300 for (auto f : GeometryInfo<dim>::face_indices())
12301 if (cell->face(f)->at_boundary() &&
12302 cell->face(f)->boundary_id() == b_id)
12303 {
12304 boundary_found = true;
12305 cell->face(f)->set_manifold_id(m_number);
12306 }
12307
12308 // loop on edges if dim >= 3
12309 if (dim >= 3)
12310 for (unsigned int e = 0; e < GeometryInfo<dim>::lines_per_cell; ++e)
12311 if (cell->line(e)->at_boundary() &&
12312 cell->line(e)->boundary_id() == b_id)
12313 {
12314 boundary_found = true;
12315 cell->line(e)->set_manifold_id(m_number);
12316 }
12317 }
12318
12319 Assert(boundary_found, ExcBoundaryIdNotFound(b_id));
12320}
12321
12322
12323
12324template <int dim, int spacedim>
12327 const types::manifold_id m_number) const
12328{
12329 // check if flat manifold has been queried
12330 if (m_number == numbers::flat_manifold_id)
12331 return internal::TriangulationImplementation::
12332 get_default_flat_manifold<dim, spacedim>();
12333
12334 // look, if there is a manifold stored at
12335 // manifold_id number.
12336 const auto it = manifolds.find(m_number);
12337
12338 if (it != manifolds.end())
12339 {
12340 // if we have found an entry, return it
12341 return *(it->second);
12342 }
12343
12344 Assert(
12345 false,
12346 ExcMessage(
12347 "No manifold of the manifold id " + std::to_string(m_number) +
12348 " has been attached to the triangulation. "
12349 "Please attach the right manifold with Triangulation::set_manifold()."));
12350
12351 return internal::TriangulationImplementation::
12352 get_default_flat_manifold<dim, spacedim>(); // never reached
12353}
12354
12355
12356
12357template <int dim, int spacedim>
12359std::vector<types::boundary_id> Triangulation<dim, spacedim>::get_boundary_ids()
12360 const
12361{
12362 std::set<types::boundary_id> boundary_ids;
12363 for (const auto &cell : active_cell_iterators())
12364 if (cell->is_locally_owned())
12365 for (const auto &face : cell->face_indices())
12366 if (cell->at_boundary(face))
12367 boundary_ids.insert(cell->face(face)->boundary_id());
12368
12369 return {boundary_ids.begin(), boundary_ids.end()};
12370}
12371
12372
12373
12374template <int dim, int spacedim>
12376std::vector<types::manifold_id> Triangulation<dim, spacedim>::get_manifold_ids()
12377 const
12378{
12379 std::set<types::manifold_id> m_ids;
12380 for (const auto &cell : active_cell_iterators())
12381 if (cell->is_locally_owned())
12382 {
12383 m_ids.insert(cell->manifold_id());
12384 for (const auto &face : cell->face_iterators())
12385 m_ids.insert(face->manifold_id());
12386 if (dim == 3)
12387 {
12388 const auto line_indices = internal::TriaAccessorImplementation::
12389 Implementation::get_line_indices_of_cell(*cell);
12390 for (unsigned int l = 0; l < cell->n_lines(); ++l)
12391 {
12392 raw_line_iterator line(this, 0, line_indices[l]);
12393 m_ids.insert(line->manifold_id());
12394 }
12395 }
12396 }
12397 return {m_ids.begin(), m_ids.end()};
12398}
12399
12400#endif
12401/*-----------------------------------------------------------------*/
12402
12403#ifndef DOXYGEN
12404
12405template <int dim, int spacedim>
12408 const Triangulation<dim, spacedim> &other_tria)
12409{
12410 Assert((vertices.empty()) && (levels.empty()) && (faces == nullptr),
12411 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
12412 Assert((other_tria.levels.size() != 0) && (other_tria.vertices.size() != 0) &&
12413 (dim == 1 || other_tria.faces != nullptr),
12414 ExcMessage(
12415 "When calling Triangulation::copy_triangulation(), "
12416 "the target triangulation must be empty but the source "
12417 "triangulation (the argument to this function) must contain "
12418 "something. Here, it seems like the source does not "
12419 "contain anything at all."));
12420
12421
12422 // copy normal elements
12423 vertices = other_tria.vertices;
12424 vertices_used = other_tria.vertices_used;
12425 anisotropic_refinement = other_tria.anisotropic_refinement;
12426 smooth_grid = other_tria.smooth_grid;
12427 reference_cells = other_tria.reference_cells;
12428
12429 if (dim > 1)
12430 faces = std::make_unique<internal::TriangulationImplementation::TriaFaces>(
12431 *other_tria.faces);
12432
12433 for (const auto &p : other_tria.manifolds)
12434 set_manifold(p.first, *p.second);
12435
12436
12437 levels.reserve(other_tria.levels.size());
12438 for (const auto &level : other_tria.levels)
12439 levels.push_back(
12440 std::make_unique<internal::TriangulationImplementation::TriaLevel>(
12441 *level));
12442
12443 number_cache = other_tria.number_cache;
12444
12445 if (dim == 1)
12446 {
12447 vertex_to_boundary_id_map_1d =
12448 std::make_unique<std::map<unsigned int, types::boundary_id>>(
12449 *other_tria.vertex_to_boundary_id_map_1d);
12450
12451 vertex_to_manifold_id_map_1d =
12452 std::make_unique<std::map<unsigned int, types::manifold_id>>(
12453 *other_tria.vertex_to_manifold_id_map_1d);
12454 }
12455
12456 if (other_tria.policy)
12457 this->policy = other_tria.policy->clone();
12458
12459 // periodic faces
12460 this->periodic_face_pairs_level_0.reserve(
12461 other_tria.periodic_face_pairs_level_0.size());
12462
12463 for (const auto &other_entry : other_tria.periodic_face_pairs_level_0)
12464 {
12465 auto entry = other_entry;
12466 entry.cell[0] =
12467 cell_iterator(this, entry.cell[0]->level(), entry.cell[0]->index());
12468 entry.cell[1] =
12469 cell_iterator(this, entry.cell[1]->level(), entry.cell[1]->index());
12470 periodic_face_pairs_level_0.emplace_back(entry);
12471 }
12472
12473 for (auto [first_cell_, second_cell_and_orientation] :
12474 other_tria.periodic_face_map)
12475 {
12476 auto first_cell = first_cell_; // make copy since key is const
12477 first_cell.first = cell_iterator(this,
12478 first_cell.first->level(),
12479 first_cell.first->index());
12480 second_cell_and_orientation.first.first =
12481 cell_iterator(this,
12482 second_cell_and_orientation.first.first->level(),
12483 second_cell_and_orientation.first.first->index());
12484
12485 this->periodic_face_map[first_cell] = second_cell_and_orientation;
12486 }
12487
12488 // inform those who are listening on other_tria of the copy operation
12489 other_tria.signals.copy(*this);
12490 // also inform all listeners of the current triangulation that the
12491 // triangulation has been created
12492 signals.create();
12493
12494 // note that we need not copy the
12495 // subscriptor!
12496}
12497
12498
12499
12500template <int dim, int spacedim>
12503{
12504 this->update_reference_cells();
12505
12506 if (this->all_reference_cells_are_hyper_cube())
12507 {
12508 this->policy =
12510 dim,
12511 spacedim,
12513 }
12514 else
12515 {
12516 this->policy =
12518 dim,
12519 spacedim,
12521 }
12522}
12523
12524
12525
12526template <int dim, int spacedim>
12529 const std::vector<Point<spacedim>> &v,
12530 const std::vector<CellData<dim>> &cells,
12531 const SubCellData &subcelldata)
12532{
12533 Assert((vertices.empty()) && (levels.empty()) && (faces == nullptr),
12534 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
12535 // check that no forbidden arrays
12536 // are used
12537 Assert(subcelldata.check_consistency(dim), ExcInternalError());
12538
12539 // try to create a triangulation; if this fails, we still want to
12540 // throw an exception but if we just do so we'll get into trouble
12541 // because sometimes other objects are already attached to it:
12542 try
12543 {
12545 create_triangulation(v, cells, subcelldata, *this);
12546 }
12547 catch (...)
12548 {
12549 clear_despite_subscriptions();
12550 throw;
12551 }
12552
12553 reset_policy();
12554
12555 // update our counts of the various elements of a triangulation, and set
12556 // active_cell_indices of all cells
12557 reset_cell_vertex_indices_cache();
12559 *this, levels.size(), number_cache);
12560 reset_active_cell_indices();
12561 reset_global_cell_indices();
12562
12563 // now verify that there are indeed no distorted cells. as per the
12564 // documentation of this class, we first collect all distorted cells
12565 // and then throw an exception if there are any
12566 if (check_for_distorted_cells)
12567 {
12568 DistortedCellList distorted_cells = collect_distorted_coarse_cells(*this);
12569 // throw the array (and fill the various location fields) if
12570 // there are distorted cells. otherwise, just fall off the end
12571 // of the function
12572 AssertThrow(distorted_cells.distorted_cells.empty(), distorted_cells);
12573 }
12574
12575
12576 /*
12577 When the triangulation is a manifold (dim < spacedim) and made of
12578 quadrilaterals, the normal field provided from the map class depends on
12579 the order of the vertices. It may happen that this normal field is
12580 discontinuous. The following code takes care that this is not the case by
12581 setting the cell direction flag on those cell that produce the wrong
12582 orientation.
12583
12584 To determine if 2 neighbors have the same or opposite orientation we use
12585 a truth table. Its entries are indexed by the local indices of the
12586 common face. For example if two elements share a face, and this face is
12587 face 0 for element 0 and face 1 for element 1, then table(0,1) will tell
12588 whether the orientation are the same (true) or opposite (false).
12589
12590 Even though there may be a combinatorial/graph theory argument to get this
12591 table in any dimension, I tested by hand all the different possible cases
12592 in 1D and 2D to generate the table.
12593
12594 Assuming that a surface respects the standard orientation for 2d meshes,
12595 the truth tables are symmetric and their true values are the following
12596
12597 - 1D curves: (0,1)
12598 - 2D surface: (0,1),(0,2),(1,3),(2,3)
12599
12600 We store this data using an n_faces x n_faces full matrix, which is
12601 actually much bigger than the minimal data required, but it makes the code
12602 more readable.
12603
12604 */
12605 if ((dim == spacedim - 1) && all_reference_cells_are_hyper_cube())
12606 {
12609 switch (dim)
12610 {
12611 case 1:
12612 {
12613 const bool values[][2] = {{false, true}, {true, false}};
12614 for (const unsigned int i : GeometryInfo<dim>::face_indices())
12615 for (const unsigned int j : GeometryInfo<dim>::face_indices())
12616 correct(i, j) = values[i][j];
12617 break;
12618 }
12619 case 2:
12620 {
12621 const bool values[][4] = {{false, true, true, false},
12622 {true, false, false, true},
12623 {true, false, false, true},
12624 {false, true, true, false}};
12625 for (const unsigned int i : GeometryInfo<dim>::face_indices())
12626 for (const unsigned int j : GeometryInfo<dim>::face_indices())
12627 correct(i, j) = (values[i][j]);
12628 break;
12629 }
12630 default:
12632 }
12633
12634
12635 std::list<active_cell_iterator> this_round, next_round;
12636 active_cell_iterator neighbor;
12637
12638 // Start with the first cell and (arbitrarily) decide that its
12639 // direction flag should be 'true':
12640 this_round.push_back(begin_active());
12641 begin_active()->set_direction_flag(true);
12642 begin_active()->set_user_flag();
12643
12644 while (this_round.size() > 0)
12645 {
12646 for (const auto &cell : this_round)
12647 {
12648 for (const unsigned int i : cell->face_indices())
12649 {
12650 if (cell->face(i)->at_boundary() == false)
12651 {
12652 // Consider the i'th neighbor of a cell for
12653 // which we have already set the direction:
12654 neighbor = cell->neighbor(i);
12655
12656 const unsigned int nb_of_nb =
12657 cell->neighbor_of_neighbor(i);
12658
12659 // If we already saw this neighboring cell,
12660 // check that everything is fine:
12661 if (neighbor->user_flag_set())
12662 {
12663 Assert(
12664 !(correct(i, nb_of_nb) ^
12665 (neighbor->direction_flag() ==
12666 cell->direction_flag())),
12667 ExcMessage(
12668 "The triangulation you are trying to create is not orientable."));
12669 }
12670 else
12671 {
12672 // We had not seen this cell yet. Set its
12673 // orientation flag (if necessary), mark it
12674 // as treated via the user flag, and push it
12675 // onto the list of cells to start work from
12676 // the next time around:
12677 if (correct(i, nb_of_nb) ^
12678 (neighbor->direction_flag() ==
12679 cell->direction_flag()))
12680 neighbor->set_direction_flag(
12681 !neighbor->direction_flag());
12682 neighbor->set_user_flag();
12683 next_round.push_back(neighbor);
12684 }
12685 }
12686 }
12687 }
12688
12689 // Before we quit let's check that if the triangulation is
12690 // disconnected that we still get all cells by starting
12691 // again from the first cell we haven't treated yet -- that
12692 // is, the first cell of the next disconnected component we
12693 // had not yet touched.
12694 if (next_round.empty())
12695 for (const auto &cell : this->active_cell_iterators())
12696 if (cell->user_flag_set() == false)
12697 {
12698 next_round.push_back(cell);
12699 cell->set_direction_flag(true);
12700 cell->set_user_flag();
12701 break;
12702 }
12703
12704 // Go on to the next round:
12705 next_round.swap(this_round);
12706 next_round.clear();
12707 }
12708 clear_user_flags();
12709 }
12710
12711 this->update_cell_relations();
12712
12713 // inform all listeners that the triangulation has been created
12714 signals.create();
12715}
12716
12717
12718
12719template <int dim, int spacedim>
12723{
12724 // 1) create coarse grid
12726 construction_data.coarse_cells,
12727 SubCellData());
12728
12729 // create a copy of cell_infos such that we can sort them
12730 auto cell_infos = construction_data.cell_infos;
12731
12732 // sort cell_infos on each level separately
12733 for (auto &cell_info : cell_infos)
12734 std::sort(
12735 cell_info.begin(),
12736 cell_info.end(),
12739 const CellId a_id(a.id);
12740 const CellId b_id(b.id);
12741
12742 const auto a_coarse_cell_index =
12743 this->coarse_cell_id_to_coarse_cell_index(a_id.get_coarse_cell_id());
12744 const auto b_coarse_cell_index =
12745 this->coarse_cell_id_to_coarse_cell_index(b_id.get_coarse_cell_id());
12746
12747 // according to their coarse-cell index and if that is
12748 // same according to their cell id (the result is that
12749 // cells on each level are sorted according to their
12750 // index on that level - what we need in the following
12751 // operations)
12752 if (a_coarse_cell_index != b_coarse_cell_index)
12753 return a_coarse_cell_index < b_coarse_cell_index;
12754 else
12755 return a_id < b_id;
12756 });
12757
12758 // 2) create all levels via a sequence of refinements. note that
12759 // we must make sure that we actually have cells on this level,
12760 // which is not clear in a parallel context for some processes
12761 for (unsigned int level = 0;
12762 level < cell_infos.size() && !cell_infos[level].empty();
12763 ++level)
12764 {
12765 // a) set manifold ids here (because new vertices have to be
12766 // positioned correctly during each refinement step)
12767 {
12768 auto cell = this->begin(level);
12769 auto cell_info = cell_infos[level].begin();
12770 for (; cell_info != cell_infos[level].end(); ++cell_info)
12771 {
12772 while (cell_info->id != cell->id().template to_binary<dim>())
12773 ++cell;
12774 if (dim == 2)
12775 for (const auto face : cell->face_indices())
12776 cell->face(face)->set_manifold_id(
12777 cell_info->manifold_line_ids[face]);
12778 else if (dim == 3)
12779 {
12780 for (const auto face : cell->face_indices())
12781 cell->face(face)->set_manifold_id(
12782 cell_info->manifold_quad_ids[face]);
12783
12784 const auto line_indices = internal::TriaAccessorImplementation::
12785 Implementation::get_line_indices_of_cell(*cell);
12786 for (unsigned int l = 0; l < cell->n_lines(); ++l)
12787 {
12788 raw_line_iterator line(this, 0, line_indices[l]);
12789 line->set_manifold_id(cell_info->manifold_line_ids[l]);
12790 }
12791 }
12792
12793 cell->set_manifold_id(cell_info->manifold_id);
12794 }
12795 }
12796
12797 // b) perform refinement on all levels but on the finest
12798 if (level + 1 != cell_infos.size())
12799 {
12800 // find cells that should have children and mark them for
12801 // refinement
12802 auto coarse_cell = this->begin(level);
12803 auto fine_cell_info = cell_infos[level + 1].begin();
12804
12805 // loop over all cells on the next level
12806 for (; fine_cell_info != cell_infos[level + 1].end();
12807 ++fine_cell_info)
12808 {
12809 // find the parent of that cell
12810 while (
12811 !coarse_cell->id().is_parent_of(CellId(fine_cell_info->id)))
12812 ++coarse_cell;
12813
12814 // set parent for refinement
12815 coarse_cell->set_refine_flag();
12816 }
12817
12818 // execute refinement
12819 ::Triangulation<dim,
12820 spacedim>::execute_coarsening_and_refinement();
12821 }
12822 }
12823
12824 // 3) set boundary ids
12825 for (unsigned int level = 0;
12826 level < cell_infos.size() && !cell_infos[level].empty();
12827 ++level)
12828 {
12829 auto cell = this->begin(level);
12830 auto cell_info = cell_infos[level].begin();
12831 for (; cell_info != cell_infos[level].end(); ++cell_info)
12832 {
12833 // find cell that has the correct cell
12834 while (cell_info->id != cell->id().template to_binary<dim>())
12835 ++cell;
12836
12837 // boundary ids
12838 for (auto pair : cell_info->boundary_ids)
12839 if (cell->face(pair.first)->at_boundary())
12840 cell->face(pair.first)->set_boundary_id(pair.second);
12841 }
12842 }
12843
12844 // inform all listeners that the triangulation has been created
12845 signals.create();
12846}
12847
12848
12849template <int dim, int spacedim>
12852{
12853 AssertThrow(dim + 1 == spacedim,
12854 ExcMessage(
12855 "This function can only be called if dim == spacedim-1."));
12856 for (const auto &cell : this->active_cell_iterators())
12857 cell->set_direction_flag(!cell->direction_flag());
12858}
12859
12860
12861
12862template <int dim, int spacedim>
12865{
12866 Assert(n_cells() > 0,
12867 ExcMessage("Error: An empty Triangulation can not be refined."));
12868
12869 for (const auto &cell : this->active_cell_iterators())
12870 {
12871 cell->clear_coarsen_flag();
12872 cell->set_refine_flag();
12873 cell->set_refine_choice();
12874 }
12875}
12876
12877
12878
12879template <int dim, int spacedim>
12881void Triangulation<dim, spacedim>::refine_global(const unsigned int times)
12882{
12883 Assert(n_cells() > 0,
12884 ExcMessage("Error: An empty Triangulation can not be refined."));
12885
12886 for (unsigned int i = 0; i < times; ++i)
12887 {
12888 set_all_refine_flags();
12889 execute_coarsening_and_refinement();
12890 }
12891}
12892
12893
12894
12895template <int dim, int spacedim>
12897void Triangulation<dim, spacedim>::coarsen_global(const unsigned int times)
12898{
12899 for (unsigned int i = 0; i < times; ++i)
12900 {
12901 for (const auto &cell : this->active_cell_iterators())
12902 {
12903 cell->clear_refine_flag();
12904 cell->set_coarsen_flag();
12905 }
12906 execute_coarsening_and_refinement();
12907 }
12908}
12909
12910
12911#endif
12912/*-------------------- refine/coarsen flags -------------------------*/
12913
12914#ifndef DOXYGEN
12915
12916template <int dim, int spacedim>
12918void Triangulation<dim, spacedim>::save_refine_flags(std::vector<bool> &v) const
12919{
12920 v.resize(dim * n_active_cells(), false);
12921 std::vector<bool>::iterator i = v.begin();
12922
12923 for (const auto &cell : this->active_cell_iterators())
12924 for (unsigned int j = 0; j < dim; ++j, ++i)
12925 if (cell->refine_flag_set() & (1 << j))
12926 *i = true;
12927
12928 Assert(i == v.end(), ExcInternalError());
12929}
12930
12931
12932
12933template <int dim, int spacedim>
12935void Triangulation<dim, spacedim>::save_refine_flags(std::ostream &out) const
12936{
12937 std::vector<bool> v;
12938 save_refine_flags(v);
12939 write_bool_vector(mn_tria_refine_flags_begin,
12940 v,
12942 out);
12943}
12944
12945
12946
12947template <int dim, int spacedim>
12950{
12951 std::vector<bool> v;
12952 read_bool_vector(mn_tria_refine_flags_begin, v, mn_tria_refine_flags_end, in);
12953 load_refine_flags(v);
12954}
12955
12956
12957
12958template <int dim, int spacedim>
12960void Triangulation<dim, spacedim>::load_refine_flags(const std::vector<bool> &v)
12961{
12962 AssertThrow(v.size() == dim * n_active_cells(), ExcGridReadError());
12963
12964 std::vector<bool>::const_iterator i = v.begin();
12965 for (const auto &cell : this->active_cell_iterators())
12966 {
12967 unsigned int ref_case = 0;
12968
12969 for (unsigned int j = 0; j < dim; ++j, ++i)
12970 if (*i == true)
12971 ref_case += 1 << j;
12973 ExcGridReadError());
12974 if (ref_case > 0)
12975 cell->set_refine_flag(RefinementCase<dim>(ref_case));
12976 else
12977 cell->clear_refine_flag();
12978 }
12979
12980 Assert(i == v.end(), ExcInternalError());
12981}
12982
12983
12984
12985template <int dim, int spacedim>
12988 std::vector<bool> &v) const
12989{
12990 v.resize(n_active_cells(), false);
12991 std::vector<bool>::iterator i = v.begin();
12992 for (const auto &cell : this->active_cell_iterators())
12993 {
12994 *i = cell->coarsen_flag_set();
12995 ++i;
12996 }
12997
12998 Assert(i == v.end(), ExcInternalError());
12999}
13000
13001
13002
13003template <int dim, int spacedim>
13005void Triangulation<dim, spacedim>::save_coarsen_flags(std::ostream &out) const
13006{
13007 std::vector<bool> v;
13008 save_coarsen_flags(v);
13009 write_bool_vector(mn_tria_coarsen_flags_begin,
13010 v,
13012 out);
13013}
13014
13015
13016
13017template <int dim, int spacedim>
13020{
13021 std::vector<bool> v;
13022 read_bool_vector(mn_tria_coarsen_flags_begin,
13023 v,
13025 in);
13026 load_coarsen_flags(v);
13027}
13028
13029
13030
13031template <int dim, int spacedim>
13034 const std::vector<bool> &v)
13035{
13036 Assert(v.size() == n_active_cells(), ExcGridReadError());
13037
13038 std::vector<bool>::const_iterator i = v.begin();
13039 for (const auto &cell : this->active_cell_iterators())
13040 {
13041 if (*i == true)
13042 cell->set_coarsen_flag();
13043 else
13044 cell->clear_coarsen_flag();
13045 ++i;
13046 }
13047
13048 Assert(i == v.end(), ExcInternalError());
13049}
13050
13051
13052template <int dim, int spacedim>
13055{
13056 return anisotropic_refinement;
13057}
13058
13059
13060#endif
13061
13062namespace internal
13063{
13064 namespace
13065 {
13066 std::vector<std::vector<bool>>
13067 extract_raw_coarsen_flags(
13068 const std::vector<std::unique_ptr<
13070 {
13071 std::vector<std::vector<bool>> coarsen_flags(levels.size());
13072 for (unsigned int level = 0; level < levels.size(); ++level)
13073 coarsen_flags[level] = levels[level]->coarsen_flags;
13074 return coarsen_flags;
13075 }
13076
13077 std::vector<std::vector<std::uint8_t>>
13078 extract_raw_refine_flags(
13079 const std::vector<std::unique_ptr<
13081 {
13082 std::vector<std::vector<std::uint8_t>> refine_flags(levels.size());
13083 for (unsigned int level = 0; level < levels.size(); ++level)
13084 refine_flags[level] = levels[level]->refine_flags;
13085 return refine_flags;
13086 }
13087 } // namespace
13088} // namespace internal
13089
13090
13091/*-------------------- user data/flags -------------------------*/
13092
13093
13094namespace
13095{
13096 // clear user data of cells
13097 void
13098 clear_user_data(std::vector<std::unique_ptr<
13100 {
13101 for (auto &level : levels)
13102 level->cells.clear_user_data();
13103 }
13104
13105
13106 // clear user data of faces
13107 void
13109 {
13110 if (faces->dim == 2)
13111 {
13112 faces->lines.clear_user_data();
13113 }
13114
13115
13116 if (faces->dim == 3)
13117 {
13118 faces->lines.clear_user_data();
13119 faces->quads.clear_user_data();
13120 }
13121 }
13122} // namespace
13123
13124#ifndef DOXYGEN
13125
13126template <int dim, int spacedim>
13129{
13130 // let functions in anonymous namespace do their work
13131 ::clear_user_data(levels);
13132 if (dim > 1)
13133 ::clear_user_data(faces.get());
13134}
13135
13136
13137
13138namespace
13139{
13140 void
13141 clear_user_flags_line(
13142 unsigned int dim,
13143 std::vector<
13144 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
13145 &levels,
13147 {
13148 if (dim == 1)
13149 {
13150 for (const auto &level : levels)
13151 level->cells.clear_user_flags();
13152 }
13153 else if (dim == 2 || dim == 3)
13154 {
13155 faces->lines.clear_user_flags();
13156 }
13157 else
13158 {
13160 }
13161 }
13162} // namespace
13163
13164
13165template <int dim, int spacedim>
13168{
13169 ::clear_user_flags_line(dim, levels, faces.get());
13170}
13171
13172
13173
13174namespace
13175{
13176 void
13177 clear_user_flags_quad(
13178 unsigned int dim,
13179 std::vector<
13180 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
13181 &levels,
13183 {
13184 if (dim == 1)
13185 {
13186 // nothing to do in 1d
13187 }
13188 else if (dim == 2)
13189 {
13190 for (const auto &level : levels)
13191 level->cells.clear_user_flags();
13192 }
13193 else if (dim == 3)
13194 {
13195 faces->quads.clear_user_flags();
13196 }
13197 else
13198 {
13200 }
13201 }
13202} // namespace
13203
13204
13205template <int dim, int spacedim>
13208{
13209 ::clear_user_flags_quad(dim, levels, faces.get());
13210}
13211
13212
13213
13214namespace
13215{
13216 void
13217 clear_user_flags_hex(
13218 unsigned int dim,
13219 std::vector<
13220 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
13221 &levels,
13223 {
13224 if (dim == 1)
13225 {
13226 // nothing to do in 1d
13227 }
13228 else if (dim == 2)
13229 {
13230 // nothing to do in 2d
13231 }
13232 else if (dim == 3)
13233 {
13234 for (const auto &level : levels)
13235 level->cells.clear_user_flags();
13236 }
13237 else
13238 {
13240 }
13241 }
13242} // namespace
13243
13244
13245template <int dim, int spacedim>
13248{
13249 ::clear_user_flags_hex(dim, levels, faces.get());
13250}
13251
13252
13253
13254template <int dim, int spacedim>
13257{
13258 clear_user_flags_line();
13259 clear_user_flags_quad();
13260 clear_user_flags_hex();
13261}
13262
13263
13264
13265template <int dim, int spacedim>
13267void Triangulation<dim, spacedim>::save_user_flags(std::ostream &out) const
13268{
13269 save_user_flags_line(out);
13270
13271 if (dim >= 2)
13272 save_user_flags_quad(out);
13273
13274 if (dim >= 3)
13275 save_user_flags_hex(out);
13276
13277 if (dim >= 4)
13279}
13280
13281
13282
13283template <int dim, int spacedim>
13285void Triangulation<dim, spacedim>::save_user_flags(std::vector<bool> &v) const
13286{
13287 // clear vector and append
13288 // all the stuff later on
13289 v.clear();
13290
13291 std::vector<bool> tmp;
13292
13293 save_user_flags_line(tmp);
13294 v.insert(v.end(), tmp.begin(), tmp.end());
13295
13296 if (dim >= 2)
13297 {
13298 save_user_flags_quad(tmp);
13299 v.insert(v.end(), tmp.begin(), tmp.end());
13300 }
13301
13302 if (dim >= 3)
13303 {
13304 save_user_flags_hex(tmp);
13305 v.insert(v.end(), tmp.begin(), tmp.end());
13306 }
13307
13308 if (dim >= 4)
13310}
13311
13312
13313
13314template <int dim, int spacedim>
13317{
13318 load_user_flags_line(in);
13319
13320 if (dim >= 2)
13321 load_user_flags_quad(in);
13322
13323 if (dim >= 3)
13324 load_user_flags_hex(in);
13325
13326 if (dim >= 4)
13328}
13329
13330
13331
13332template <int dim, int spacedim>
13334void Triangulation<dim, spacedim>::load_user_flags(const std::vector<bool> &v)
13335{
13336 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
13337 std::vector<bool> tmp;
13338
13339 // first extract the flags
13340 // belonging to lines
13341 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
13342 // and set the lines
13343 load_user_flags_line(tmp);
13344
13345 if (dim >= 2)
13346 {
13347 tmp.clear();
13348 tmp.insert(tmp.end(),
13349 v.begin() + n_lines(),
13350 v.begin() + n_lines() + n_quads());
13351 load_user_flags_quad(tmp);
13352 }
13353
13354 if (dim >= 3)
13355 {
13356 tmp.clear();
13357 tmp.insert(tmp.end(),
13358 v.begin() + n_lines() + n_quads(),
13359 v.begin() + n_lines() + n_quads() + n_hexs());
13360 load_user_flags_hex(tmp);
13361 }
13362
13363 if (dim >= 4)
13365}
13366
13367
13368
13369template <int dim, int spacedim>
13372 std::vector<bool> &v) const
13373{
13374 v.resize(n_lines(), false);
13375 std::vector<bool>::iterator i = v.begin();
13376 line_iterator line = begin_line(), endl = end_line();
13377 for (; line != endl; ++line, ++i)
13378 *i = line->user_flag_set();
13379
13380 Assert(i == v.end(), ExcInternalError());
13381}
13382
13383
13384
13385template <int dim, int spacedim>
13387void Triangulation<dim, spacedim>::save_user_flags_line(std::ostream &out) const
13388{
13389 std::vector<bool> v;
13390 save_user_flags_line(v);
13391 write_bool_vector(mn_tria_line_user_flags_begin,
13392 v,
13394 out);
13395}
13396
13397
13398
13399template <int dim, int spacedim>
13402{
13403 std::vector<bool> v;
13404 read_bool_vector(mn_tria_line_user_flags_begin,
13405 v,
13407 in);
13408 load_user_flags_line(v);
13409}
13410
13411
13412
13413template <int dim, int spacedim>
13416 const std::vector<bool> &v)
13417{
13418 Assert(v.size() == n_lines(), ExcGridReadError());
13419
13420 line_iterator line = begin_line(), endl = end_line();
13421 std::vector<bool>::const_iterator i = v.begin();
13422 for (; line != endl; ++line, ++i)
13423 if (*i == true)
13424 line->set_user_flag();
13425 else
13426 line->clear_user_flag();
13427
13428 Assert(i == v.end(), ExcInternalError());
13429}
13430
13431#endif
13432
13433namespace
13434{
13435 template <typename Iterator>
13436 bool
13437 get_user_flag(const Iterator &i)
13438 {
13439 return i->user_flag_set();
13440 }
13441
13442
13443
13444 template <int structdim, int dim, int spacedim>
13445 bool
13447 {
13449 return false;
13450 }
13451
13452
13453
13454 template <typename Iterator>
13455 void
13456 set_user_flag(const Iterator &i)
13457 {
13458 i->set_user_flag();
13459 }
13460
13461
13462
13463 template <int structdim, int dim, int spacedim>
13464 void
13466 {
13468 }
13469
13470
13471
13472 template <typename Iterator>
13473 void
13474 clear_user_flag(const Iterator &i)
13475 {
13476 i->clear_user_flag();
13477 }
13478
13479
13480
13481 template <int structdim, int dim, int spacedim>
13482 void
13483 clear_user_flag(
13485 {
13487 }
13488} // namespace
13489
13490#ifndef DOXYGEN
13491
13492template <int dim, int spacedim>
13495 std::vector<bool> &v) const
13496{
13497 v.resize(n_quads(), false);
13498
13499 if (dim >= 2)
13500 {
13501 std::vector<bool>::iterator i = v.begin();
13502 quad_iterator quad = begin_quad(), endq = end_quad();
13503 for (; quad != endq; ++quad, ++i)
13504 *i = get_user_flag(quad);
13505
13506 Assert(i == v.end(), ExcInternalError());
13507 }
13508}
13509
13510
13511
13512template <int dim, int spacedim>
13514void Triangulation<dim, spacedim>::save_user_flags_quad(std::ostream &out) const
13515{
13516 std::vector<bool> v;
13517 save_user_flags_quad(v);
13518 write_bool_vector(mn_tria_quad_user_flags_begin,
13519 v,
13521 out);
13522}
13523
13524
13525
13526template <int dim, int spacedim>
13529{
13530 std::vector<bool> v;
13531 read_bool_vector(mn_tria_quad_user_flags_begin,
13532 v,
13534 in);
13535 load_user_flags_quad(v);
13536}
13537
13538
13539
13540template <int dim, int spacedim>
13543 const std::vector<bool> &v)
13544{
13545 Assert(v.size() == n_quads(), ExcGridReadError());
13546
13547 if (dim >= 2)
13548 {
13549 quad_iterator quad = begin_quad(), endq = end_quad();
13550 std::vector<bool>::const_iterator i = v.begin();
13551 for (; quad != endq; ++quad, ++i)
13552 if (*i == true)
13553 set_user_flag(quad);
13554 else
13555 clear_user_flag(quad);
13556
13557 Assert(i == v.end(), ExcInternalError());
13558 }
13559}
13560
13561
13562
13563template <int dim, int spacedim>
13566 std::vector<bool> &v) const
13567{
13568 v.resize(n_hexs(), false);
13569
13570 if (dim >= 3)
13571 {
13572 std::vector<bool>::iterator i = v.begin();
13573 hex_iterator hex = begin_hex(), endh = end_hex();
13574 for (; hex != endh; ++hex, ++i)
13575 *i = get_user_flag(hex);
13576
13577 Assert(i == v.end(), ExcInternalError());
13578 }
13579}
13580
13581
13582
13583template <int dim, int spacedim>
13585void Triangulation<dim, spacedim>::save_user_flags_hex(std::ostream &out) const
13586{
13587 std::vector<bool> v;
13588 save_user_flags_hex(v);
13589 write_bool_vector(mn_tria_hex_user_flags_begin,
13590 v,
13592 out);
13593}
13594
13595
13596
13597template <int dim, int spacedim>
13600{
13601 std::vector<bool> v;
13602 read_bool_vector(mn_tria_hex_user_flags_begin,
13603 v,
13605 in);
13606 load_user_flags_hex(v);
13607}
13608
13609
13610
13611template <int dim, int spacedim>
13614 const std::vector<bool> &v)
13615{
13616 Assert(v.size() == n_hexs(), ExcGridReadError());
13617
13618 if (dim >= 3)
13619 {
13620 hex_iterator hex = begin_hex(), endh = end_hex();
13621 std::vector<bool>::const_iterator i = v.begin();
13622 for (; hex != endh; ++hex, ++i)
13623 if (*i == true)
13624 set_user_flag(hex);
13625 else
13626 clear_user_flag(hex);
13627
13628 Assert(i == v.end(), ExcInternalError());
13629 }
13630}
13631
13632
13633
13634template <int dim, int spacedim>
13637 std::vector<unsigned int> &v) const
13638{
13639 // clear vector and append all the
13640 // stuff later on
13641 v.clear();
13642
13643 std::vector<unsigned int> tmp;
13644
13645 save_user_indices_line(tmp);
13646 v.insert(v.end(), tmp.begin(), tmp.end());
13647
13648 if (dim >= 2)
13649 {
13650 save_user_indices_quad(tmp);
13651 v.insert(v.end(), tmp.begin(), tmp.end());
13652 }
13653
13654 if (dim >= 3)
13655 {
13656 save_user_indices_hex(tmp);
13657 v.insert(v.end(), tmp.begin(), tmp.end());
13658 }
13659
13660 if (dim >= 4)
13662}
13663
13664
13665
13666template <int dim, int spacedim>
13669 const std::vector<unsigned int> &v)
13670{
13671 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
13672 std::vector<unsigned int> tmp;
13673
13674 // first extract the indices
13675 // belonging to lines
13676 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
13677 // and set the lines
13678 load_user_indices_line(tmp);
13679
13680 if (dim >= 2)
13681 {
13682 tmp.clear();
13683 tmp.insert(tmp.end(),
13684 v.begin() + n_lines(),
13685 v.begin() + n_lines() + n_quads());
13686 load_user_indices_quad(tmp);
13687 }
13688
13689 if (dim >= 3)
13690 {
13691 tmp.clear();
13692 tmp.insert(tmp.end(),
13693 v.begin() + n_lines() + n_quads(),
13694 v.begin() + n_lines() + n_quads() + n_hexs());
13695 load_user_indices_hex(tmp);
13696 }
13697
13698 if (dim >= 4)
13700}
13701
13702
13703
13704template <int dim, int spacedim>
13706void Triangulation<dim, spacedim>::save(const std::string &file_basename) const
13707{
13708 // Save triangulation information.
13709 {
13710 std::ofstream ofs_tria(file_basename + "_triangulation.data");
13711 AssertThrow(ofs_tria.fail() == false, ExcIO());
13712
13713 boost::archive::text_oarchive oa(ofs_tria, boost::archive::no_header);
13714 save(oa,
13716 }
13717
13718 // Save attached data.
13719 {
13720 std::ofstream ofs_info(file_basename + ".info");
13721 ofs_info
13722 << "version nproc n_attached_fixed_size_objs n_attached_variable_size_objs n_active_cells"
13723 << std::endl
13725 << " " << 1 << " " << this->cell_attached_data.pack_callbacks_fixed.size()
13726 << " " << this->cell_attached_data.pack_callbacks_variable.size() << " "
13727 << this->n_global_active_cells() << std::endl;
13728 }
13729
13730 this->save_attached_data(0, this->n_global_active_cells(), file_basename);
13731}
13732
13733
13734
13735template <int dim, int spacedim>
13737void Triangulation<dim, spacedim>::load(const std::string &file_basename)
13738{
13739 // It's probably prudent to first get rid of any all content of the
13740 // triangulation, rather than hope that the deserialization below
13741 // overwrites everything:
13742 clear();
13743
13744 // Load triangulation information.
13745 {
13746 std::ifstream ifs_tria(file_basename + "_triangulation.data");
13747 AssertThrow(ifs_tria.fail() == false, ExcIO());
13748
13749 boost::archive::text_iarchive ia(ifs_tria, boost::archive::no_header);
13750 load(ia,
13752 }
13753
13754 // Load attached data.
13755 unsigned int version, numcpus, attached_count_fixed, attached_count_variable,
13756 n_global_active_cells;
13757 {
13758 std::ifstream ifs_info(std::string(file_basename) + ".info");
13759 AssertThrow(ifs_info.fail() == false, ExcIO());
13760 std::string firstline;
13761 std::getline(ifs_info, firstline);
13762 ifs_info >> version >> numcpus >> attached_count_fixed >>
13763 attached_count_variable >> n_global_active_cells;
13764 }
13765
13766 AssertThrow(numcpus == 1,
13767 ExcMessage("Incompatible number of CPUs found in .info file."));
13768
13769 const auto expected_version =
13771 spacedim>::version_number;
13772 AssertThrow(version == expected_version,
13773 ExcMessage(
13774 "The information saved in the file you are trying "
13775 "to read the triangulation from was written with an "
13776 "incompatible file format version and cannot be read."));
13777 Assert(this->n_global_active_cells() == n_global_active_cells,
13778 ExcMessage("The number of cells of the triangulation differs "
13779 "from the number of cells written into the .info file."));
13780
13781 // Clear all of the callback data, as explained in the documentation of
13782 // register_data_attach().
13783 this->cell_attached_data.n_attached_data_sets = 0;
13784 this->cell_attached_data.n_attached_deserialize =
13785 attached_count_fixed + attached_count_variable;
13786
13787 this->load_attached_data(0,
13788 this->n_global_active_cells(),
13789 this->n_active_cells(),
13790 file_basename,
13791 attached_count_fixed,
13792 attached_count_variable);
13793
13794 this->update_cell_relations();
13795}
13796
13797#endif
13798namespace
13799{
13800 template <typename Iterator>
13801 unsigned int
13802 get_user_index(const Iterator &i)
13803 {
13804 return i->user_index();
13805 }
13806
13807
13808
13809 template <int structdim, int dim, int spacedim>
13810 unsigned int
13811 get_user_index(
13813 {
13816 }
13817
13818
13819
13820 template <typename Iterator>
13821 void
13822 set_user_index(const Iterator &i, const unsigned int x)
13823 {
13824 i->set_user_index(x);
13825 }
13826
13827
13828
13829 template <int structdim, int dim, int spacedim>
13830 void
13831 set_user_index(
13833 const unsigned int)
13834 {
13836 }
13837} // namespace
13838
13839#ifndef DOXYGEN
13840
13841template <int dim, int spacedim>
13844 std::vector<unsigned int> &v) const
13845{
13846 v.resize(n_lines(), 0);
13847 std::vector<unsigned int>::iterator i = v.begin();
13848 line_iterator line = begin_line(), endl = end_line();
13849 for (; line != endl; ++line, ++i)
13850 *i = line->user_index();
13851}
13852
13853
13854
13855template <int dim, int spacedim>
13858 const std::vector<unsigned int> &v)
13859{
13860 Assert(v.size() == n_lines(), ExcGridReadError());
13861
13862 line_iterator line = begin_line(), endl = end_line();
13863 std::vector<unsigned int>::const_iterator i = v.begin();
13864 for (; line != endl; ++line, ++i)
13865 line->set_user_index(*i);
13866}
13867
13868
13869template <int dim, int spacedim>
13872 std::vector<unsigned int> &v) const
13873{
13874 v.resize(n_quads(), 0);
13875
13876 if (dim >= 2)
13877 {
13878 std::vector<unsigned int>::iterator i = v.begin();
13879 quad_iterator quad = begin_quad(), endq = end_quad();
13880 for (; quad != endq; ++quad, ++i)
13881 *i = get_user_index(quad);
13882 }
13883}
13884
13885
13886
13887template <int dim, int spacedim>
13890 const std::vector<unsigned int> &v)
13891{
13892 Assert(v.size() == n_quads(), ExcGridReadError());
13893
13894 if (dim >= 2)
13895 {
13896 quad_iterator quad = begin_quad(), endq = end_quad();
13897 std::vector<unsigned int>::const_iterator i = v.begin();
13898 for (; quad != endq; ++quad, ++i)
13899 set_user_index(quad, *i);
13900 }
13901}
13902
13903
13904template <int dim, int spacedim>
13907 std::vector<unsigned int> &v) const
13908{
13909 v.resize(n_hexs(), 0);
13910
13911 if (dim >= 3)
13912 {
13913 std::vector<unsigned int>::iterator i = v.begin();
13914 hex_iterator hex = begin_hex(), endh = end_hex();
13915 for (; hex != endh; ++hex, ++i)
13916 *i = get_user_index(hex);
13917 }
13918}
13919
13920
13921
13922template <int dim, int spacedim>
13925 const std::vector<unsigned int> &v)
13926{
13927 Assert(v.size() == n_hexs(), ExcGridReadError());
13928
13929 if (dim >= 3)
13930 {
13931 hex_iterator hex = begin_hex(), endh = end_hex();
13932 std::vector<unsigned int>::const_iterator i = v.begin();
13933 for (; hex != endh; ++hex, ++i)
13934 set_user_index(hex, *i);
13935 }
13936}
13937
13938#endif
13939
13940
13941//---------------- user pointers ----------------------------------------//
13942
13943
13944namespace
13945{
13946 template <typename Iterator>
13947 void *
13948 get_user_pointer(const Iterator &i)
13949 {
13950 return i->user_pointer();
13951 }
13952
13953
13954
13955 template <int structdim, int dim, int spacedim>
13956 void *
13957 get_user_pointer(
13959 {
13961 return nullptr;
13962 }
13963
13964
13965
13966 template <typename Iterator>
13967 void
13968 set_user_pointer(const Iterator &i, void *x)
13969 {
13970 i->set_user_pointer(x);
13971 }
13972
13973
13974
13975 template <int structdim, int dim, int spacedim>
13976 void
13977 set_user_pointer(
13979 void *)
13980 {
13982 }
13983} // namespace
13984
13985#ifndef DOXYGEN
13986
13987template <int dim, int spacedim>
13990 std::vector<void *> &v) const
13991{
13992 // clear vector and append all the
13993 // stuff later on
13994 v.clear();
13995
13996 std::vector<void *> tmp;
13997
13998 save_user_pointers_line(tmp);
13999 v.insert(v.end(), tmp.begin(), tmp.end());
14000
14001 if (dim >= 2)
14002 {
14003 save_user_pointers_quad(tmp);
14004 v.insert(v.end(), tmp.begin(), tmp.end());
14005 }
14006
14007 if (dim >= 3)
14008 {
14009 save_user_pointers_hex(tmp);
14010 v.insert(v.end(), tmp.begin(), tmp.end());
14011 }
14012
14013 if (dim >= 4)
14015}
14016
14017
14018
14019template <int dim, int spacedim>
14022 const std::vector<void *> &v)
14023{
14024 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
14025 std::vector<void *> tmp;
14026
14027 // first extract the pointers
14028 // belonging to lines
14029 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
14030 // and set the lines
14031 load_user_pointers_line(tmp);
14032
14033 if (dim >= 2)
14034 {
14035 tmp.clear();
14036 tmp.insert(tmp.end(),
14037 v.begin() + n_lines(),
14038 v.begin() + n_lines() + n_quads());
14039 load_user_pointers_quad(tmp);
14040 }
14041
14042 if (dim >= 3)
14043 {
14044 tmp.clear();
14045 tmp.insert(tmp.end(),
14046 v.begin() + n_lines() + n_quads(),
14047 v.begin() + n_lines() + n_quads() + n_hexs());
14048 load_user_pointers_hex(tmp);
14049 }
14050
14051 if (dim >= 4)
14053}
14054
14055
14056
14057template <int dim, int spacedim>
14060 std::vector<void *> &v) const
14061{
14062 v.resize(n_lines(), nullptr);
14063 std::vector<void *>::iterator i = v.begin();
14064 line_iterator line = begin_line(), endl = end_line();
14065 for (; line != endl; ++line, ++i)
14066 *i = line->user_pointer();
14067}
14068
14069
14070
14071template <int dim, int spacedim>
14074 const std::vector<void *> &v)
14075{
14076 Assert(v.size() == n_lines(), ExcGridReadError());
14077
14078 line_iterator line = begin_line(), endl = end_line();
14079 std::vector<void *>::const_iterator i = v.begin();
14080 for (; line != endl; ++line, ++i)
14081 line->set_user_pointer(*i);
14082}
14083
14084
14085
14086template <int dim, int spacedim>
14089 std::vector<void *> &v) const
14090{
14091 v.resize(n_quads(), nullptr);
14092
14093 if (dim >= 2)
14094 {
14095 std::vector<void *>::iterator i = v.begin();
14096 quad_iterator quad = begin_quad(), endq = end_quad();
14097 for (; quad != endq; ++quad, ++i)
14098 *i = get_user_pointer(quad);
14099 }
14100}
14101
14102
14103
14104template <int dim, int spacedim>
14107 const std::vector<void *> &v)
14108{
14109 Assert(v.size() == n_quads(), ExcGridReadError());
14110
14111 if (dim >= 2)
14112 {
14113 quad_iterator quad = begin_quad(), endq = end_quad();
14114 std::vector<void *>::const_iterator i = v.begin();
14115 for (; quad != endq; ++quad, ++i)
14116 set_user_pointer(quad, *i);
14117 }
14118}
14119
14120
14121template <int dim, int spacedim>
14124 std::vector<void *> &v) const
14125{
14126 v.resize(n_hexs(), nullptr);
14127
14128 if (dim >= 3)
14129 {
14130 std::vector<void *>::iterator i = v.begin();
14131 hex_iterator hex = begin_hex(), endh = end_hex();
14132 for (; hex != endh; ++hex, ++i)
14133 *i = get_user_pointer(hex);
14134 }
14135}
14136
14137
14138
14139template <int dim, int spacedim>
14142 const std::vector<void *> &v)
14143{
14144 Assert(v.size() == n_hexs(), ExcGridReadError());
14145
14146 if (dim >= 3)
14147 {
14148 hex_iterator hex = begin_hex(), endh = end_hex();
14149 std::vector<void *>::const_iterator i = v.begin();
14150 for (; hex != endh; ++hex, ++i)
14151 set_user_pointer(hex, *i);
14152 }
14153}
14154
14155#endif
14156
14157/*------------------------ Cell iterator functions ------------------------*/
14158
14159#ifndef DOXYGEN
14160
14161template <int dim, int spacedim>
14164 Triangulation<dim, spacedim>::begin_raw(const unsigned int level) const
14165{
14166 switch (dim)
14167 {
14168 case 1:
14169 return begin_raw_line(level);
14170 case 2:
14171 return begin_raw_quad(level);
14172 case 3:
14173 return begin_raw_hex(level);
14174 default:
14176 return raw_cell_iterator();
14177 }
14178}
14179
14180
14181
14182template <int dim, int spacedim>
14185 Triangulation<dim, spacedim>::begin(const unsigned int level) const
14186{
14187 switch (dim)
14188 {
14189 case 1:
14190 return begin_line(level);
14191 case 2:
14192 return begin_quad(level);
14193 case 3:
14194 return begin_hex(level);
14195 default:
14196 Assert(false, ExcImpossibleInDim(dim));
14197 return cell_iterator();
14198 }
14199}
14200
14201
14202
14203template <int dim, int spacedim>
14206 Triangulation<dim, spacedim>::begin_active(const unsigned int level) const
14207{
14208 switch (dim)
14209 {
14210 case 1:
14211 return begin_active_line(level);
14212 case 2:
14213 return begin_active_quad(level);
14214 case 3:
14215 return begin_active_hex(level);
14216 default:
14218 return active_cell_iterator();
14219 }
14220}
14221
14222
14223
14224template <int dim, int spacedim>
14228{
14229 const unsigned int level = levels.size() - 1;
14230 if (levels[level]->cells.n_objects() == 0)
14231 return end(level);
14232
14233 // find the last raw iterator on
14234 // this level
14235 raw_cell_iterator ri(const_cast<Triangulation<dim, spacedim> *>(this),
14236 level,
14237 levels[level]->cells.n_objects() - 1);
14238
14239 // then move to the last used one
14240 if (ri->used() == true)
14241 return ri;
14242 while ((--ri).state() == IteratorState::valid)
14243 if (ri->used() == true)
14244 return ri;
14245 return ri;
14246}
14247
14248
14249
14250template <int dim, int spacedim>
14254{
14255 // get the last used cell
14256 cell_iterator cell = last();
14257
14258 if (cell != end())
14259 {
14260 // then move to the last active one
14261 if (cell->is_active() == true)
14262 return cell;
14263 while ((--cell).state() == IteratorState::valid)
14264 if (cell->is_active() == true)
14265 return cell;
14266 }
14267 return cell;
14268}
14269
14270
14271
14272template <int dim, int spacedim>
14276 const CellId &cell_id) const
14277{
14278 Assert(
14279 this->contains_cell(cell_id),
14280 ExcMessage(
14281 "CellId is invalid for this triangulation.\n"
14282 "Either the provided CellId does not correspond to a cell in this "
14283 "triangulation object, or, in case you are using a parallel "
14284 "triangulation, may correspond to an artificial cell that is less "
14285 "refined on this processor. In the case of "
14286 "parallel::fullydistributed::Triangulation, the corresponding coarse "
14287 "cell might not be accessible by the current process."));
14288
14289 cell_iterator cell(
14290 this, 0, coarse_cell_id_to_coarse_cell_index(cell_id.get_coarse_cell_id()));
14291
14292 for (const auto &child_index : cell_id.get_child_indices())
14293 cell = cell->child(static_cast<unsigned int>(child_index));
14294
14295 return cell;
14296}
14297
14298
14299
14300template <int dim, int spacedim>
14302bool Triangulation<dim, spacedim>::contains_cell(const CellId &cell_id) const
14303{
14304 const auto coarse_cell_index =
14305 coarse_cell_id_to_coarse_cell_index(cell_id.get_coarse_cell_id());
14306
14307 if (coarse_cell_index == numbers::invalid_unsigned_int)
14308 return false;
14309
14310 cell_iterator cell(this, 0, coarse_cell_index);
14311
14312 for (const auto &child_index : cell_id.get_child_indices())
14313 {
14314 if (cell->has_children() == false)
14315 return false;
14316 cell = cell->child(static_cast<unsigned int>(child_index));
14317 }
14318
14319 return true;
14320}
14321
14322
14323
14324template <int dim, int spacedim>
14328{
14329 return cell_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14330 -1,
14331 -1);
14332}
14333
14334
14335
14336template <int dim, int spacedim>
14339 Triangulation<dim, spacedim>::end_raw(const unsigned int level) const
14340{
14341 // This function may be called on parallel triangulations on levels
14342 // that exist globally, but not on the local portion of the
14343 // triangulation. In that case, just return the end iterator.
14344 //
14345 // We need to use levels.size() instead of n_levels() because the
14346 // latter function uses the cache, but we need to be able to call
14347 // this function at a time when the cache is not currently up to
14348 // date.
14349 if (level >= levels.size())
14350 {
14351 Assert(level < n_global_levels(),
14352 ExcInvalidLevel(level, n_global_levels()));
14353 return end();
14354 }
14355
14356 // Query whether the given level is valid for the local portion of the
14357 // triangulation.
14358 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14359 if (level < levels.size() - 1)
14360 return begin_raw(level + 1);
14361 else
14362 return end();
14363}
14364
14365
14366template <int dim, int spacedim>
14369 Triangulation<dim, spacedim>::end(const unsigned int level) const
14370{
14371 // This function may be called on parallel triangulations on levels
14372 // that exist globally, but not on the local portion of the
14373 // triangulation. In that case, just return the end iterator.
14374 //
14375 // We need to use levels.size() instead of n_levels() because the
14376 // latter function uses the cache, but we need to be able to call
14377 // this function at a time when the cache is not currently up to
14378 // date.
14379 if (level >= levels.size())
14380 {
14381 Assert(level < n_global_levels(),
14382 ExcInvalidLevel(level, n_global_levels()));
14383 return end();
14384 }
14385
14386 // Query whether the given level is valid for the local portion of the
14387 // triangulation.
14388 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14389 if (level < levels.size() - 1)
14390 return begin(level + 1);
14391 else
14392 return end();
14393}
14394
14395
14396template <int dim, int spacedim>
14399 Triangulation<dim, spacedim>::end_active(const unsigned int level) const
14400{
14401 // This function may be called on parallel triangulations on levels
14402 // that exist globally, but not on the local portion of the
14403 // triangulation. In that case, just return the end iterator.
14404 //
14405 // We need to use levels.size() instead of n_levels() because the
14406 // latter function uses the cache, but we need to be able to call
14407 // this function at a time when the cache is not currently up to
14408 // date.
14409 if (level >= levels.size())
14410 {
14411 Assert(level < n_global_levels(),
14412 ExcInvalidLevel(level, n_global_levels()));
14413 return end();
14414 }
14415
14416 // Query whether the given level is valid for the local portion of the
14417 // triangulation.
14418 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14419 return (level >= levels.size() - 1 ? active_cell_iterator(end()) :
14420 begin_active(level + 1));
14421}
14422
14423
14424
14425template <int dim, int spacedim>
14429 const
14430{
14432 begin(), end());
14433}
14434
14435
14436template <int dim, int spacedim>
14439 active_cell_iterator> Triangulation<dim, spacedim>::
14441{
14442 return IteratorRange<
14444 end());
14445}
14446
14447
14448
14449template <int dim, int spacedim>
14452 cell_iterator> Triangulation<dim, spacedim>::
14453 cell_iterators_on_level(const unsigned int level) const
14454{
14456 begin(level), end(level));
14457}
14458
14459
14460
14461template <int dim, int spacedim>
14464 active_cell_iterator> Triangulation<dim, spacedim>::
14465 active_cell_iterators_on_level(const unsigned int level) const
14466{
14467 return IteratorRange<
14469 begin_active(level), end_active(level));
14470}
14471#endif
14472
14473/*------------------------ Face iterator functions ------------------------*/
14474
14475#ifndef DOXYGEN
14476
14477template <int dim, int spacedim>
14481{
14482 switch (dim)
14483 {
14484 case 1:
14485 Assert(false, ExcImpossibleInDim(1));
14486 return raw_face_iterator();
14487 case 2:
14488 return begin_line();
14489 case 3:
14490 return begin_quad();
14491 default:
14493 return face_iterator();
14494 }
14495}
14496
14497
14498
14499template <int dim, int spacedim>
14503{
14504 switch (dim)
14505 {
14506 case 1:
14507 Assert(false, ExcImpossibleInDim(1));
14508 return raw_face_iterator();
14509 case 2:
14510 return begin_active_line();
14511 case 3:
14512 return begin_active_quad();
14513 default:
14515 return active_face_iterator();
14516 }
14517}
14518
14519
14520
14521template <int dim, int spacedim>
14525{
14526 switch (dim)
14527 {
14528 case 1:
14529 Assert(false, ExcImpossibleInDim(1));
14530 return raw_face_iterator();
14531 case 2:
14532 return end_line();
14533 case 3:
14534 return end_quad();
14535 default:
14537 return raw_face_iterator();
14538 }
14539}
14540
14541
14542
14543template <int dim, int spacedim>
14546 active_face_iterator> Triangulation<dim, spacedim>::
14548{
14549 return IteratorRange<
14551 begin_active_face(), end_face());
14552}
14553
14554/*------------------------ Vertex iterator functions ------------------------*/
14555
14556
14557template <int dim, int spacedim>
14561{
14562 vertex_iterator i =
14563 raw_vertex_iterator(const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
14564 if (i.state() != IteratorState::valid)
14565 return i;
14566 // This loop will end because every triangulation has used vertices.
14567 while (i->used() == false)
14568 if ((++i).state() != IteratorState::valid)
14569 return i;
14570 return i;
14571}
14572
14573
14574
14575template <int dim, int spacedim>
14579{
14580 // every vertex is active
14581 return begin_vertex();
14582}
14583
14584
14585
14586template <int dim, int spacedim>
14590{
14591 return raw_vertex_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14592 -1,
14594}
14595
14596#endif
14597
14598
14599/*------------------------ Line iterator functions ------------------------*/
14600
14601#ifndef DOXYGEN
14602
14603template <int dim, int spacedim>
14606 Triangulation<dim, spacedim>::begin_raw_line(const unsigned int level) const
14607{
14608 // This function may be called on parallel triangulations on levels
14609 // that exist globally, but not on the local portion of the
14610 // triangulation. In that case, just return the end iterator.
14611 //
14612 // We need to use levels.size() instead of n_levels() because the
14613 // latter function uses the cache, but we need to be able to call
14614 // this function at a time when the cache is not currently up to
14615 // date.
14616 if (level >= levels.size())
14617 {
14618 Assert(level < n_global_levels(),
14619 ExcInvalidLevel(level, n_global_levels()));
14620 return end_line();
14621 }
14622
14623 switch (dim)
14624 {
14625 case 1:
14626 // Query whether the given level is valid for the local portion of the
14627 // triangulation.
14628 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14629
14630 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
14631 return end_line();
14632
14633 return raw_line_iterator(
14634 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
14635
14636 default:
14637 Assert(level == 0, ExcFacesHaveNoLevel());
14638 return raw_line_iterator(
14639 const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
14640 }
14641}
14642
14643
14644template <int dim, int spacedim>
14647 Triangulation<dim, spacedim>::begin_line(const unsigned int level) const
14648{
14649 // level is checked in begin_raw
14650 raw_line_iterator ri = begin_raw_line(level);
14651 if (ri.state() != IteratorState::valid)
14652 return ri;
14653 while (ri->used() == false)
14654 if ((++ri).state() != IteratorState::valid)
14655 return ri;
14656 return ri;
14657}
14658
14659
14660
14661template <int dim, int spacedim>
14665 const unsigned int level) const
14666{
14667 // level is checked in begin_raw
14668 line_iterator i = begin_line(level);
14669 if (i.state() != IteratorState::valid)
14670 return i;
14671 while (i->has_children())
14672 if ((++i).state() != IteratorState::valid)
14673 return i;
14674 return i;
14675}
14676
14677
14678
14679template <int dim, int spacedim>
14683{
14684 return raw_line_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14685 -1,
14686 -1);
14687}
14688
14689#endif
14690
14691/*------------------------ Quad iterator functions ------------------------*/
14692
14693#ifndef DOXYGEN
14694
14695template <int dim, int spacedim>
14698 Triangulation<dim, spacedim>::begin_raw_quad(const unsigned int level) const
14699{
14700 // This function may be called on parallel triangulations on levels
14701 // that exist globally, but not on the local portion of the
14702 // triangulation. In that case, just return the end iterator.
14703 //
14704 // We need to use levels.size() instead of n_levels() because the
14705 // latter function uses the cache, but we need to be able to call
14706 // this function at a time when the cache is not currently up to
14707 // date.
14708 if (level >= levels.size())
14709 {
14710 Assert(level < n_global_levels(),
14711 ExcInvalidLevel(level, n_global_levels()));
14712 return end_quad();
14713 }
14714
14715 switch (dim)
14716 {
14717 case 1:
14718 Assert(false, ExcImpossibleInDim(1));
14719 return raw_hex_iterator();
14720 case 2:
14721 {
14722 // Query whether the given level is valid for the local portion of the
14723 // triangulation.
14724 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14725
14726 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
14727 return end_quad();
14728
14729 return raw_quad_iterator(
14730 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
14731 }
14732
14733 case 3:
14734 {
14735 Assert(level == 0, ExcFacesHaveNoLevel());
14736
14737 return raw_quad_iterator(
14738 const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
14739 }
14740
14741
14742 default:
14744 return raw_hex_iterator();
14745 }
14746}
14747
14748
14749
14750template <int dim, int spacedim>
14753 Triangulation<dim, spacedim>::begin_quad(const unsigned int level) const
14754{
14755 // level is checked in begin_raw
14756 raw_quad_iterator ri = begin_raw_quad(level);
14757 if (ri.state() != IteratorState::valid)
14758 return ri;
14759 while (ri->used() == false)
14760 if ((++ri).state() != IteratorState::valid)
14761 return ri;
14762 return ri;
14763}
14764
14765
14766
14767template <int dim, int spacedim>
14771 const unsigned int level) const
14772{
14773 // level is checked in begin_raw
14774 quad_iterator i = begin_quad(level);
14775 if (i.state() != IteratorState::valid)
14776 return i;
14777 while (i->has_children())
14778 if ((++i).state() != IteratorState::valid)
14779 return i;
14780 return i;
14781}
14782
14783
14784
14785template <int dim, int spacedim>
14789{
14790 return raw_quad_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14791 -1,
14792 -1);
14793}
14794
14795#endif
14796
14797/*------------------------ Hex iterator functions ------------------------*/
14798
14799#ifndef DOXYGEN
14800
14801template <int dim, int spacedim>
14804 Triangulation<dim, spacedim>::begin_raw_hex(const unsigned int level) const
14805{
14806 // This function may be called on parallel triangulations on levels
14807 // that exist globally, but not on the local portion of the
14808 // triangulation. In that case, just return the end iterator.
14809 //
14810 // We need to use levels.size() instead of n_levels() because the
14811 // latter function uses the cache, but we need to be able to call
14812 // this function at a time when the cache is not currently up to
14813 // date.
14814 if (level >= levels.size())
14815 {
14816 Assert(level < n_global_levels(),
14817 ExcInvalidLevel(level, n_global_levels()));
14818 return end_hex();
14819 }
14820
14821 switch (dim)
14822 {
14823 case 1:
14824 case 2:
14825 Assert(false, ExcImpossibleInDim(1));
14826 return raw_hex_iterator();
14827 case 3:
14828 {
14829 // Query whether the given level is valid for the local portion of the
14830 // triangulation.
14831 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14832
14833 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
14834 return end_hex();
14835
14836 return raw_hex_iterator(
14837 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
14838 }
14839
14840 default:
14842 return raw_hex_iterator();
14843 }
14844}
14845
14846
14847
14848template <int dim, int spacedim>
14851 Triangulation<dim, spacedim>::begin_hex(const unsigned int level) const
14852{
14853 // level is checked in begin_raw
14854 raw_hex_iterator ri = begin_raw_hex(level);
14855 if (ri.state() != IteratorState::valid)
14856 return ri;
14857 while (ri->used() == false)
14858 if ((++ri).state() != IteratorState::valid)
14859 return ri;
14860 return ri;
14861}
14862
14863
14864
14865template <int dim, int spacedim>
14869{
14870 // level is checked in begin_raw
14871 hex_iterator i = begin_hex(level);
14872 if (i.state() != IteratorState::valid)
14873 return i;
14874 while (i->has_children())
14875 if ((++i).state() != IteratorState::valid)
14876 return i;
14877 return i;
14878}
14879
14880
14881
14882template <int dim, int spacedim>
14886{
14887 return raw_hex_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14888 -1,
14889 -1);
14890}
14891
14892#endif
14893
14894// -------------------------------- number of cells etc ---------------
14895
14896
14897namespace internal
14898{
14899 namespace TriangulationImplementation
14900 {
14901 inline unsigned int
14903 {
14904 return c.n_lines;
14905 }
14906
14907
14908 inline unsigned int
14911 {
14912 return c.n_active_lines;
14913 }
14914
14915
14916 inline unsigned int
14918 {
14919 return c.n_quads;
14920 }
14921
14922
14923 inline unsigned int
14926 {
14927 return c.n_active_quads;
14928 }
14929
14930
14931 inline unsigned int
14933 {
14934 return c.n_hexes;
14935 }
14936
14937
14938 inline unsigned int
14941 {
14942 return c.n_active_hexes;
14943 }
14944 } // namespace TriangulationImplementation
14945} // namespace internal
14946
14947#ifndef DOXYGEN
14948
14949template <int dim, int spacedim>
14951unsigned int Triangulation<dim, spacedim>::n_cells() const
14952{
14954}
14955
14956
14957template <int dim, int spacedim>
14960{
14962}
14963
14964template <int dim, int spacedim>
14968{
14969 return n_active_cells();
14970}
14971
14972template <int dim, int spacedim>
14976{
14977 return n_cells(0);
14978}
14979
14980template <int dim, int spacedim>
14982unsigned int Triangulation<dim, spacedim>::n_faces() const
14983{
14984 switch (dim)
14985 {
14986 case 1:
14987 return n_used_vertices();
14988 case 2:
14989 return n_lines();
14990 case 3:
14991 return n_quads();
14992 default:
14994 }
14995 return 0;
14996}
14997
14998
14999template <int dim, int spacedim>
15002{
15003 switch (dim)
15004 {
15005 case 1:
15006 return n_vertices();
15007 case 2:
15008 return n_raw_lines();
15009 case 3:
15010 return n_raw_quads();
15011 default:
15013 }
15014 return 0;
15015}
15016
15017
15018template <int dim, int spacedim>
15021{
15022 switch (dim)
15023 {
15024 case 1:
15025 return n_used_vertices();
15026 case 2:
15027 return n_active_lines();
15028 case 3:
15029 return n_active_quads();
15030 default:
15032 }
15033 return 0;
15034}
15035
15036
15037template <int dim, int spacedim>
15040 const unsigned int level) const
15041{
15042 switch (dim)
15043 {
15044 case 1:
15045 return n_raw_lines(level);
15046 case 2:
15047 return n_raw_quads(level);
15048 case 3:
15049 return n_raw_hexs(level);
15050 default:
15052 }
15053 return 0;
15054}
15055
15056
15057
15058template <int dim, int spacedim>
15061 const unsigned int level) const
15062{
15063 switch (dim)
15064 {
15065 case 1:
15066 return n_lines(level);
15067 case 2:
15068 return n_quads(level);
15069 case 3:
15070 return n_hexs(level);
15071 default:
15073 }
15074 return 0;
15075}
15076
15077
15078
15079template <int dim, int spacedim>
15082 const unsigned int level) const
15083{
15084 switch (dim)
15085 {
15086 case 1:
15087 return n_active_lines(level);
15088 case 2:
15089 return n_active_quads(level);
15090 case 3:
15091 return n_active_hexs(level);
15092 default:
15094 }
15095 return 0;
15096}
15097
15098
15099template <int dim, int spacedim>
15102{
15103 if (anisotropic_refinement == false)
15104 {
15105 for (unsigned int lvl = 0; lvl < n_global_levels() - 1; ++lvl)
15106 if (n_active_cells(lvl) != 0)
15107 return true;
15108 }
15109 else
15110 {
15111 for (const auto &cell : active_cell_iterators())
15112 for (const auto &i : cell->face_indices())
15113 if (cell->face(i)->has_children())
15114 return true;
15115 }
15116 return false;
15117}
15118
15119
15120template <int dim, int spacedim>
15122unsigned int Triangulation<dim, spacedim>::n_lines() const
15123{
15124 return number_cache.n_lines;
15125}
15126
15127
15128
15129template <int dim, int spacedim>
15132 const unsigned int level) const
15133{
15134 if (dim == 1)
15135 {
15136 AssertIndexRange(level, n_levels());
15137 return levels[level]->cells.n_objects();
15138 }
15139
15140 Assert(false, ExcFacesHaveNoLevel());
15141 return 0;
15142}
15143
15144
15145template <int dim, int spacedim>
15148{
15149 if (dim == 1)
15150 {
15152 return 0;
15153 }
15154
15155 return faces->lines.n_objects();
15156}
15157
15158
15159template <int dim, int spacedim>
15162 const unsigned int level) const
15163{
15164 AssertIndexRange(level, number_cache.n_lines_level.size());
15165 Assert(dim == 1, ExcFacesHaveNoLevel());
15166 return number_cache.n_lines_level[level];
15167}
15168
15169
15170template <int dim, int spacedim>
15173{
15174 return number_cache.n_active_lines;
15175}
15176
15177
15178template <int dim, int spacedim>
15181 const unsigned int level) const
15182{
15183 AssertIndexRange(level, number_cache.n_lines_level.size());
15184 Assert(dim == 1, ExcFacesHaveNoLevel());
15185
15186 return number_cache.n_active_lines_level[level];
15187}
15188#endif
15189
15190template <>
15191unsigned int
15193{
15194 return 0;
15195}
15196
15197
15198template <>
15199unsigned int
15200Triangulation<1, 1>::n_quads(const unsigned int) const
15201{
15202 return 0;
15203}
15204
15205
15206template <>
15207unsigned int
15208Triangulation<1, 1>::n_raw_quads(const unsigned int) const
15209{
15210 return 0;
15211}
15212
15213
15214template <>
15215unsigned int
15216Triangulation<1, 1>::n_raw_hexs(const unsigned int) const
15217{
15218 return 0;
15219}
15220
15221
15222template <>
15223unsigned int
15225{
15226 return 0;
15227}
15228
15229
15230template <>
15231unsigned int
15233{
15234 return 0;
15235}
15236
15237
15238
15239template <>
15240unsigned int
15242{
15243 return 0;
15244}
15245
15246
15247template <>
15248unsigned int
15249Triangulation<1, 2>::n_quads(const unsigned int) const
15250{
15251 return 0;
15252}
15253
15254
15255template <>
15256unsigned int
15257Triangulation<1, 2>::n_raw_quads(const unsigned int) const
15258{
15259 return 0;
15260}
15261
15262
15263template <>
15264unsigned int
15265Triangulation<1, 2>::n_raw_hexs(const unsigned int) const
15266{
15267 return 0;
15268}
15269
15270
15271template <>
15272unsigned int
15274{
15275 return 0;
15276}
15277
15278
15279template <>
15280unsigned int
15282{
15283 return 0;
15284}
15285
15286
15287template <>
15288unsigned int
15290{
15291 return 0;
15292}
15293
15294
15295template <>
15296unsigned int
15297Triangulation<1, 3>::n_quads(const unsigned int) const
15298{
15299 return 0;
15300}
15301
15302
15303template <>
15304unsigned int
15305Triangulation<1, 3>::n_raw_quads(const unsigned int) const
15306{
15307 return 0;
15308}
15309
15310
15311template <>
15312unsigned int
15313Triangulation<1, 3>::n_raw_hexs(const unsigned int) const
15314{
15315 return 0;
15316}
15317
15318
15319template <>
15320unsigned int
15322{
15323 return 0;
15324}
15325
15326
15327template <>
15328unsigned int
15330{
15331 return 0;
15332}
15333
15334#ifndef DOXYGEN
15335
15336template <int dim, int spacedim>
15338unsigned int Triangulation<dim, spacedim>::n_quads() const
15339{
15340 return number_cache.n_quads;
15341}
15342
15343
15344template <int dim, int spacedim>
15347 const unsigned int level) const
15348{
15349 Assert(dim == 2, ExcFacesHaveNoLevel());
15350 AssertIndexRange(level, number_cache.n_quads_level.size());
15351 return number_cache.n_quads_level[level];
15352}
15353
15354#endif
15355
15356template <>
15357unsigned int
15359{
15360 AssertIndexRange(level, n_levels());
15361 return levels[level]->cells.n_objects();
15362}
15363
15364
15365
15366template <>
15367unsigned int
15369{
15370 AssertIndexRange(level, n_levels());
15371 return levels[level]->cells.n_objects();
15372}
15373
15374
15375template <>
15376unsigned int
15377Triangulation<3, 3>::n_raw_quads(const unsigned int) const
15378{
15379 Assert(false, ExcFacesHaveNoLevel());
15380 return 0;
15381}
15382
15383#ifndef DOXYGEN
15384
15385template <int dim, int spacedim>
15388{
15390 return 0;
15391}
15392
15393#endif
15394
15395template <>
15396unsigned int
15398{
15399 return faces->quads.n_objects();
15400}
15401
15402#ifndef DOXYGEN
15403
15404template <int dim, int spacedim>
15407{
15408 return number_cache.n_active_quads;
15409}
15410
15411
15412template <int dim, int spacedim>
15415 const unsigned int level) const
15416{
15417 AssertIndexRange(level, number_cache.n_quads_level.size());
15418 Assert(dim == 2, ExcFacesHaveNoLevel());
15419
15420 return number_cache.n_active_quads_level[level];
15421}
15422
15423
15424template <int dim, int spacedim>
15426unsigned int Triangulation<dim, spacedim>::n_hexs() const
15427{
15428 return 0;
15429}
15430
15431
15432
15433template <int dim, int spacedim>
15435unsigned int Triangulation<dim, spacedim>::n_hexs(const unsigned int) const
15436{
15437 return 0;
15438}
15439
15440
15441
15442template <int dim, int spacedim>
15444unsigned int Triangulation<dim, spacedim>::n_raw_hexs(const unsigned int) const
15445{
15446 return 0;
15447}
15448
15449
15450template <int dim, int spacedim>
15453{
15454 return 0;
15455}
15456
15457
15458
15459template <int dim, int spacedim>
15462 const unsigned int) const
15463{
15464 return 0;
15465}
15466
15467#endif
15468
15469template <>
15470unsigned int
15472{
15473 return number_cache.n_hexes;
15474}
15475
15476
15477
15478template <>
15479unsigned int
15480Triangulation<3, 3>::n_hexs(const unsigned int level) const
15481{
15482 AssertIndexRange(level, number_cache.n_hexes_level.size());
15483
15484 return number_cache.n_hexes_level[level];
15485}
15486
15487
15488
15489template <>
15490unsigned int
15492{
15493 AssertIndexRange(level, n_levels());
15494 return levels[level]->cells.n_objects();
15495}
15496
15497
15498template <>
15499unsigned int
15501{
15502 return number_cache.n_active_hexes;
15503}
15504
15505
15506
15507template <>
15508unsigned int
15510{
15511 AssertIndexRange(level, number_cache.n_hexes_level.size());
15512
15513 return number_cache.n_active_hexes_level[level];
15514}
15515
15516#ifndef DOXYGEN
15517
15518template <int dim, int spacedim>
15521{
15522 return std::count(vertices_used.begin(), vertices_used.end(), true);
15523}
15524
15525
15526
15527template <int dim, int spacedim>
15529const std::vector<bool> &Triangulation<dim, spacedim>::get_used_vertices() const
15530{
15531 return vertices_used;
15532}
15533
15534#endif
15535
15536template <>
15537unsigned int
15539{
15540 return 2;
15541}
15542
15543
15544
15545template <>
15546unsigned int
15548{
15549 return 2;
15550}
15551
15552
15553template <>
15554unsigned int
15556{
15557 return 2;
15558}
15559
15560#ifndef DOXYGEN
15561
15562template <int dim, int spacedim>
15565{
15566 cell_iterator cell = begin(0),
15567 endc = (n_levels() > 1 ? begin(1) : cell_iterator(end()));
15568 // store the largest index of the
15569 // vertices used on level 0
15570 unsigned int max_vertex_index = 0;
15571 for (; cell != endc; ++cell)
15572 for (const unsigned int vertex : GeometryInfo<dim>::vertex_indices())
15573 if (cell->vertex_index(vertex) > max_vertex_index)
15574 max_vertex_index = cell->vertex_index(vertex);
15575
15576 // store the number of times a cell
15577 // touches a vertex. An unsigned
15578 // int should suffice, even for
15579 // larger dimensions
15580 std::vector<unsigned short int> usage_count(max_vertex_index + 1, 0);
15581 // touch a vertex's usage count
15582 // every time we find an adjacent
15583 // element
15584 for (cell = begin(); cell != endc; ++cell)
15585 for (const unsigned int vertex : GeometryInfo<dim>::vertex_indices())
15586 ++usage_count[cell->vertex_index(vertex)];
15587
15589 static_cast<unsigned int>(
15590 *std::max_element(usage_count.begin(), usage_count.end())));
15591}
15592
15593
15594
15595template <int dim, int spacedim>
15599{
15601}
15602
15603
15604
15605template <int dim, int spacedim>
15608{
15609 return *this;
15610}
15611
15612
15613
15614template <int dim, int spacedim>
15618{
15619 return *this;
15620}
15621
15622
15623
15624template <int dim, int spacedim>
15628 &periodicity_vector)
15629{
15630 periodic_face_pairs_level_0.insert(periodic_face_pairs_level_0.end(),
15631 periodicity_vector.begin(),
15632 periodicity_vector.end());
15633
15634 // Now initialize periodic_face_map
15635 update_periodic_face_map();
15636}
15637
15638
15639
15640template <int dim, int spacedim>
15642const typename std::map<
15643 std::pair<typename Triangulation<dim, spacedim>::cell_iterator, unsigned int>,
15644 std::pair<std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
15645 unsigned int>,
15648{
15649 return periodic_face_map;
15650}
15651
15652
15653template <int dim, int spacedim>
15656{
15657 // We only update the cell relations here for serial triangulations.
15658 // For other triangulations, this is done at other stages of
15659 // mesh creation and mesh refinement.
15661 this))
15662 return;
15663
15664 this->local_cell_relations.clear();
15665 this->local_cell_relations.reserve(this->n_active_cells());
15666
15667 for (const auto &cell : this->active_cell_iterators())
15668 this->local_cell_relations.emplace_back(
15669 cell, ::CellStatus::cell_will_persist);
15670}
15671
15672
15673
15674template <int dim, int spacedim>
15677{
15679 this))
15680 return;
15681
15682 std::vector<CellId> active_cell_old;
15683
15684 // pack data before triangulation gets updated
15685 if (this->cell_attached_data.n_attached_data_sets > 0)
15686 {
15687 // store old active cells to determine cell status after
15688 // coarsening/refinement
15689 active_cell_old.reserve(this->n_active_cells());
15690
15691 for (const auto &cell : this->active_cell_iterators())
15692 {
15693 const bool children_will_be_coarsened =
15694 (cell->level() > 0) && (cell->coarsen_flag_set());
15695
15696 if (children_will_be_coarsened == false)
15697 active_cell_old.emplace_back(cell->id());
15698 else
15699 {
15700 if (cell->parent()->child(0) == cell)
15701 active_cell_old.emplace_back(cell->parent()->id());
15702 }
15703 }
15704
15705 // update cell relations
15706 this->local_cell_relations.clear();
15707 this->local_cell_relations.reserve(this->n_global_active_cells());
15708
15709 std::vector<
15710 std::pair<unsigned int,
15712 cell_relation_t>>
15713 local_cell_relations_tmp;
15714
15715 for (const auto &cell : this->active_cell_iterators())
15716 {
15717 if (std::find(active_cell_old.begin(),
15718 active_cell_old.end(),
15719 cell->id()) != active_cell_old.end())
15720 {
15721 const unsigned int index =
15722 std::distance(active_cell_old.begin(),
15723 std::find(active_cell_old.begin(),
15724 active_cell_old.end(),
15725 cell->id()));
15726
15727 ::CellStatus status =
15728 cell->refine_flag_set() ?
15731
15732 local_cell_relations_tmp.emplace_back(
15733 index,
15735 cell_relation_t{cell, status});
15736 }
15737 else if (cell->level() > 0 &&
15738 std::find(active_cell_old.begin(),
15739 active_cell_old.end(),
15740 cell->parent()->id()) != active_cell_old.end())
15741 {
15742 const unsigned int index =
15743 std::distance(active_cell_old.begin(),
15744 std::find(active_cell_old.begin(),
15745 active_cell_old.end(),
15746 cell->parent()->id()));
15747
15748 ::CellStatus status;
15749
15750 if (cell->parent()->child_iterator_to_index(cell) == 0)
15752 else
15754
15755 local_cell_relations_tmp.emplace_back(
15756 index,
15758 cell_relation_t{cell->parent(), status});
15759 }
15760 else
15761 {
15763 }
15764 }
15765
15766 std::stable_sort(local_cell_relations_tmp.begin(),
15767 local_cell_relations_tmp.end(),
15768 [](const auto &a, const auto &b) {
15769 return a.first < b.first;
15770 });
15771
15772 for (const auto &tmp : local_cell_relations_tmp)
15773 this->local_cell_relations.emplace_back(tmp.second);
15774
15775 // pack data
15776 this->data_serializer.pack_data(
15777 this->local_cell_relations,
15778 this->cell_attached_data.pack_callbacks_fixed,
15779 this->cell_attached_data.pack_callbacks_variable,
15780 this->get_mpi_communicator());
15781
15782 // dummy copy of data
15783 this->data_serializer.dest_data_fixed =
15784 this->data_serializer.src_data_fixed;
15785 this->data_serializer.dest_data_variable =
15786 this->data_serializer.src_data_variable;
15787 this->data_serializer.dest_sizes_variable =
15788 this->data_serializer.src_sizes_variable;
15789 }
15790}
15791
15792
15793
15794template <int dim, int spacedim>
15797{
15799 this))
15800 return;
15801
15802 // transfer data after triangulation got updated
15803 if (this->cell_attached_data.n_attached_data_sets > 0)
15804 {
15805 std::vector<typename internal::CellAttachedDataSerializer<dim, spacedim>::
15806 cell_relation_t>
15807 temp;
15808
15809 for (const auto &cell : local_cell_relations)
15810 {
15811 if (cell.first->has_children())
15812 {
15815
15816 temp.emplace_back(cell.first->child(0),
15818 }
15819 else
15820 temp.push_back(cell);
15821 }
15822
15823 this->local_cell_relations = temp;
15824 }
15825}
15826
15827
15828
15829template <int dim, int spacedim>
15832{
15833 // Call our version of prepare_coarsening_and_refinement() even if a derived
15834 // class like parallel::distributed::Triangulation overrides it. Their
15835 // function will be called in their execute_coarsening_and_refinement()
15836 // function. Even in a distributed computation our job here is to reconstruct
15837 // the local part of the mesh and as such checking our flags is enough.
15839
15840 // verify a case with which we have had
15841 // some difficulty in the past (see the
15842 // deal.II/coarsening_* tests)
15843 if (smooth_grid & limit_level_difference_at_vertices)
15844 Assert(satisfies_level1_at_vertex_rule(*this) == true, ExcInternalError());
15845
15846 // Inform all listeners about beginning of refinement.
15847 signals.pre_refinement();
15848
15849 this->pack_data_serial();
15850
15851 execute_coarsening();
15852
15853 const DistortedCellList cells_with_distorted_children = execute_refinement();
15854
15855 // We need to update the cell relations in order to be able to
15856 // deserialize data. Later on, update_cell_relations is called to mark all
15857 // active cells with the cell_will_persist status.
15858 this->unpack_data_serial();
15859
15860 reset_cell_vertex_indices_cache();
15861
15862 // verify a case with which we have had
15863 // some difficulty in the past (see the
15864 // deal.II/coarsening_* tests)
15865 if (smooth_grid & limit_level_difference_at_vertices)
15866 Assert(satisfies_level1_at_vertex_rule(*this) == true, ExcInternalError());
15867
15868 // finally build up neighbor connectivity information, and set
15869 // active cell indices
15870 this->policy->update_neighbors(*this);
15871 reset_active_cell_indices();
15872
15873 reset_global_cell_indices(); // TODO: better place?
15874
15875 // Inform all listeners about end of refinement.
15876 signals.post_refinement();
15877
15878 AssertThrow(cells_with_distorted_children.distorted_cells.empty(),
15879 cells_with_distorted_children);
15880
15881 update_periodic_face_map();
15882
15883 if (this->cell_attached_data.n_attached_data_sets == 0)
15884 this->update_cell_relations();
15885
15886 if constexpr (running_in_debug_mode())
15887 {
15888 // In debug mode, we want to check for some consistency of the
15889 // result of this function. Because there are multiple exit
15890 // paths, put this check into a ScopeExit object that is
15891 // executed on each of the exit paths.
15892 //
15893 // Specifically, check on exit of this function that if a quad
15894 // cell has been refined, all of its children have neighbors
15895 // in all directions in which the parent cell has neighbors as
15896 // well. The children's neighbors are either the parent
15897 // neighbor or the parent neighbor's children, or simply one of
15898 // the other children of the current cell. This check is
15899 // useful because if one creates a triangulation with an
15900 // inconsistently ordered set of cells (e.g., because one has
15901 // forgotten to call GridTools::consistently_order_cells()),
15902 // then this relatively simple invariant is violated -- so the
15903 // check here can be used to catch that case, at least
15904 // sometimes.
15905 //
15906 // In 1d, this situation cannot happen. In 3d, we have explicit
15907 // orientation flags to ensure that it is not necessary to re-orient
15908 // cells at the beginning. But in both cases, the invariant should
15909 // still hold as long as the cell is a hypercube.
15910 for (const auto &cell : cell_iterators())
15911 {
15912 if (cell->has_children() && cell->reference_cell().is_hyper_cube())
15913 for (const unsigned int f : cell->face_indices())
15914 if (cell->at_boundary(f) == false)
15915 {
15916 for (const auto &child : cell->child_iterators())
15917 {
15918 Assert(
15919 child->at_boundary(f) == false,
15920 ExcMessage(
15921 "We ended up with a triangulation whose child cells "
15922 "are not connected to their neighbors as expected. "
15923 "When you created the triangulation, did you forget "
15924 "to call GridTools::consistently_order_cells() "
15925 "before calling Triangulation::create_triangulation()?"));
15926 }
15927 }
15928 }
15929 }
15930}
15931
15932
15933
15934template <int dim, int spacedim>
15937{
15938 unsigned int active_cell_index = 0;
15939 for (raw_cell_iterator cell = begin_raw(); cell != end(); ++cell)
15940 if ((cell->used() == false) || cell->has_children())
15941 cell->set_active_cell_index(numbers::invalid_unsigned_int);
15942 else
15943 {
15944 cell->set_active_cell_index(active_cell_index);
15945 ++active_cell_index;
15946 }
15947
15948 Assert(active_cell_index == n_active_cells(), ExcInternalError());
15949}
15950
15951
15952
15953template <int dim, int spacedim>
15956{
15957 {
15959 for (const auto &cell : active_cell_iterators())
15960 cell->set_global_active_cell_index(cell_index++);
15961 }
15962
15963 for (unsigned int l = 0; l < levels.size(); ++l)
15964 {
15966 for (const auto &cell : cell_iterators_on_level(l))
15967 cell->set_global_level_cell_index(cell_index++);
15968 }
15969}
15970
15971
15972
15973template <int dim, int spacedim>
15976{
15977 for (unsigned int l = 0; l < levels.size(); ++l)
15978 {
15979 std::vector<unsigned int> &cache = levels[l]->cell_vertex_indices_cache;
15980 cache.clear();
15981 cache.resize(levels[l]->refine_flags.size() *
15982 ReferenceCells::max_n_vertices<dim>(),
15984 for (const auto &cell : cell_iterators_on_level(l))
15985 {
15986 const unsigned int my_index =
15987 cell->index() * ReferenceCells::max_n_vertices<dim>();
15988
15989 // to reduce the cost of this function when passing down into quads,
15990 // then lines, then vertices, we use a more low-level access method
15991 // for hexahedral cells, where we can streamline most of the logic
15992 const ReferenceCell ref_cell = cell->reference_cell();
15993 if (ref_cell == ReferenceCells::Hexahedron)
15994 for (unsigned int face = 4; face < 6; ++face)
15995 {
15996 const auto face_iter = cell->face(face);
15997 const std::array<types::geometric_orientation, 2>
15998 line_orientations{{face_iter->line_orientation(0),
15999 face_iter->line_orientation(1)}};
16000 const std::array<unsigned int, 2> line_vertex_indices{
16001 {line_orientations[0] ==
16003 line_orientations[1] ==
16005 const std::array<unsigned int, 4> raw_vertex_indices{
16006 {face_iter->line(0)->vertex_index(1 - line_vertex_indices[0]),
16007 face_iter->line(1)->vertex_index(1 - line_vertex_indices[1]),
16008 face_iter->line(0)->vertex_index(line_vertex_indices[0]),
16009 face_iter->line(1)->vertex_index(line_vertex_indices[1])}};
16010
16011 const auto combined_orientation =
16012 levels[l]->face_orientations.get_combined_orientation(
16013 cell->index() * ReferenceCells::max_n_faces<dim>() + face);
16014 const std::array<unsigned int, 4> vertex_order{
16015 {ref_cell.standard_to_real_face_vertex(0,
16016 face,
16017 combined_orientation),
16019 face,
16020 combined_orientation),
16022 face,
16023 combined_orientation),
16025 3, face, combined_orientation)}};
16026
16027 const unsigned int index = my_index + 4 * (face - 4);
16028 for (unsigned int i = 0; i < 4; ++i)
16029 cache[index + i] = raw_vertex_indices[vertex_order[i]];
16030 }
16031 else if (ref_cell == ReferenceCells::Quadrilateral)
16032 {
16033 const std::array<types::geometric_orientation, 2>
16034 line_orientations{
16035 {cell->line_orientation(0), cell->line_orientation(1)}};
16036 const std::array<unsigned int, 2> line_vertex_indices{
16037 {line_orientations[0] == numbers::default_geometric_orientation,
16038 line_orientations[1] ==
16040 const std::array<unsigned int, 4> raw_vertex_indices{
16041 {cell->line(0)->vertex_index(1 - line_vertex_indices[0]),
16042 cell->line(1)->vertex_index(1 - line_vertex_indices[1]),
16043 cell->line(0)->vertex_index(line_vertex_indices[0]),
16044 cell->line(1)->vertex_index(line_vertex_indices[1])}};
16045 for (unsigned int i = 0; i < 4; ++i)
16046 cache[my_index + i] = raw_vertex_indices[i];
16047 }
16048 else if (ref_cell == ReferenceCells::Line)
16049 {
16050 cache[my_index + 0] = cell->vertex_index(0);
16051 cache[my_index + 1] = cell->vertex_index(1);
16052 }
16053 else
16054 {
16055 Assert(dim == 2 || dim == 3, ExcInternalError());
16056 for (const unsigned int i : cell->vertex_indices())
16057 {
16058 const auto [face_index, vertex_index] =
16060 const auto vertex_within_face_index =
16062 vertex_index,
16063 face_index,
16064 cell->combined_face_orientation(face_index));
16065 cache[my_index + i] =
16066 cell->face(face_index)
16067 ->vertex_index(vertex_within_face_index);
16068 }
16069 }
16070 }
16071 }
16072}
16073
16074
16075
16076template <int dim, int spacedim>
16079{
16080 // first empty the currently stored objects
16081 periodic_face_map.clear();
16082
16083 typename std::vector<
16085 for (it = periodic_face_pairs_level_0.begin();
16086 it != periodic_face_pairs_level_0.end();
16087 ++it)
16088 {
16089 update_periodic_face_map_recursively<dim, spacedim>(it->cell[0],
16090 it->cell[1],
16091 it->face_idx[0],
16092 it->face_idx[1],
16093 it->orientation,
16094 periodic_face_map);
16095
16096 const auto face_reference_cell =
16097 it->cell[0]->reference_cell().face_reference_cell(it->face_idx[0]);
16098 // for the other way, we need to invert the orientation
16099 update_periodic_face_map_recursively<dim, spacedim>(
16100 it->cell[1],
16101 it->cell[0],
16102 it->face_idx[1],
16103 it->face_idx[0],
16104 face_reference_cell.get_inverse_combined_orientation(it->orientation),
16105 periodic_face_map);
16106 }
16107
16108 // check consistency
16109 typename std::map<std::pair<cell_iterator, unsigned int>,
16110 std::pair<std::pair<cell_iterator, unsigned int>,
16111 types::geometric_orientation>>::const_iterator
16112 it_test;
16113 for (it_test = periodic_face_map.begin(); it_test != periodic_face_map.end();
16114 ++it_test)
16115 {
16117 it_test->first.first;
16119 it_test->second.first.first;
16120 if (cell_1->level() == cell_2->level())
16121 {
16122 // if both cells have the same neighbor, then the same pair
16123 // order swapped has to be in the map
16124 Assert(periodic_face_map[it_test->second.first].first ==
16125 it_test->first,
16127 }
16128 }
16129}
16130
16131
16132
16133template <int dim, int spacedim>
16136{
16137 std::set<ReferenceCell> reference_cells_set;
16138 for (auto cell : active_cell_iterators())
16139 if (cell->is_locally_owned())
16140 reference_cells_set.insert(cell->reference_cell());
16141
16142 this->reference_cells =
16143 std::vector<ReferenceCell>(reference_cells_set.begin(),
16144 reference_cells_set.end());
16145}
16146
16147
16148
16149template <int dim, int spacedim>
16151const std::vector<ReferenceCell>
16153{
16154 return this->reference_cells;
16155}
16156
16157
16158
16159template <int dim, int spacedim>
16162{
16163 Assert(this->reference_cells.size() > 0,
16164 ExcMessage("You can't ask about the kinds of reference "
16165 "cells used by this triangulation if the "
16166 "triangulation doesn't yet have any cells in it."));
16167 return (this->reference_cells.size() == 1 &&
16168 this->reference_cells[0].is_hyper_cube());
16169}
16170
16171
16172
16173template <int dim, int spacedim>
16176{
16177 Assert(this->reference_cells.size() > 0,
16178 ExcMessage("You can't ask about the kinds of reference "
16179 "cells used by this triangulation if the "
16180 "triangulation doesn't yet have any cells in it."));
16181 return (this->reference_cells.size() == 1 &&
16182 this->reference_cells[0].is_simplex());
16183}
16184
16185
16186
16187template <int dim, int spacedim>
16190{
16191 Assert(this->reference_cells.size() > 0,
16192 ExcMessage("You can't ask about the kinds of reference "
16193 "cells used by this triangulation if the "
16194 "triangulation doesn't yet have any cells in it."));
16195 return reference_cells.size() > 1 ||
16196 ((reference_cells[0].is_hyper_cube() == false) &&
16197 (reference_cells[0].is_simplex() == false));
16198}
16199
16200
16201
16202template <int dim, int spacedim>
16205 const std::function<std::vector<char>(const cell_iterator &,
16206 const ::CellStatus)>
16207 &pack_callback,
16208 const bool returns_variable_size_data)
16209{
16210 unsigned int handle = numbers::invalid_unsigned_int;
16211
16212 // Add new callback function to the corresponding register.
16213 // Encode handles according to returns_variable_size_data.
16214 if (returns_variable_size_data)
16215 {
16216 handle = 2 * this->cell_attached_data.pack_callbacks_variable.size();
16217 this->cell_attached_data.pack_callbacks_variable.push_back(pack_callback);
16218 }
16219 else
16220 {
16221 handle = 2 * this->cell_attached_data.pack_callbacks_fixed.size() + 1;
16222 this->cell_attached_data.pack_callbacks_fixed.push_back(pack_callback);
16223 }
16224
16225 // Increase overall counter.
16226 ++this->cell_attached_data.n_attached_data_sets;
16227
16228 return handle;
16229}
16230
16231
16232
16233template <int dim, int spacedim>
16236 const unsigned int handle,
16237 const std::function<
16238 void(const cell_iterator &,
16239 const ::CellStatus,
16240 const boost::iterator_range<std::vector<char>::const_iterator> &)>
16241 &unpack_callback)
16242{
16243 // perform unpacking
16244 this->data_serializer.unpack_data(this->local_cell_relations,
16245 handle,
16246 unpack_callback);
16247
16248 // decrease counters
16249 --this->cell_attached_data.n_attached_data_sets;
16250 if (this->cell_attached_data.n_attached_deserialize > 0)
16251 --this->cell_attached_data.n_attached_deserialize;
16252
16253 // important: only remove data if we are not in the deserialization
16254 // process. There, each SolutionTransfer registers and unpacks before
16255 // the next one does this, so n_attached_data_sets is only 1 here. This
16256 // would destroy the saved data before the second SolutionTransfer can
16257 // get it. This created a bug that is documented in
16258 // tests/mpi/p4est_save_03 with more than one SolutionTransfer.
16259
16260 if (this->cell_attached_data.n_attached_data_sets == 0 &&
16261 this->cell_attached_data.n_attached_deserialize == 0)
16262 {
16263 // everybody got their data, time for cleanup!
16264 this->cell_attached_data.pack_callbacks_fixed.clear();
16265 this->cell_attached_data.pack_callbacks_variable.clear();
16266 this->data_serializer.clear();
16267
16268 // reset all cell_status entries after coarsening/refinement
16269 for (auto &cell_rel : this->local_cell_relations)
16270 cell_rel.second = ::CellStatus::cell_will_persist;
16271 }
16272}
16273
16274
16275
16276template <int dim, int spacedim>
16279 const unsigned int global_first_cell,
16280 const unsigned int global_num_cells,
16281 const std::string &file_basename) const
16282{
16283 // cast away constness
16284 auto tria = const_cast<Triangulation<dim, spacedim> *>(this);
16285
16286 // each cell should have been flagged `CellStatus::cell_will_persist`
16287 for (const auto &cell_rel : this->local_cell_relations)
16288 {
16289 (void)cell_rel;
16290 Assert((cell_rel.second == // cell_status
16293 }
16294
16295 if (this->cell_attached_data.n_attached_data_sets > 0)
16296 {
16297 // pack attached data first
16298 tria->data_serializer.pack_data(
16299 tria->local_cell_relations,
16300 tria->cell_attached_data.pack_callbacks_fixed,
16301 tria->cell_attached_data.pack_callbacks_variable,
16302 this->get_mpi_communicator());
16303
16304 // then store buffers in file
16305 tria->data_serializer.save(global_first_cell,
16306 global_num_cells,
16307 file_basename,
16308 this->get_mpi_communicator());
16309
16310 // and release the memory afterwards
16311 tria->data_serializer.clear();
16312 }
16313
16314 // clear all of the callback data, as explained in the documentation of
16315 // register_data_attach()
16316 {
16317 tria->cell_attached_data.n_attached_data_sets = 0;
16318 tria->cell_attached_data.pack_callbacks_fixed.clear();
16319 tria->cell_attached_data.pack_callbacks_variable.clear();
16320 }
16321}
16322
16323
16324template <int dim, int spacedim>
16327 const unsigned int global_first_cell,
16328 const unsigned int global_num_cells,
16329 const unsigned int local_num_cells,
16330 const std::string &file_basename,
16331 const unsigned int n_attached_deserialize_fixed,
16332 const unsigned int n_attached_deserialize_variable)
16333{
16334 // load saved data, if any was stored
16335 if (this->cell_attached_data.n_attached_deserialize > 0)
16336 {
16337 this->data_serializer.load(global_first_cell,
16338 global_num_cells,
16339 local_num_cells,
16340 file_basename,
16341 n_attached_deserialize_fixed,
16342 n_attached_deserialize_variable,
16343 this->get_mpi_communicator());
16344
16345 this->data_serializer.unpack_cell_status(this->local_cell_relations);
16346
16347 if constexpr (running_in_debug_mode())
16348 {
16349 // the CellStatus of all stored cells should always be
16350 // CellStatus::cell_will_persist.
16351 for (const auto &cell_rel : this->local_cell_relations)
16352 {
16353 Assert((cell_rel.second == // cell_status
16356 }
16357 }
16358 }
16359}
16360
16361
16362template <int dim, int spacedim>
16365{
16366 levels.clear();
16367 faces.reset();
16368
16369 vertices.clear();
16370 vertices_used.clear();
16371
16372 manifolds.clear();
16373
16374 // In 1d, also reset vertex-to-(boundary|manifold) maps to empty maps
16375 if (dim == 1)
16376 {
16377 Assert(vertex_to_boundary_id_map_1d != nullptr, ExcInternalError());
16378 vertex_to_boundary_id_map_1d->clear();
16379
16380 Assert(vertex_to_manifold_id_map_1d != nullptr, ExcInternalError());
16381 vertex_to_manifold_id_map_1d->clear();
16382 }
16383 else
16384 {
16385 // For dim>1, these maps should simply not exist.
16386 Assert(vertex_to_boundary_id_map_1d == nullptr, ExcInternalError());
16387 Assert(vertex_to_manifold_id_map_1d == nullptr, ExcInternalError());
16388 }
16389
16390
16392}
16393
16394
16395
16396template <int dim, int spacedim>
16400{
16401 const DistortedCellList cells_with_distorted_children =
16402 this->policy->execute_refinement(*this, check_for_distorted_cells);
16403
16404
16405
16406 // re-compute number of lines
16408 *this, levels.size(), number_cache);
16409
16410 if constexpr (running_in_debug_mode())
16411 {
16412 for (const auto &level : levels)
16413 monitor_memory(level->cells, dim);
16414
16415 // check whether really all refinement flags are reset (also of
16416 // previously non-active cells which we may not have touched. If the
16417 // refinement flag of a non-active cell is set, something went wrong
16418 // since the cell-accessors should have caught this)
16419 for (const auto &cell : this->cell_iterators())
16420 Assert(!cell->refine_flag_set(), ExcInternalError());
16421 }
16422
16423 return cells_with_distorted_children;
16424}
16425
16426
16427
16428template <int dim, int spacedim>
16431{
16432 // first find out if there are any cells at all to be coarsened in the
16433 // loop below
16434 const cell_iterator endc = end();
16435 bool do_coarsen = false;
16436 if (levels.size() >= 2)
16437 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
16438 if (!cell->is_active() && cell->child(0)->coarsen_flag_set())
16439 {
16440 do_coarsen = true;
16441 break;
16442 }
16443
16444 if (!do_coarsen)
16445 return;
16446
16447 // create a vector counting for each line and quads how many cells contain
16448 // the respective object. this is used later to decide which lines can be
16449 // deleted after coarsening a cell.
16450 std::vector<unsigned int> line_cell_count(dim > 1 ? this->n_raw_lines() : 0);
16451 std::vector<unsigned int> quad_cell_count(dim > 2 ? this->n_raw_quads() : 0);
16452 if (dim > 1)
16453 for (const auto &cell : this->cell_iterators())
16454 {
16455 if (dim > 2)
16456 {
16457 const auto line_indices = internal::TriaAccessorImplementation::
16458 Implementation::get_line_indices_of_cell(*cell);
16459 // avoid a compiler warning by fixing the max number of
16460 // loop iterations to 12
16461 const unsigned int n_lines = std::min(cell->n_lines(), 12u);
16462 for (unsigned int l = 0; l < n_lines; ++l)
16463 ++line_cell_count[line_indices[l]];
16464 for (const unsigned int q : cell->face_indices())
16465 ++quad_cell_count[cell->face_index(q)];
16466 }
16467 else
16468 for (unsigned int l = 0; l < cell->n_lines(); ++l)
16469 ++line_cell_count[cell->line(l)->index()];
16470 }
16471
16472 // Since the loop goes over used cells we only need not worry about
16473 // deleting some cells since the ++operator will then just hop over them
16474 // if we should hit one. Do the loop in the reverse way since we may
16475 // only delete some cells if their neighbors have already been deleted
16476 // (if the latter are on a higher level for example). In effect, only
16477 // those cells are deleted of which originally all children were flagged
16478 // and for which all children are on the same refinement level. Note
16479 // that because of the effects of
16480 // @p{fix_coarsen_flags}, of a cell either all or no children must be
16481 // flagged for coarsening, so it is ok to only check the first child
16482 //
16483 // since we delete the *children* of cells, we can ignore cells on the
16484 // highest level, i.e., level must be less than or equal to
16485 // n_levels()-2.
16486 if (levels.size() >= 2)
16487 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
16488 if (!cell->is_active() && cell->child(0)->coarsen_flag_set())
16489 {
16490 for (unsigned int child = 0; child < cell->n_children(); ++child)
16491 {
16492 Assert(cell->child(child)->coarsen_flag_set(),
16494 cell->child(child)->clear_coarsen_flag();
16495 }
16496 // inform all listeners that cell coarsening is going to happen
16497 signals.pre_coarsening_on_cell(cell);
16498 // use a separate function, since this is dimension specific
16499 this->policy->delete_children(*this,
16500 cell,
16501 line_cell_count,
16502 quad_cell_count);
16503 }
16504
16505 // re-compute number of lines and quads
16507 *this, levels.size(), number_cache);
16508}
16509
16510
16511
16512template <int dim, int spacedim>
16515{
16516 // copy a piece of code from prepare_coarsening_and_refinement that
16517 // ensures that the level difference at vertices is limited if so
16518 // desired. we need this code here since at least in 1d we don't
16519 // call the dimension-independent version of
16520 // prepare_coarsening_and_refinement function. in 2d and 3d, having
16521 // this hunk here makes our lives a bit easier as well as it takes
16522 // care of these cases earlier than it would otherwise happen.
16523 //
16524 // the main difference to the code in p_c_and_r is that here we
16525 // absolutely have to make sure that we get things right, i.e. that
16526 // in particular we set flags right if
16527 // limit_level_difference_at_vertices is set. to do so we iterate
16528 // until the flags don't change any more
16529 auto previous_coarsen_flags = internal::extract_raw_coarsen_flags(levels);
16530
16531 bool continue_iterating = true;
16532
16533 do
16534 {
16535 if (smooth_grid & limit_level_difference_at_vertices)
16536 {
16537 Assert(!anisotropic_refinement,
16538 ExcMessage("In case of anisotropic refinement the "
16539 "limit_level_difference_at_vertices flag for "
16540 "mesh smoothing must not be set!"));
16541
16542 // store highest level one of the cells adjacent to a vertex
16543 // belongs to
16544 std::vector<int> vertex_level(vertices.size(), 0);
16545 for (const auto &cell : this->active_cell_iterators())
16546 {
16547 if (cell->refine_flag_set())
16548 for (const unsigned int vertex : cell->vertex_indices())
16549 vertex_level[cell->vertex_index(vertex)] =
16550 std::max(vertex_level[cell->vertex_index(vertex)],
16551 cell->level() + 1);
16552 else if (!cell->coarsen_flag_set())
16553 for (const unsigned int vertex : cell->vertex_indices())
16554 vertex_level[cell->vertex_index(vertex)] =
16555 std::max(vertex_level[cell->vertex_index(vertex)],
16556 cell->level());
16557 else
16558 {
16559 // if coarsen flag is set then tentatively assume
16560 // that the cell will be coarsened. this isn't
16561 // always true (the coarsen flag could be removed
16562 // again) and so we may make an error here. we try
16563 // to correct this by iterating over the entire
16564 // process until we are converged
16565 Assert(cell->coarsen_flag_set(), ExcInternalError());
16566 for (const unsigned int vertex : cell->vertex_indices())
16567 vertex_level[cell->vertex_index(vertex)] =
16568 std::max(vertex_level[cell->vertex_index(vertex)],
16569 cell->level() - 1);
16570 }
16571 }
16572
16573
16574 // loop over all cells in reverse order. do so because we
16575 // can then update the vertex levels on the adjacent
16576 // vertices and maybe already flag additional cells in this
16577 // loop
16578 //
16579 // note that not only may we have to add additional
16580 // refinement flags, but we will also have to remove
16581 // coarsening flags on cells adjacent to vertices that will
16582 // see refinement
16583 active_cell_iterator endc = end();
16584 for (active_cell_iterator cell = last_active(); cell != endc; --cell)
16585 if (cell->refine_flag_set() == false)
16586 {
16587 for (const unsigned int vertex : cell->vertex_indices())
16588 if (vertex_level[cell->vertex_index(vertex)] >=
16589 cell->level() + 1)
16590 {
16591 // remove coarsen flag...
16592 cell->clear_coarsen_flag();
16593
16594 // ...and if necessary also refine the current
16595 // cell, at the same time updating the level
16596 // information about vertices
16597 if (vertex_level[cell->vertex_index(vertex)] >
16598 cell->level() + 1)
16599 {
16600 cell->set_refine_flag();
16601
16602 for (const unsigned int v : cell->vertex_indices())
16603 vertex_level[cell->vertex_index(v)] =
16604 std::max(vertex_level[cell->vertex_index(v)],
16605 cell->level() + 1);
16606 }
16607
16608 // continue and see whether we may, for example,
16609 // go into the inner 'if' above based on a
16610 // different vertex
16611 }
16612 }
16613 }
16614
16615 // loop over all cells and remove the coarsen flags for those cells that
16616 // have sister cells not marked for coarsening, or where some neighbors
16617 // are more refined.
16618
16619 // Coarsen flags of cells with no mother cell, i.e. on the
16620 // coarsest level, are deleted explicitly.
16621 for (const auto &acell : this->active_cell_iterators_on_level(0))
16622 acell->clear_coarsen_flag();
16623
16624 const cell_iterator endc = end();
16625 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
16626 {
16627 // nothing to do if we are already on the finest level
16628 if (cell->is_active())
16629 continue;
16630
16631 const unsigned int n_children = cell->n_children();
16632 unsigned int flagged_children = 0;
16633 for (unsigned int child = 0; child < n_children; ++child)
16634 {
16635 const auto child_cell = cell->child(child);
16636 if (child_cell->is_active() && child_cell->coarsen_flag_set())
16637 {
16638 ++flagged_children;
16639 // clear flag since we don't need it anymore
16640 child_cell->clear_coarsen_flag();
16641 }
16642 }
16643
16644 // flag the children for coarsening again if all children were
16645 // flagged and if the policy allows it
16646 if (flagged_children == n_children &&
16647 this->policy->coarsening_allowed(cell))
16648 for (unsigned int c = 0; c < n_children; ++c)
16649 {
16650 Assert(cell->child(c)->refine_flag_set() == false,
16652
16653 cell->child(c)->set_coarsen_flag();
16654 }
16655 }
16656
16657 // now see if anything has changed in the last iteration of this
16658 // function
16659 auto current_coarsen_flags = internal::extract_raw_coarsen_flags(levels);
16660
16661 continue_iterating = (current_coarsen_flags != previous_coarsen_flags);
16662 previous_coarsen_flags.swap(current_coarsen_flags);
16663 }
16664 while (continue_iterating == true);
16665}
16666
16667#endif
16668
16669// TODO: merge the following 3 functions since they are the same
16670template <>
16671bool
16673{
16674 // save the flags to determine whether something was changed in the
16675 // course of this function
16676 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
16677
16678 // do nothing in 1d, except setting the coarsening flags correctly
16679 fix_coarsen_flags();
16680
16681 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
16682
16683 return (flags_before != flags_after);
16684}
16685
16686
16687
16688template <>
16689bool
16691{
16692 // save the flags to determine whether something was changed in the
16693 // course of this function
16694 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
16695
16696 // do nothing in 1d, except setting the coarsening flags correctly
16697 fix_coarsen_flags();
16698
16699 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
16700
16701 return (flags_before != flags_after);
16702}
16703
16704
16705
16706template <>
16707bool
16709{
16710 // save the flags to determine whether something was changed in the
16711 // course of this function
16712 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
16713
16714 // do nothing in 1d, except setting the coarsening flags correctly
16715 fix_coarsen_flags();
16716
16717 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
16718
16719 return (flags_before != flags_after);
16720}
16721
16722
16723
16724namespace
16725{
16726 // check if the given @param cell marked for coarsening would
16727 // produce an unrefined island. To break up long chains of these
16728 // cells we recursively check our neighbors in case we change this
16729 // cell. This reduces the number of outer iterations dramatically.
16730 template <int dim, int spacedim>
16731 void
16732 possibly_do_not_produce_unrefined_islands(
16734 {
16735 Assert(cell->has_children(), ExcInternalError());
16736
16737 unsigned int n_neighbors = 0;
16738 // count all neighbors that will be refined along the face of our
16739 // cell after the next step
16740 unsigned int count = 0;
16741 for (const unsigned int n : GeometryInfo<dim>::face_indices())
16742 {
16743 const typename Triangulation<dim, spacedim>::cell_iterator neighbor =
16744 cell->neighbor(n);
16745 if (neighbor.state() == IteratorState::valid)
16746 {
16747 ++n_neighbors;
16748 if (face_will_be_refined_by_neighbor(cell, n))
16749 ++count;
16750 }
16751 }
16752 // clear coarsen flags if either all existing neighbors will be
16753 // refined or all but one will be and the cell is in the interior
16754 // of the domain
16755 if (count == n_neighbors ||
16756 (count >= n_neighbors - 1 &&
16757 n_neighbors == GeometryInfo<dim>::faces_per_cell))
16758 {
16759 for (unsigned int c = 0; c < cell->n_children(); ++c)
16760 cell->child(c)->clear_coarsen_flag();
16761
16762 for (const unsigned int face : GeometryInfo<dim>::face_indices())
16763 if (!cell->at_boundary(face) &&
16764 (!cell->neighbor(face)->is_active()) &&
16765 (cell_will_be_coarsened(cell->neighbor(face))))
16766 possibly_do_not_produce_unrefined_islands<dim, spacedim>(
16767 cell->neighbor(face));
16768 }
16769 }
16770
16771
16772 // see if the current cell needs to be refined to avoid unrefined
16773 // islands.
16774 //
16775 // there are sometimes chains of cells that induce refinement of
16776 // each other. to avoid running the loop in
16777 // prepare_coarsening_and_refinement over and over again for each
16778 // one of them, at least for the isotropic refinement case we seek
16779 // to flag neighboring elements as well as necessary. this takes
16780 // care of (slightly pathological) cases like
16781 // deal.II/mesh_smoothing_03
16782 template <int dim, int spacedim>
16783 void
16784 possibly_refine_unrefined_island(
16786 const bool allow_anisotropic_smoothing)
16787 {
16788 Assert(cell->is_active(), ExcInternalError());
16789
16790 if constexpr (running_in_debug_mode())
16791 {
16792 // If this is not a parallel::distributed::Triangulation, then we really
16793 // should only get here if the cell is marked for refinement:
16794 if (dynamic_cast<
16796 &cell->get_triangulation()) == nullptr)
16797 Assert(cell->refine_flag_set() == false, ExcInternalError());
16798 else
16799 // But if this is a p::d::Triangulation, then we don't have that
16800 // much control and we can get here because mesh smoothing is
16801 // requested but can not be honored because p4est controls
16802 // what gets refined. In that case, we can at least provide
16803 // a better error message.
16804 Assert(
16805 cell->refine_flag_set() == false,
16806 ExcMessage(
16807 "The triangulation is trying to avoid unrefined islands "
16808 "during mesh refinement/coarsening, as you had requested "
16809 " by passing the appropriate 'smoothing flags' to the "
16810 "constructor of the triangulation. However, for objects "
16811 "of type parallel::distributed::Triangulation, control "
16812 "over which cells get refined rests with p4est, not the "
16813 "deal.II triangulation, and consequently it is not "
16814 "always possible to avoid unrefined islands in the mesh. "
16815 "Please remove the constructor argument to the triangulation "
16816 "object that requests mesh smoothing."));
16817 }
16818
16819 // now we provide two algorithms. the first one is the standard
16820 // one, coming from the time, where only isotropic refinement was
16821 // possible. it simply counts the neighbors that are or will be
16822 // refined and compares to the number of other ones. the second
16823 // one does this check independently for each direction: if all
16824 // neighbors in one direction (normally two, at the boundary only
16825 // one) are refined, the current cell is flagged to be refined in
16826 // an according direction.
16827
16828 if (allow_anisotropic_smoothing == false)
16829 {
16830 // use first algorithm
16831 unsigned int refined_neighbors = 0, unrefined_neighbors = 0;
16832 for (const unsigned int face : GeometryInfo<dim>::face_indices())
16833 if (!cell->at_boundary(face))
16834 {
16835 if (face_will_be_refined_by_neighbor(cell, face))
16836 ++refined_neighbors;
16837 else
16838 ++unrefined_neighbors;
16839 }
16840
16841 if (unrefined_neighbors < refined_neighbors)
16842 {
16843 cell->clear_coarsen_flag();
16844 cell->set_refine_flag();
16845
16846 // ok, so now we have flagged this cell. if we know that
16847 // there were any unrefined neighbors at all, see if any
16848 // of those will have to be refined as well
16849 if (unrefined_neighbors > 0)
16850 for (const unsigned int face : GeometryInfo<dim>::face_indices())
16851 if (!cell->at_boundary(face) &&
16852 (face_will_be_refined_by_neighbor(cell, face) == false) &&
16853 (cell->neighbor(face)->has_children() == false) &&
16854 (cell->neighbor(face)->refine_flag_set() == false))
16855 possibly_refine_unrefined_island<dim, spacedim>(
16856 cell->neighbor(face), allow_anisotropic_smoothing);
16857 }
16858 }
16859 else
16860 {
16861 // variable to store the cell refine case needed to fulfill
16862 // all smoothing requirements
16863 RefinementCase<dim> smoothing_cell_refinement_case =
16865
16866 // use second algorithm, do the check individually for each
16867 // direction
16868 for (unsigned int face_pair = 0;
16869 face_pair < GeometryInfo<dim>::faces_per_cell / 2;
16870 ++face_pair)
16871 {
16872 // variable to store the cell refine case needed to refine
16873 // at the current face pair in the same way as the
16874 // neighbors do...
16875 RefinementCase<dim> directional_cell_refinement_case =
16877
16878 for (unsigned int face_index = 0; face_index < 2; ++face_index)
16879 {
16880 unsigned int face = 2 * face_pair + face_index;
16881 // variable to store the refine case (to come) of the
16882 // face under consideration
16883 RefinementCase<dim - 1> expected_face_ref_case =
16884 RefinementCase<dim - 1>::no_refinement;
16885
16886 if (cell->neighbor(face).state() == IteratorState::valid)
16887 face_will_be_refined_by_neighbor<dim, spacedim>(
16888 cell, face, expected_face_ref_case);
16889 // now extract which refine case would be necessary to
16890 // achieve the same face refinement. set the
16891 // intersection with other requirements for the same
16892 // direction.
16893
16894 // note: using the intersection is not an obvious
16895 // decision, we could also argue that it is more
16896 // natural to use the union. however, intersection is
16897 // the less aggressive tactic and favours a smaller
16898 // number of refined cells over an intensive
16899 // smoothing. this way we try not to lose too much of
16900 // the effort we put in anisotropic refinement
16901 // indicators due to overly aggressive smoothing...
16902 directional_cell_refinement_case =
16903 (directional_cell_refinement_case &
16906 expected_face_ref_case,
16907 face,
16908 cell->face_orientation(face),
16909 cell->face_flip(face),
16910 cell->face_rotation(face)));
16911 } // for both face indices
16912 // if both requirements sum up to something useful, add
16913 // this to the refine case for smoothing. note: if
16914 // directional_cell_refinement_case is isotropic still,
16915 // then something went wrong...
16916 Assert(directional_cell_refinement_case <
16919 smoothing_cell_refinement_case =
16920 smoothing_cell_refinement_case | directional_cell_refinement_case;
16921 } // for all face_pairs
16922 // no we collected contributions from all directions. combine
16923 // the new flags with the existing refine case, but only if
16924 // smoothing is required
16925 if (smoothing_cell_refinement_case)
16926 {
16927 cell->clear_coarsen_flag();
16928 cell->set_refine_flag(cell->refine_flag_set() |
16929 smoothing_cell_refinement_case);
16930 }
16931 }
16932 }
16933} // namespace
16934
16935#ifndef DOXYGEN
16936template <int dim, int spacedim>
16939{
16940 // save the flags to determine whether something was changed in the
16941 // course of this function
16942 const auto coarsen_flags_before = internal::extract_raw_coarsen_flags(levels);
16943 const auto refine_flags_before = internal::extract_raw_refine_flags(levels);
16944
16945 // save the flags at the outset of each loop. we do so in order to
16946 // find out whether something was changed in the present loop, in
16947 // which case we would have to re-run the loop. the other
16948 // possibility to find this out would be to set a flag
16949 // @p{something_changed} to true each time we change something.
16950 // however, sometimes one change in one of the parts of the loop is
16951 // undone by another one, so we might end up in an endless loop. we
16952 // could be tempted to break this loop at an arbitrary number of
16953 // runs, but that would not be a clean solution, since we would
16954 // either have to 1/ break the loop too early, in which case the
16955 // promise that a second call to this function immediately after the
16956 // first one does not change anything, would be broken, or 2/ we do
16957 // as many loops as there are levels. we know that information is
16958 // transported over one level in each run of the loop, so this is
16959 // enough. Unfortunately, each loop is rather expensive, so we chose
16960 // the way presented here
16961 auto coarsen_flags_before_loop = coarsen_flags_before;
16962 auto refine_flags_before_loop = refine_flags_before;
16963
16964 // now for what is done in each loop: we have to fulfill several
16965 // tasks at the same time, namely several mesh smoothing algorithms
16966 // and mesh regularization, by which we mean that the next mesh
16967 // fulfills several requirements such as no double refinement at
16968 // each face or line, etc.
16969 //
16970 // since doing these things at once seems almost impossible (in the
16971 // first year of this library, they were done in two functions, one
16972 // for refinement and one for coarsening, and most things within
16973 // these were done at once, so the code was rather impossible to
16974 // join into this, only, function), we do them one after each
16975 // other. the order in which we do them is such that the important
16976 // tasks, namely regularization, are done last and the least
16977 // important things are done the first. the following order is
16978 // chosen:
16979 //
16980 // 0/ Only if coarsest_level_1 or patch_level_1 is set: clear all
16981 // coarsen flags on level 1 to avoid level 0 cells being created
16982 // by coarsening. As coarsen flags will never be added, this can
16983 // be done once and for all before the actual loop starts.
16984 //
16985 // 1/ do not coarsen a cell if 'most of the neighbors' will be
16986 // refined after the step. This is to prevent occurrence of
16987 // unrefined islands.
16988 //
16989 // 2/ eliminate refined islands in the interior and at the
16990 // boundary. since they don't do much harm besides increasing the
16991 // number of degrees of freedom, doing this has a rather low
16992 // priority.
16993 //
16994 // 3/ limit the level difference of neighboring cells at each
16995 // vertex.
16996 //
16997 // 4/ eliminate unrefined islands. this has higher priority since
16998 // this diminishes the approximation properties not only of the
16999 // unrefined island, but also of the surrounding patch.
17000 //
17001 // 5/ ensure patch level 1. Then the triangulation consists of
17002 // patches, i.e. of cells that are refined once. It follows that
17003 // if at least one of the children of a cell is or will be
17004 // refined than all children need to be refined. This step only
17005 // sets refinement flags and does not set coarsening flags. If
17006 // the patch_level_1 flag is set, then
17007 // eliminate_unrefined_islands, eliminate_refined_inner_islands
17008 // and eliminate_refined_boundary_islands will be fulfilled
17009 // automatically and do not need to be enforced separately.
17010 //
17011 // 6/ take care of the requirement that no double refinement is done
17012 // at each face
17013 //
17014 // 7/ take care that no double refinement is done at each line in 3d
17015 // or higher dimensions.
17016 //
17017 // 8/ make sure that all children of each cell are either flagged
17018 // for coarsening or none of the children is
17019 //
17020 // For some of these steps, it is known that they interact. Namely,
17021 // it is not possible to guarantee that after step 6 another step 5
17022 // would have no effect; the same holds for the opposite order and
17023 // also when taking into account step 7. however, it is important to
17024 // guarantee that step five or six do not undo something that step 5
17025 // did, and step 7 not something of step 6, otherwise the
17026 // requirements will not be satisfied even if the loop
17027 // terminates. this is accomplished by the fact that steps 5 and 6
17028 // only *add* refinement flags and delete coarsening flags
17029 // (therefore, step 6 can't undo something that step 4 already did),
17030 // and step 7 only deletes coarsening flags, never adds some. step 7
17031 // needs also take care that it won't tag cells for refinement for
17032 // which some neighbors are more refined or will be refined.
17033
17034 //------------------------------------
17035 // STEP 0:
17036 // Only if coarsest_level_1 or patch_level_1 is set: clear all
17037 // coarsen flags on level 1 to avoid level 0 cells being created
17038 // by coarsening.
17039 if (((smooth_grid & coarsest_level_1) || (smooth_grid & patch_level_1)) &&
17040 n_levels() >= 2)
17041 {
17042 for (const auto &cell : active_cell_iterators_on_level(1))
17043 cell->clear_coarsen_flag();
17044 }
17045
17046 bool mesh_changed_in_this_loop = false;
17047 do
17048 {
17049 //------------------------------------
17050 // STEP 1:
17051 // do not coarsen a cell if 'most of the neighbors' will be
17052 // refined after the step. This is to prevent the occurrence
17053 // of unrefined islands. If patch_level_1 is set, this will
17054 // be automatically fulfilled.
17055 if (smooth_grid & do_not_produce_unrefined_islands &&
17056 !(smooth_grid & patch_level_1))
17057 {
17058 for (const auto &cell : cell_iterators())
17059 {
17060 // only do something if this
17061 // cell will be coarsened
17062 if (!cell->is_active() && cell_will_be_coarsened(cell))
17063 possibly_do_not_produce_unrefined_islands<dim, spacedim>(cell);
17064 }
17065 }
17066
17067
17068 //------------------------------------
17069 // STEP 2:
17070 // eliminate refined islands in the interior and at the
17071 // boundary. since they don't do much harm besides increasing
17072 // the number of degrees of freedom, doing this has a rather
17073 // low priority. If patch_level_1 is set, this will be
17074 // automatically fulfilled.
17075 //
17076 // there is one corner case to consider: if this is a
17077 // distributed triangulation, there may be refined islands on
17078 // the boundary of which we own only part (e.g. a single cell
17079 // in the corner of a domain). the rest of the island is
17080 // ghost cells and it *looks* like the area around it
17081 // (artificial cells) are coarser but this is only because
17082 // they may actually be equally fine on other
17083 // processors. it's hard to detect this case but we can do
17084 // the following: only set coarsen flags to remove this
17085 // refined island if all cells we want to set flags on are
17086 // locally owned
17087 if (smooth_grid & (eliminate_refined_inner_islands |
17088 eliminate_refined_boundary_islands) &&
17089 !(smooth_grid & patch_level_1))
17090 {
17091 for (const auto &cell : cell_iterators())
17092 if (!cell->is_active() ||
17093 (cell->is_active() && cell->refine_flag_set() &&
17094 cell->is_locally_owned()))
17095 {
17096 // check whether all children are active, i.e. not
17097 // refined themselves. This is a precondition that the
17098 // children may be coarsened away. If the cell is only
17099 // flagged for refinement, then all future children
17100 // will be active
17101 bool all_children_active = true;
17102 if (!cell->is_active())
17103 for (unsigned int c = 0; c < cell->n_children(); ++c)
17104 if (!cell->child(c)->is_active() ||
17105 cell->child(c)->is_ghost() ||
17106 cell->child(c)->is_artificial())
17107 {
17108 all_children_active = false;
17109 break;
17110 }
17111
17112 if (all_children_active)
17113 {
17114 // count number of refined and unrefined neighbors
17115 // of cell. neighbors on lower levels are counted
17116 // as unrefined since they can only get to the
17117 // same level as this cell by the next refinement
17118 // cycle
17119 unsigned int unrefined_neighbors = 0, total_neighbors = 0;
17120
17121 // Keep track if this cell is at a periodic
17122 // boundary or not. TODO: We do not currently run
17123 // the algorithm for inner islands at a periodic
17124 // boundary (remains to be implemented), but we
17125 // also don't want to consider them
17126 // boundary_island cells as this can interfere
17127 // with 2:1 refinement across periodic faces.
17128 // Instead: just ignore those cells for this
17129 // smoothing operation below.
17130 bool at_periodic_boundary = false;
17131
17132 for (const unsigned int n : cell->face_indices())
17133 {
17134 const cell_iterator neighbor = cell->neighbor(n);
17135 if (neighbor.state() == IteratorState::valid)
17136 {
17137 ++total_neighbors;
17138
17139 if (!face_will_be_refined_by_neighbor(cell, n))
17140 ++unrefined_neighbors;
17141 }
17142 else if (cell->has_periodic_neighbor(n))
17143 {
17144 ++total_neighbors;
17145 at_periodic_boundary = true;
17146 }
17147 }
17148
17149 // if all neighbors unrefined: mark this cell for
17150 // coarsening or don't refine if marked for that
17151 //
17152 // also do the distinction between the two
17153 // versions of the eliminate_refined_*_islands
17154 // flag
17155 //
17156 // the last check is whether there are any
17157 // neighbors at all. if not so, then we are (e.g.)
17158 // on the coarsest grid with one cell, for which,
17159 // of course, we do not remove the refine flag.
17160 if ((unrefined_neighbors == total_neighbors) &&
17161 ((!cell->at_boundary() &&
17162 (smooth_grid & eliminate_refined_inner_islands)) ||
17163 (cell->at_boundary() && !at_periodic_boundary &&
17164 (smooth_grid &
17165 eliminate_refined_boundary_islands))) &&
17166 (total_neighbors != 0))
17167 {
17168 if (!cell->is_active())
17169 for (unsigned int c = 0; c < cell->n_children(); ++c)
17170 {
17171 cell->child(c)->clear_refine_flag();
17172 cell->child(c)->set_coarsen_flag();
17173 }
17174 else
17175 cell->clear_refine_flag();
17176 }
17177 }
17178 }
17179 }
17180
17181 //------------------------------------
17182 // STEP 3:
17183 // limit the level difference of neighboring cells at each
17184 // vertex.
17185 //
17186 // in case of anisotropic refinement this does not make
17187 // sense. as soon as one cell is anisotropically refined, an
17188 // Assertion is thrown. therefore we can ignore this problem
17189 // later on
17190 if (smooth_grid & limit_level_difference_at_vertices)
17191 {
17192 Assert(!anisotropic_refinement,
17193 ExcMessage("In case of anisotropic refinement the "
17194 "limit_level_difference_at_vertices flag for "
17195 "mesh smoothing must not be set!"));
17196
17197 // store highest level one of the cells adjacent to a vertex
17198 // belongs to
17199 std::vector<int> vertex_level(vertices.size(), 0);
17200 for (const auto &cell : active_cell_iterators())
17201 {
17202 if (cell->refine_flag_set())
17203 for (const unsigned int vertex : cell->vertex_indices())
17204 vertex_level[cell->vertex_index(vertex)] =
17205 std::max(vertex_level[cell->vertex_index(vertex)],
17206 cell->level() + 1);
17207 else if (!cell->coarsen_flag_set())
17208 for (const unsigned int vertex : cell->vertex_indices())
17209 vertex_level[cell->vertex_index(vertex)] =
17210 std::max(vertex_level[cell->vertex_index(vertex)],
17211 cell->level());
17212 else
17213 {
17214 // if coarsen flag is set then tentatively assume
17215 // that the cell will be coarsened. this isn't
17216 // always true (the coarsen flag could be removed
17217 // again) and so we may make an error here
17218 Assert(cell->coarsen_flag_set(), ExcInternalError());
17219 for (const unsigned int vertex : cell->vertex_indices())
17220 vertex_level[cell->vertex_index(vertex)] =
17221 std::max(vertex_level[cell->vertex_index(vertex)],
17222 cell->level() - 1);
17223 }
17224 }
17225
17226
17227 // loop over all cells in reverse order. do so because we
17228 // can then update the vertex levels on the adjacent
17229 // vertices and maybe already flag additional cells in this
17230 // loop
17231 //
17232 // note that not only may we have to add additional
17233 // refinement flags, but we will also have to remove
17234 // coarsening flags on cells adjacent to vertices that will
17235 // see refinement
17236 for (active_cell_iterator cell = last_active(); cell != end(); --cell)
17237 if (cell->refine_flag_set() == false)
17238 {
17239 for (const unsigned int vertex : cell->vertex_indices())
17240 if (vertex_level[cell->vertex_index(vertex)] >=
17241 cell->level() + 1)
17242 {
17243 // remove coarsen flag...
17244 cell->clear_coarsen_flag();
17245
17246 // ...and if necessary also refine the current
17247 // cell, at the same time updating the level
17248 // information about vertices
17249 if (vertex_level[cell->vertex_index(vertex)] >
17250 cell->level() + 1)
17251 {
17252 cell->set_refine_flag();
17253
17254 for (const unsigned int v : cell->vertex_indices())
17255 vertex_level[cell->vertex_index(v)] =
17256 std::max(vertex_level[cell->vertex_index(v)],
17257 cell->level() + 1);
17258 }
17259
17260 // continue and see whether we may, for example,
17261 // go into the inner'if'
17262 // above based on a
17263 // different vertex
17264 }
17265 }
17266 }
17267
17268 //-----------------------------------
17269 // STEP 4:
17270 // eliminate unrefined islands. this has higher priority
17271 // since this diminishes the approximation properties not
17272 // only of the unrefined island, but also of the surrounding
17273 // patch.
17274 //
17275 // do the loop from finest to coarsest cells since we may
17276 // trigger a cascade by marking cells for refinement which
17277 // may trigger more cells further down below
17278 if (smooth_grid & eliminate_unrefined_islands)
17279 {
17280 for (active_cell_iterator cell = last_active(); cell != end(); --cell)
17281 // only do something if cell is not already flagged for
17282 // (isotropic) refinement
17283 if (cell->refine_flag_set() !=
17285 possibly_refine_unrefined_island<dim, spacedim>(
17286 cell, (smooth_grid & allow_anisotropic_smoothing) != 0);
17287 }
17288
17289 //-------------------------------
17290 // STEP 5:
17291 // ensure patch level 1.
17292 //
17293 // Introduce some terminology:
17294 // - a cell that is refined
17295 // once is a patch of
17296 // level 1 simply called patch.
17297 // - a cell that is globally
17298 // refined twice is called
17299 // a patch of level 2.
17300 // - patch level n says that
17301 // the triangulation consists
17302 // of patches of level n.
17303 // This makes sense only
17304 // if the grid is already at
17305 // least n times globally
17306 // refined.
17307 //
17308 // E.g. from patch level 1 follows: if at least one of the
17309 // children of a cell is or will be refined than enforce all
17310 // children to be refined.
17311
17312 // This step 4 only sets refinement flags and does not set
17313 // coarsening flags.
17314 if (smooth_grid & patch_level_1)
17315 {
17316 // An important assumption (A) is that before calling this
17317 // function the grid was already of patch level 1.
17318
17319 // loop over all cells whose children are all active. (By
17320 // assumption (A) either all or none of the children are
17321 // active). If the refine flag of at least one of the
17322 // children is set then set_refine_flag and
17323 // clear_coarsen_flag of all children.
17324 for (const auto &cell : cell_iterators())
17325 if (!cell->is_active())
17326 {
17327 // ensure the invariant. we can then check whether all
17328 // of its children are further refined or not by
17329 // simply looking at the first child
17330 Assert(cell_is_patch_level_1(cell), ExcInternalError());
17331 if (cell->child(0)->has_children() == true)
17332 continue;
17333
17334 // cell is found to be a patch. combine the refine
17335 // cases of all children
17336 RefinementCase<dim> combined_ref_case =
17338 for (unsigned int i = 0; i < cell->n_children(); ++i)
17339 combined_ref_case =
17340 combined_ref_case | cell->child(i)->refine_flag_set();
17341 if (combined_ref_case != RefinementCase<dim>::no_refinement)
17342 for (unsigned int i = 0; i < cell->n_children(); ++i)
17343 {
17344 cell_iterator child = cell->child(i);
17345
17346 child->clear_coarsen_flag();
17347 child->set_refine_flag(combined_ref_case);
17348 }
17349 }
17350
17351 // The code above dealt with the case where we may get a
17352 // non-patch_level_1 mesh from refinement. Now also deal
17353 // with the case where we could get such a mesh by
17354 // coarsening. Coarsen the children (and remove the
17355 // grandchildren) only if all cell->grandchild(i)
17356 // ->coarsen_flag_set() are set.
17357 //
17358 // for a case where this is a bit tricky, take a look at the
17359 // mesh_smoothing_0[12] testcases
17360 for (const auto &cell : cell_iterators())
17361 {
17362 // check if this cell has active grandchildren. note
17363 // that we know that it is patch_level_1, i.e. if one of
17364 // its children is active then so are all, and it isn't
17365 // going to have any grandchildren at all:
17366 if (cell->is_active() || cell->child(0)->is_active())
17367 continue;
17368
17369 // cell is not active, and so are none of its
17370 // children. check the grandchildren. note that the
17371 // children are also patch_level_1, and so we only ever
17372 // need to check their first child
17373 const unsigned int n_children = cell->n_children();
17374 bool has_active_grandchildren = false;
17375
17376 for (unsigned int i = 0; i < n_children; ++i)
17377 if (cell->child(i)->child(0)->is_active())
17378 {
17379 has_active_grandchildren = true;
17380 break;
17381 }
17382
17383 if (has_active_grandchildren == false)
17384 continue;
17385
17386
17387 // ok, there are active grandchildren. see if either all
17388 // or none of them are flagged for coarsening
17389 unsigned int n_grandchildren = 0;
17390
17391 // count all coarsen flags of the grandchildren.
17392 unsigned int n_coarsen_flags = 0;
17393
17394 // cell is not a patch (of level 1) as it has a
17395 // grandchild. Is cell a patch of level 2?? Therefore:
17396 // find out whether all cell->child(i) are patches
17397 for (unsigned int c = 0; c < n_children; ++c)
17398 {
17399 // get at the child. by assumption (A), and the
17400 // check by which we got here, the child is not
17401 // active
17402 cell_iterator child = cell->child(c);
17403
17404 const unsigned int nn_children = child->n_children();
17405 n_grandchildren += nn_children;
17406
17407 // if child is found to be a patch of active cells
17408 // itself, then add up how many of its children are
17409 // supposed to be coarsened
17410 if (child->child(0)->is_active())
17411 for (unsigned int cc = 0; cc < nn_children; ++cc)
17412 if (child->child(cc)->coarsen_flag_set())
17413 ++n_coarsen_flags;
17414 }
17415
17416 // if not all grandchildren are supposed to be coarsened
17417 // (e.g. because some simply don't have the flag set, or
17418 // because they are not active and therefore cannot
17419 // carry the flag), then remove the coarsen flag from
17420 // all of the active grandchildren. note that there may
17421 // be coarsen flags on the grandgrandchildren -- we
17422 // don't clear them here, but we'll get to them in later
17423 // iterations if necessary
17424 //
17425 // there is nothing we have to do if no coarsen flags
17426 // have been set at all
17427 if ((n_coarsen_flags != n_grandchildren) && (n_coarsen_flags > 0))
17428 for (unsigned int c = 0; c < n_children; ++c)
17429 {
17430 const cell_iterator child = cell->child(c);
17431 if (child->child(0)->is_active())
17432 for (unsigned int cc = 0; cc < child->n_children(); ++cc)
17433 child->child(cc)->clear_coarsen_flag();
17434 }
17435 }
17436 }
17437
17438 //--------------------------------
17439 //
17440 // at the boundary we could end up with cells with negative
17441 // volume or at least with a part, that is negative, if the
17442 // cell is refined anisotropically. we have to check, whether
17443 // that can happen
17444 this->policy->prevent_distorted_boundary_cells(*this);
17445
17446 //-------------------------------
17447 // STEP 6:
17448 // take care of the requirement that no
17449 // double refinement is done at each face
17450 //
17451 // in case of anisotropic refinement it is only likely, but
17452 // not sure, that the cells, which are more refined along a
17453 // certain face common to two cells are on a higher
17454 // level. therefore we cannot be sure, that the requirement
17455 // of no double refinement is fulfilled after a single pass
17456 // of the following actions. We could just wait for the next
17457 // global loop. when this function terminates, the
17458 // requirement will be fulfilled. However, it might be faster
17459 // to insert an inner loop here.
17460 bool changed = true;
17461 while (changed)
17462 {
17463 changed = false;
17464 active_cell_iterator cell = last_active(), endc = end();
17465
17466 for (; cell != endc; --cell)
17467 if (cell->refine_flag_set())
17468 {
17469 // loop over neighbors of cell
17470 for (const auto i : cell->face_indices())
17471 {
17472 // only do something if the face is not at the
17473 // boundary and if the face will be refined with
17474 // the RefineCase currently flagged for
17475 const bool has_periodic_neighbor =
17476 cell->has_periodic_neighbor(i);
17477 const bool has_neighbor_or_periodic_neighbor =
17478 !cell->at_boundary(i) || has_periodic_neighbor;
17479 if (has_neighbor_or_periodic_neighbor &&
17481 cell->refine_flag_set(), i) !=
17483 {
17484 // 1) if the neighbor has children: nothing to
17485 // worry about. 2) if the neighbor is active
17486 // and a coarser one, ensure, that its
17487 // refine_flag is set 3) if the neighbor is
17488 // active and as refined along the face as our
17489 // current cell, make sure, that no
17490 // coarsen_flag is set. if we remove the
17491 // coarsen flag of our neighbor,
17492 // fix_coarsen_flags() makes sure, that the
17493 // mother cell will not be coarsened
17494 if (cell->neighbor_or_periodic_neighbor(i)->is_active())
17495 {
17496 if ((!has_periodic_neighbor &&
17497 cell->neighbor_is_coarser(i)) ||
17498 (has_periodic_neighbor &&
17499 cell->periodic_neighbor_is_coarser(i)))
17500 {
17501 if (cell->neighbor_or_periodic_neighbor(i)
17502 ->coarsen_flag_set())
17503 cell->neighbor_or_periodic_neighbor(i)
17504 ->clear_coarsen_flag();
17505 // we'll set the refine flag for this
17506 // neighbor below. we note, that we
17507 // have changed something by setting
17508 // the changed flag to true. We do not
17509 // need to do so, if we just removed
17510 // the coarsen flag, as the changed
17511 // flag only indicates the need to
17512 // re-run the inner loop. however, we
17513 // only loop over cells flagged for
17514 // refinement here, so nothing to
17515 // worry about if we remove coarsen
17516 // flags
17517
17518 if (dim == 2)
17519 {
17520 if (smooth_grid &
17521 allow_anisotropic_smoothing)
17522 changed =
17523 has_periodic_neighbor ?
17524 cell->periodic_neighbor(i)
17525 ->flag_for_face_refinement(
17526 cell
17527 ->periodic_neighbor_of_coarser_periodic_neighbor(
17528 i)
17529 .first,
17531 cell->neighbor(i)
17532 ->flag_for_face_refinement(
17533 cell
17534 ->neighbor_of_coarser_neighbor(
17535 i)
17536 .first,
17538 else
17539 {
17540 if (!cell
17541 ->neighbor_or_periodic_neighbor(
17542 i)
17543 ->refine_flag_set())
17544 changed = true;
17545 cell->neighbor_or_periodic_neighbor(i)
17546 ->set_refine_flag();
17547 }
17548 }
17549 else // i.e. if (dim==3)
17550 {
17551 // ugly situations might arise here,
17552 // consider the following situation, which
17553 // shows neighboring cells at the common
17554 // face, where the upper right element is
17555 // coarser at the given face. Now the upper
17556 // child element of the lower left wants to
17557 // refine according to cut_z, such that
17558 // there is a 'horizontal' refinement of the
17559 // face marked with #####
17560 //
17561 // / /
17562 // / /
17563 // *---------------*
17564 // | |
17565 // | |
17566 // | |
17567 // | |
17568 // | |
17569 // | | /
17570 // | |/
17571 // *---------------*
17572 //
17573 //
17574 // *---------------*
17575 // /| /|
17576 // / | ##### / |
17577 // | |
17578 // *---------------*
17579 // /| /|
17580 // / | / |
17581 // | |
17582 // *---------------*
17583 // / /
17584 // / /
17585 //
17586 // this introduces too many hanging nodes
17587 // and the neighboring (coarser) cell (upper
17588 // right) has to be refined. If it is only
17589 // refined according to cut_z, then
17590 // everything is ok:
17591 //
17592 // / /
17593 // / /
17594 // *---------------*
17595 // | |
17596 // | | /
17597 // | |/
17598 // *---------------*
17599 // | |
17600 // | | /
17601 // | |/
17602 // *---------------*
17603 //
17604 //
17605 // *---------------*
17606 // /| /|
17607 // / *---------------*
17608 // /| /|
17609 // *---------------*
17610 // /| /|
17611 // / | / |
17612 // | |
17613 // *---------------*
17614 // / /
17615 // / /
17616 //
17617 // if however the cell wants to refine
17618 // itself in an other way, or if we disallow
17619 // anisotropic smoothing, then simply
17620 // refining the neighbor isotropically is
17621 // not going to work, since this introduces
17622 // a refinement of face ##### with both
17623 // cut_x and cut_y, which is not possible:
17624 //
17625 // / / /
17626 // / / /
17627 // *-------*-------*
17628 // | | |
17629 // | | | /
17630 // | | |/
17631 // *-------*-------*
17632 // | | |
17633 // | | | /
17634 // | | |/
17635 // *-------*-------*
17636 //
17637 //
17638 // *---------------*
17639 // /| /|
17640 // / *---------------*
17641 // /| /|
17642 // *---------------*
17643 // /| /|
17644 // / | / |
17645 // | |
17646 // *---------------*
17647 // / /
17648 // / /
17649 //
17650 // thus, in this case we also need to refine
17651 // our current cell in the new direction:
17652 //
17653 // / / /
17654 // / / /
17655 // *-------*-------*
17656 // | | |
17657 // | | | /
17658 // | | |/
17659 // *-------*-------*
17660 // | | |
17661 // | | | /
17662 // | | |/
17663 // *-------*-------*
17664 //
17665 //
17666 // *-------*-------*
17667 // /| /| /|
17668 // / *-------*-------*
17669 // /| /| /|
17670 // *-------*-------*
17671 // /| / /|
17672 // / | / |
17673 // | |
17674 // *---------------*
17675 // / /
17676 // / /
17677
17678 std::pair<unsigned int, unsigned int>
17679 nb_indices =
17680 has_periodic_neighbor ?
17681 cell
17682 ->periodic_neighbor_of_coarser_periodic_neighbor(
17683 i) :
17684 cell->neighbor_of_coarser_neighbor(i);
17685 unsigned int refined_along_x = 0,
17686 refined_along_y = 0,
17687 to_be_refined_along_x = 0,
17688 to_be_refined_along_y = 0;
17689
17690 const int this_face_index =
17691 cell->face_index(i);
17692
17693 // step 1: detect, along which axis the face
17694 // is currently refined
17695
17696 // first, we need an iterator pointing to
17697 // the parent face. This requires a slight
17698 // detour in case the neighbor is behind a
17699 // periodic face.
17700 const auto parent_face = [&]() {
17701 if (has_periodic_neighbor)
17702 {
17703 const auto neighbor =
17704 cell->periodic_neighbor(i);
17705 const auto parent_face_no =
17706 neighbor
17707 ->periodic_neighbor_of_periodic_neighbor(
17708 nb_indices.first);
17709 auto parent =
17710 neighbor->periodic_neighbor(
17711 nb_indices.first);
17712 return parent->face(parent_face_no);
17713 }
17714 else
17715 return cell->neighbor(i)->face(
17716 nb_indices.first);
17717 }();
17718
17719 if ((this_face_index ==
17720 parent_face->child_index(0)) ||
17721 (this_face_index ==
17722 parent_face->child_index(1)))
17723 {
17724 // this might be an
17725 // anisotropic child. get the
17726 // face refine case of the
17727 // neighbors face and count
17728 // refinements in x and y
17729 // direction.
17730 RefinementCase<dim - 1> frc =
17731 parent_face->refinement_case();
17733 ++refined_along_x;
17735 ++refined_along_y;
17736 }
17737 else
17738 // this has to be an isotropic
17739 // child
17740 {
17741 ++refined_along_x;
17742 ++refined_along_y;
17743 }
17744 // step 2: detect, along which axis the face
17745 // has to be refined given the current
17746 // refine flag
17747 RefinementCase<dim - 1> flagged_frc =
17749 cell->refine_flag_set(),
17750 i,
17751 cell->face_orientation(i),
17752 cell->face_flip(i),
17753 cell->face_rotation(i));
17754 if (flagged_frc &
17756 ++to_be_refined_along_x;
17757 if (flagged_frc &
17759 ++to_be_refined_along_y;
17760
17761 // step 3: set the refine flag of the
17762 // (coarser and active) neighbor.
17763 if ((smooth_grid &
17764 allow_anisotropic_smoothing) ||
17765 cell->neighbor_or_periodic_neighbor(i)
17766 ->refine_flag_set())
17767 {
17768 if (refined_along_x +
17769 to_be_refined_along_x >
17770 1)
17771 changed |=
17772 cell
17773 ->neighbor_or_periodic_neighbor(i)
17774 ->flag_for_face_refinement(
17775 nb_indices.first,
17776 RefinementCase<dim -
17777 1>::cut_axis(0));
17778 if (refined_along_y +
17779 to_be_refined_along_y >
17780 1)
17781 changed |=
17782 cell
17783 ->neighbor_or_periodic_neighbor(i)
17784 ->flag_for_face_refinement(
17785 nb_indices.first,
17786 RefinementCase<dim -
17787 1>::cut_axis(1));
17788 }
17789 else
17790 {
17791 if (cell
17792 ->neighbor_or_periodic_neighbor(i)
17793 ->refine_flag_set() !=
17796 changed = true;
17797 cell->neighbor_or_periodic_neighbor(i)
17798 ->set_refine_flag();
17799 }
17800
17801 // step 4: if necessary (see above) add to
17802 // the refine flag of the current cell
17803 cell_iterator nb =
17804 cell->neighbor_or_periodic_neighbor(i);
17805 RefinementCase<dim - 1> nb_frc =
17807 nb->refine_flag_set(),
17808 nb_indices.first,
17809 nb->face_orientation(nb_indices.first),
17810 nb->face_flip(nb_indices.first),
17811 nb->face_rotation(nb_indices.first));
17812 if ((nb_frc & RefinementCase<dim>::cut_x) &&
17813 !((refined_along_x != 0u) ||
17814 (to_be_refined_along_x != 0u)))
17815 changed |= cell->flag_for_face_refinement(
17816 i,
17818 if ((nb_frc & RefinementCase<dim>::cut_y) &&
17819 !((refined_along_y != 0u) ||
17820 (to_be_refined_along_y != 0u)))
17821 changed |= cell->flag_for_face_refinement(
17822 i,
17824 }
17825 } // if neighbor is coarser
17826 else // -> now the neighbor is not coarser
17827 {
17828 cell->neighbor_or_periodic_neighbor(i)
17829 ->clear_coarsen_flag();
17830 const unsigned int nb_nb =
17831 has_periodic_neighbor ?
17832 cell
17833 ->periodic_neighbor_of_periodic_neighbor(
17834 i) :
17835 cell->neighbor_of_neighbor(i);
17836 const cell_iterator neighbor =
17837 cell->neighbor_or_periodic_neighbor(i);
17838 RefinementCase<dim - 1> face_ref_case =
17840 neighbor->refine_flag_set(),
17841 nb_nb,
17842 neighbor->face_orientation(nb_nb),
17843 neighbor->face_flip(nb_nb),
17844 neighbor->face_rotation(nb_nb));
17845 RefinementCase<dim - 1> needed_face_ref_case =
17847 cell->refine_flag_set(),
17848 i,
17849 cell->face_orientation(i),
17850 cell->face_flip(i),
17851 cell->face_rotation(i));
17852 // if the neighbor wants to refine the
17853 // face with cut_x and we want cut_y
17854 // or vice versa, we have to refine
17855 // isotropically at the given face
17856 if ((face_ref_case ==
17858 needed_face_ref_case ==
17860 (face_ref_case ==
17862 needed_face_ref_case ==
17864 {
17865 changed = cell->flag_for_face_refinement(
17866 i, face_ref_case);
17867 neighbor->flag_for_face_refinement(
17868 nb_nb, needed_face_ref_case);
17869 }
17870 }
17871 }
17872 else //-> the neighbor is not active
17873 {
17874 RefinementCase<dim - 1>
17875 face_ref_case = cell->face(i)->refinement_case(),
17876 needed_face_ref_case =
17878 cell->refine_flag_set(),
17879 i,
17880 cell->face_orientation(i),
17881 cell->face_flip(i),
17882 cell->face_rotation(i));
17883 // if the face is refined with cut_x and
17884 // we want cut_y or vice versa, we have to
17885 // refine isotropically at the given face
17886 if ((face_ref_case == RefinementCase<dim>::cut_x &&
17887 needed_face_ref_case ==
17889 (face_ref_case == RefinementCase<dim>::cut_y &&
17890 needed_face_ref_case ==
17892 changed =
17893 cell->flag_for_face_refinement(i,
17894 face_ref_case);
17895 }
17896 }
17897 }
17898 }
17899 }
17900
17901 //------------------------------------
17902 // STEP 7:
17903 // take care that no double refinement is done at each line in 3d or
17904 // higher dimensions.
17905 this->policy->prepare_refinement_dim_dependent(*this);
17906
17907 //------------------------------------
17908 // STEP 8:
17909 // make sure that all children of each cell are either flagged for
17910 // coarsening or none of the children is
17911 fix_coarsen_flags();
17912
17913 // get the refinement and coarsening flags
17914 auto coarsen_flags_after_loop =
17915 internal::extract_raw_coarsen_flags(levels);
17916 auto refine_flags_after_loop = internal::extract_raw_refine_flags(levels);
17917
17918 // find out whether something was changed in this loop
17919 mesh_changed_in_this_loop =
17920 ((coarsen_flags_before_loop != coarsen_flags_after_loop) ||
17921 (refine_flags_before_loop != refine_flags_after_loop));
17922
17923 // set the flags for the next loop already
17924 coarsen_flags_before_loop.swap(coarsen_flags_after_loop);
17925 refine_flags_before_loop.swap(refine_flags_after_loop);
17926 }
17927 while (mesh_changed_in_this_loop);
17928
17929
17930 // find out whether something was really changed in this
17931 // function. Note that @p{..._flags_before_loop} represents the state
17932 // after the last loop, i.e., the present state
17933 return ((coarsen_flags_before != coarsen_flags_before_loop) ||
17934 (refine_flags_before != refine_flags_before_loop));
17935}
17936
17937
17938
17939template <int dim, int spacedim>
17942 const unsigned int magic_number1,
17943 const std::vector<bool> &v,
17944 const unsigned int magic_number2,
17945 std::ostream &out)
17946{
17947 const unsigned int N = v.size();
17948 unsigned char *flags = new unsigned char[N / 8 + 1];
17949 for (unsigned int i = 0; i < N / 8 + 1; ++i)
17950 flags[i] = 0;
17951
17952 for (unsigned int position = 0; position < N; ++position)
17953 flags[position / 8] |= (v[position] ? (1 << (position % 8)) : 0);
17954
17955 AssertThrow(out.fail() == false, ExcIO());
17956
17957 // format:
17958 // 0. magic number
17959 // 1. number of flags
17960 // 2. the flags
17961 // 3. magic number
17962 out << magic_number1 << ' ' << N << std::endl;
17963 for (unsigned int i = 0; i < N / 8 + 1; ++i)
17964 out << static_cast<unsigned int>(flags[i]) << ' ';
17965
17966 out << std::endl << magic_number2 << std::endl;
17967
17968 delete[] flags;
17969
17970 AssertThrow(out.fail() == false, ExcIO());
17971}
17972
17973
17974template <int dim, int spacedim>
17977 const unsigned int magic_number1,
17978 std::vector<bool> &v,
17979 const unsigned int magic_number2,
17980 std::istream &in)
17981{
17982 AssertThrow(in.fail() == false, ExcIO());
17983
17984 unsigned int magic_number;
17985 in >> magic_number;
17986 AssertThrow(magic_number == magic_number1, ExcGridReadError());
17987
17988 unsigned int N;
17989 in >> N;
17990 v.resize(N);
17991
17992 unsigned char *flags = new unsigned char[N / 8 + 1];
17993 unsigned short int tmp;
17994 for (unsigned int i = 0; i < N / 8 + 1; ++i)
17995 {
17996 in >> tmp;
17997 flags[i] = tmp;
17998 }
17999
18000 for (unsigned int position = 0; position != N; ++position)
18001 v[position] = ((flags[position / 8] & (1 << (position % 8))) != 0);
18002
18003 in >> magic_number;
18004 AssertThrow(magic_number == magic_number2, ExcGridReadError());
18005
18006 delete[] flags;
18007
18008 AssertThrow(in.fail() == false, ExcIO());
18009}
18010
18011
18012
18013template <int dim, int spacedim>
18016{
18017 std::size_t mem = 0;
18018 mem += sizeof(MeshSmoothing);
18019 mem += MemoryConsumption::memory_consumption(reference_cells);
18020 mem += MemoryConsumption::memory_consumption(periodic_face_pairs_level_0);
18022 for (const auto &level : levels)
18025 mem += MemoryConsumption::memory_consumption(vertices_used);
18026 mem += sizeof(manifolds);
18027 mem += sizeof(smooth_grid);
18028 mem += MemoryConsumption::memory_consumption(number_cache);
18029 mem += sizeof(faces);
18030 if (faces)
18032
18033 return mem;
18034}
18035
18036
18037
18038template <int dim, int spacedim>
18041 default;
18042
18043#endif
18044
18045// explicit instantiations
18046#include "grid/tria.inst"
18047
auto make_const_array_view(const Container &container) -> decltype(make_array_view(container))
ArrayView< std::remove_reference_t< typename std::iterator_traits< Iterator >::reference >, MemorySpaceType > make_array_view(const Iterator begin, const Iterator end)
Definition array_view.h:954
CellStatus
Definition cell_status.h:31
@ cell_will_be_refined
@ children_will_be_coarsened
types::coarse_cell_id get_coarse_cell_id() const
Definition cell_id.h:393
EnableObserverPointer & operator=(const EnableObserverPointer &)
virtual std::unique_ptr< Manifold< dim, spacedim > > clone() const =0
Definition point.h:113
numbers::NumberTraits< Number >::real_type distance(const Point< dim, Number > &p) const
unsigned int standard_to_real_face_vertex(const unsigned int vertex, const unsigned int face, const types::geometric_orientation face_orientation) const
std::array< unsigned int, 2 > standard_vertex_to_face_and_vertex_index(const unsigned int vertex) const
types::geometric_orientation get_combined_orientation(const ArrayView< const T > &vertices_0, const ArrayView< const T > &vertices_1) const
unsigned int n_lines() const
constexpr void clear()
void join() const
IteratorState::IteratorStates state() const
virtual void add_periodicity(const std::vector< GridTools::PeriodicFacePair< cell_iterator > > &)
virtual types::global_cell_index n_global_active_cells() const
quad_iterator begin_quad(const unsigned int level=0) const
MPI_Comm get_communicator() const
typename IteratorSelector::raw_line_iterator raw_line_iterator
Definition tria.h:4127
active_vertex_iterator begin_active_vertex() const
void load_user_indices_quad(const std::vector< unsigned int > &v)
unsigned int n_quads() const
Triangulation & operator=(Triangulation< dim, spacedim > &&tria) noexcept
void load_user_indices(const std::vector< unsigned int > &v)
std::vector< bool > vertices_used
Definition tria.h:4503
virtual void clear()
bool anisotropic_refinement
Definition tria.h:4514
active_quad_iterator begin_active_quad(const unsigned int level=0) const
bool get_anisotropic_refinement_flag() const
virtual const MeshSmoothing & get_mesh_smoothing() const
virtual void copy_triangulation(const Triangulation< dim, spacedim > &other_tria)
virtual types::coarse_cell_id n_global_coarse_cells() const
std::unique_ptr< std::map< unsigned int, types::manifold_id > > vertex_to_manifold_id_map_1d
Definition tria.h:4572
void save_user_pointers_quad(std::vector< void * > &v) const
void save_user_flags_hex(std::ostream &out) const
void clear_user_flags_quad()
unsigned int n_faces() const
active_hex_iterator begin_active_hex(const unsigned int level=0) const
static void read_bool_vector(const unsigned int magic_number1, std::vector< bool > &v, const unsigned int magic_number2, std::istream &in)
virtual std::weak_ptr< const Utilities::MPI::Partitioner > global_active_cell_index_partitioner() const
bool all_reference_cells_are_hyper_cube() const
void load_user_flags_line(std::istream &in)
void clear_user_data()
raw_hex_iterator begin_raw_hex(const unsigned int level=0) const
void save_user_flags_line(std::ostream &out) const
active_cell_iterator last_active() const
void save(Archive &ar, const unsigned int version) const
void reset_global_cell_indices()
face_iterator end_face() const
void reset_active_cell_indices()
cell_iterator create_cell_iterator(const CellId &cell_id) const
cell_iterator begin(const unsigned int level=0) const
void fix_coarsen_flags()
virtual MPI_Comm get_mpi_communicator() const
void save_user_pointers_line(std::vector< void * > &v) const
void load_refine_flags(std::istream &in)
void save_user_indices_line(std::vector< unsigned int > &v) const
raw_cell_iterator begin_raw(const unsigned int level=0) const
unsigned int n_lines() const
virtual void set_mesh_smoothing(const MeshSmoothing mesh_smoothing)
unsigned int n_raw_lines() const
virtual std::size_t memory_consumption() const
std::vector< Point< spacedim > > vertices
Definition tria.h:4498
raw_quad_iterator begin_raw_quad(const unsigned int level=0) const
virtual types::subdomain_id locally_owned_subdomain() const
unsigned int n_raw_faces() const
unsigned int n_active_faces() const
virtual void create_triangulation(const std::vector< Point< spacedim > > &vertices, const std::vector< CellData< dim > > &cells, const SubCellData &subcelldata)
const bool check_for_distorted_cells
Definition tria.h:4521
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:4549
void load_user_flags_quad(std::istream &in)
unsigned int n_active_cells() const
virtual void update_reference_cells()
std::vector< ReferenceCell > reference_cells
Definition tria.h:4042
void update_periodic_face_map()
void clear_despite_subscriptions()
void coarsen_global(const unsigned int times=1)
Triangulation(const MeshSmoothing smooth_grid=none, const bool check_for_distorted_cells=false)
void save_user_flags(std::ostream &out) const
void refine_global(const unsigned int times=1)
virtual std::weak_ptr< const Utilities::MPI::Partitioner > global_level_cell_index_partitioner(const unsigned int level) const
void load_user_flags_hex(std::istream &in)
void load_user_pointers_quad(const std::vector< void * > &v)
std::unique_ptr<::internal::TriangulationImplementation::TriaFaces > faces
Definition tria.h:4492
unsigned int n_used_vertices() const
void reset_cell_vertex_indices_cache()
unsigned int n_active_lines() const
void load_user_indices_line(const std::vector< unsigned int > &v)
void clear_user_flags_hex()
void save_user_pointers_hex(std::vector< void * > &v) const
const std::vector< ReferenceCell > & get_reference_cells() const
typename IteratorSelector::raw_quad_iterator raw_quad_iterator
Definition tria.h:4128
void load_user_pointers(const std::vector< void * > &v)
unsigned int register_data_attach(const std::function< std::vector< char >(const cell_iterator &, const ::CellStatus)> &pack_callback, const bool returns_variable_size_data)
::internal::TriangulationImplementation::NumberCache< dim > number_cache
Definition tria.h:4532
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:4103
unsigned int n_raw_cells(const unsigned int level) const
bool contains_cell(const CellId &cell_id) const
void load_attached_data(const unsigned int global_first_cell, const unsigned int global_num_cells, const unsigned int local_num_cells, const std::string &file_basename, const unsigned int n_attached_deserialize_fixed, const unsigned int n_attached_deserialize_variable)
void load_coarsen_flags(std::istream &out)
quad_iterator end_quad() const
line_iterator begin_line(const unsigned int level=0) const
unsigned int max_adjacent_cells() const
vertex_iterator begin_vertex() const
void clear_user_flags()
unsigned int n_hexs() const
vertex_iterator end_vertex() const
void load_user_pointers_line(const std::vector< void * > &v)
hex_iterator end_hex() const
hex_iterator begin_hex(const unsigned int level=0) const
virtual void execute_coarsening_and_refinement()
active_cell_iterator end_active(const unsigned int level) const
bool is_mixed_mesh() const
cell_iterator last() const
unsigned int n_active_quads() const
void load_user_indices_hex(const std::vector< unsigned int > &v)
unsigned int n_raw_quads() const
void save_user_pointers(std::vector< void * > &v) const
face_iterator begin_face() const
unsigned int n_cells() const
virtual bool prepare_coarsening_and_refinement()
void unpack_data_serial()
const std::vector< bool > & get_used_vertices() const
typename IteratorSelector::raw_hex_iterator raw_hex_iterator
Definition tria.h:4129
MeshSmoothing smooth_grid
Definition tria.h:4036
void save_refine_flags(std::ostream &out) const
std::unique_ptr< ::internal::TriangulationImplementation::Policy< dim, spacedim > > policy
Definition tria.h:4094
Triangulation< dim, spacedim > & get_triangulation()
void save_user_flags_quad(std::ostream &out) const
Signals signals
Definition tria.h:2527
virtual ~Triangulation() override
unsigned int n_vertices() const
void load(Archive &ar, const unsigned int version)
void save_user_indices(std::vector< unsigned int > &v) const
void notify_ready_to_unpack(const unsigned int handle, const std::function< void(const cell_iterator &, const ::CellStatus, const boost::iterator_range< std::vector< char >::const_iterator > &)> &unpack_callback)
bool all_reference_cells_are_simplex() const
std::vector< std::unique_ptr<::internal::TriangulationImplementation::TriaLevel > > levels
Definition tria.h:4484
unsigned int n_raw_hexs(const unsigned int level) const
void set_all_refine_flags()
const std::map< std::pair< cell_iterator, unsigned int >, std::pair< std::pair< cell_iterator, unsigned int >, types::geometric_orientation > > & get_periodic_face_map() const
unsigned int n_active_hexs() const
virtual std::vector< types::boundary_id > get_boundary_ids() const
void load_user_flags(std::istream &in)
void reset_policy()
void save_coarsen_flags(std::ostream &out) const
active_face_iterator begin_active_face() const
void clear_user_flags_line()
raw_line_iterator begin_raw_line(const unsigned int level=0) const
static void write_bool_vector(const unsigned int magic_number1, const std::vector< bool > &v, const unsigned int magic_number2, std::ostream &out)
void flip_all_direction_flags()
active_cell_iterator begin_active(const unsigned int level=0) const
void execute_coarsening()
typename std::pair< cell_iterator, CellStatus > cell_relation_t
Definition tria.h:394
void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation) override
Definition tria.cc:2591
void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation) override
Definition tria.cc:2598
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:2574
void update_neighbors(Triangulation< dim, spacedim > &tria) override
Definition tria.cc:2568
bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell) override
Definition tria.cc:2605
Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells) override
Definition tria.cc:2584
std::unique_ptr< Policy< dim, spacedim > > clone() override
Definition tria.cc:2613
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< std::pair< int, int > > neighbors
std::vector< types::global_cell_index > global_active_cell_indices
std::vector< types::global_cell_index > global_level_cell_indices
std::vector< ReferenceCell > reference_cell
std::vector< types::subdomain_id > level_subdomain_ids
std::vector< types::subdomain_id > subdomain_ids
std::vector< unsigned int > active_cell_indices
std::vector< types::manifold_id > manifold_id
std::vector< BoundaryOrMaterialId > boundary_or_material_id
constexpr LibraryBuildMode library_build_mode
Definition config.h:68
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:40
constexpr bool running_in_debug_mode()
Definition config.h:78
#define DEAL_II_CXX20_REQUIRES(condition)
Definition config.h:245
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:41
#define AssertIsNotUsed(obj)
#define DEAL_II_ASSERT_UNREACHABLE()
#define DEAL_II_NOT_IMPLEMENTED()
Point< 2 > second
Definition grid_out.cc:4633
Point< 2 > first
Definition grid_out.cc:4632
unsigned int level
Definition grid_out.cc:4635
AdjacentCell adjacent_cells[2]
unsigned int vertex_indices[2]
unsigned int cell_index
IteratorRange< active_cell_iterator > active_cell_iterators_on_level(const unsigned int level) const
IteratorRange< active_face_iterator > active_face_iterators() const
IteratorRange< active_cell_iterator > active_cell_iterators() const
IteratorRange< cell_iterator > cell_iterators_on_level(const unsigned int level) const
IteratorRange< cell_iterator > cell_iterators() const
static ::ExceptionBase & ExcInternalErrorOnCell(int arg1)
static ::ExceptionBase & ExcIO()
static ::ExceptionBase & ExcInteriorQuadCantBeBoundary(int arg1, int arg2, int arg3, int arg4, types::boundary_id arg5)
static ::ExceptionBase & ExcNotImplemented()
static ::ExceptionBase & ExcInconsistentLineInfoOfLine(int arg1, int arg2, std::string arg3)
static ::ExceptionBase & ExcCellHasNegativeMeasure(int arg1)
#define Assert(cond, exc)
static ::ExceptionBase & ExcImpossibleInDim(int arg1)
static ::ExceptionBase & ExcMemoryInexact(int arg1, int arg2)
#define DeclException2(Exception2, type1, type2, outsequence)
#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:1692
typename IteratorSelector::active_quad_iterator active_quad_iterator
Definition tria.h:1683
typename IteratorSelector::active_hex_iterator active_hex_iterator
Definition tria.h:1703
typename IteratorSelector::quad_iterator quad_iterator
Definition tria.h:1668
typename IteratorSelector::line_iterator line_iterator
Definition tria.h:1644
TriaIterator< CellAccessor< dim, spacedim > > cell_iterator
Definition tria.h:1557
typename IteratorSelector::active_line_iterator active_line_iterator
Definition tria.h:1659
void set_all_manifold_ids_on_boundary(const types::manifold_id number)
const Manifold< dim, spacedim > & get_manifold(const types::manifold_id number) const
virtual std::vector< types::manifold_id > get_manifold_ids() const
void reset_manifold(const types::manifold_id manifold_number)
void set_manifold(const types::manifold_id number, const Manifold< dim, spacedim > &manifold_object)
void reset_all_manifolds()
void set_all_manifold_ids(const types::manifold_id number)
Task< RT > new_task(const std::function< RT()> &function)
const unsigned int mn_tria_refine_flags_end
const unsigned int mn_tria_coarsen_flags_end
const unsigned int mn_tria_refine_flags_begin
const unsigned int mn_tria_hex_user_flags_end
const unsigned int mn_tria_line_user_flags_begin
const unsigned int mn_tria_line_user_flags_end
const unsigned int mn_tria_quad_user_flags_end
const unsigned int mn_tria_coarsen_flags_begin
const unsigned int mn_tria_hex_user_flags_begin
const unsigned int mn_tria_quad_user_flags_begin
const Mapping< dim, spacedim > & get_default_linear_mapping(const Triangulation< dim, spacedim > &triangulation)
Definition mapping.cc:316
std::vector< index_type > data
Definition mpi.cc:746
std::size_t size
Definition mpi.cc:745
void create_triangulation(Triangulation< dim, dim > &tria, const AdditionalData &additional_data=AdditionalData())
void reference_cell(Triangulation< dim, spacedim > &tria, const ReferenceCell &reference_cell)
double diameter(const Triangulation< dim, spacedim > &tria)
@ valid
Iterator points to a valid object.
constexpr char N
std::enable_if_t< std::is_fundamental_v< T >, std::size_t > memory_consumption(const T &t)
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
Tensor< 2, dim, Number > l(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
constexpr const ReferenceCell Tetrahedron
constexpr const ReferenceCell Quadrilateral
constexpr const ReferenceCell Invalid
constexpr const ReferenceCell Triangle
constexpr const ReferenceCell Hexahedron
constexpr unsigned int max_n_faces()
constexpr const ReferenceCell Line
VectorType::value_type * end(VectorType &V)
VectorType::value_type * begin(VectorType &V)
int File_write_at_c(MPI_File fh, MPI_Offset offset, const void *buf, MPI_Count count, MPI_Datatype datatype, MPI_Status *status)
int File_read_at_c(MPI_File fh, MPI_Offset offset, void *buf, MPI_Count count, MPI_Datatype datatype, MPI_Status *status)
unsigned int n_mpi_processes(const MPI_Comm mpi_communicator)
Definition mpi.cc:99
T max(const T &t, const MPI_Comm mpi_communicator)
unsigned int this_mpi_process(const MPI_Comm mpi_communicator)
Definition mpi.cc:114
std::size_t pack(const T &object, std::vector< char > &dest_buffer, const bool allow_compression=true)
Definition utilities.h:1382
constexpr T fixed_power(const T t)
Definition utilities.h:943
unsigned int n_active_cells(const internal::TriangulationImplementation::NumberCache< 1 > &c)
Definition tria.cc:14909
const Manifold< dim, spacedim > & get_default_flat_manifold()
Definition tria.cc:12006
unsigned int n_cells(const internal::TriangulationImplementation::NumberCache< 1 > &c)
Definition tria.cc:14902
void reserve_space(TriaFaces &tria_faces, const unsigned int new_quads_in_pairs, const unsigned int new_quads_single)
Definition tria.cc:2036
void monitor_memory(const TriaLevel &tria_level, const unsigned int true_dimension)
Definition tria.cc:2235
std::tuple< bool, bool, bool > split_face_orientation(const types::geometric_orientation combined_face_orientation)
constexpr types::global_dof_index invalid_dof_index
Definition types.h:263
constexpr unsigned int invalid_unsigned_int
Definition types.h:232
constexpr types::boundary_id internal_face_boundary_id
Definition types.h:323
constexpr types::manifold_id flat_manifold_id
Definition types.h:336
constexpr types::geometric_orientation reverse_line_orientation
Definition types.h:359
constexpr types::subdomain_id invalid_subdomain_id
Definition types.h:375
constexpr types::geometric_orientation default_geometric_orientation
Definition types.h:346
STL namespace.
::VectorizedArray< Number, width > min(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > abs(const ::VectorizedArray< Number, width > &)
unsigned int manifold_id
Definition types.h:165
unsigned char geometric_orientation
Definition types.h:40
unsigned int boundary_id
Definition types.h:153
const ::parallel::distributed::Triangulation< dim, spacedim > * triangulation
static unsigned int child_cell_on_face(const RefinementCase< dim > &ref_case, const unsigned int face, const unsigned int subface, const bool face_orientation=true, const bool face_flip=false, const bool face_rotation=false, const RefinementCase< dim - 1 > &face_refinement_case=RefinementCase< dim - 1 >::isotropic_refinement)
static RefinementCase< dim - 1 > face_refinement_case(const RefinementCase< dim > &cell_refinement_case, const unsigned int face_no, const bool face_orientation=true, const bool face_flip=false, const bool face_rotation=false)
static std_cxx20::ranges::iota_view< unsigned int, unsigned int > face_indices()
static RefinementCase< dim > min_cell_refinement_case_for_face_refinement(const RefinementCase< dim - 1 > &face_refinement_case, const unsigned int face_no, const bool face_orientation=true, const bool face_flip=false, const bool face_rotation=false)
static unsigned int n_children(const RefinementCase< dim > &refinement_case)
static void alternating_form_at_vertices(const Point< spacedim >(&vertices)[vertices_per_cell], Tensor< spacedim - dim, spacedim >(&forms)[vertices_per_cell])
std::vector< CellData< 2 > > boundary_quads
Definition cell_data.h:248
bool check_consistency(const unsigned int dim) const
std::vector< CellData< 1 > > boundary_lines
Definition cell_data.h:232
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:1738
boost::signals2::signal< void(const Triangulation< dim, spacedim > &destination_tria)> copy
Definition tria.h:2373
static void update_neighbors(Triangulation< 1, spacedim > &)
Definition tria.cc:11888
static void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &)
Definition tria.cc:11978
static Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:11969
static bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &)
Definition tria.cc:11994
static void update_neighbors(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:11892
static void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:11986
static void delete_children(Triangulation< dim, spacedim > &, typename Triangulation< dim, spacedim >::cell_iterator &, std::vector< unsigned int > &, std::vector< unsigned int > &)
Definition tria.cc:11958
static void reserve_space_(TriaObjects &obj, const unsigned int size)
Definition tria.cc:3661
static void reserve_space_(TriaFaces &faces, const unsigned structdim, const unsigned int size)
Definition tria.cc:3604
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:2819
static void prevent_distorted_boundary_cells(Triangulation< 1, spacedim > &)
Definition tria.cc:11495
static void update_neighbors(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:3047
static void prepare_refinement_dim_dependent(const Triangulation< dim, spacedim > &)
Definition tria.cc:11583
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:3955
static void reserve_space_(TriaLevel &level, const unsigned int spacedim, const unsigned int size, const bool orientation_needed)
Definition tria.cc:3624
static void update_neighbors(Triangulation< 1, spacedim > &)
Definition tria.cc:3041
static Triangulation< 3, spacedim >::DistortedCellList execute_refinement(Triangulation< 3, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:7122
static Triangulation< dim, spacedim >::DistortedCellList execute_refinement_isotropic(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:4951
static void compute_number_cache(const Triangulation< dim, spacedim > &triangulation, const unsigned int level_objects, internal::TriangulationImplementation::NumberCache< dim > &number_cache)
Definition tria.cc:3019
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:4584
static void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:11502
static bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell)
Definition tria.cc:11816
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:2926
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:3713
static void prepare_refinement_dim_dependent(Triangulation< 3, spacedim > &triangulation)
Definition tria.cc:11593
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:3817
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:2731
static Triangulation< 1, spacedim >::DistortedCellList execute_refinement(Triangulation< 1, spacedim > &triangulation, const bool)
Definition tria.cc:5406
static Triangulation< 3, spacedim >::DistortedCellList execute_refinement_isotropic(Triangulation< 3, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:5948
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:3226
static Triangulation< 2, spacedim >::DistortedCellList execute_refinement(Triangulation< 2, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:5640
static void process_subcelldata(const CRS< T > &crs, TriaObjects &obj, const std::vector< CellData< structdim > > &boundary_objects_in, const std::vector< Point< spacedim > > &vertex_locations)
Definition tria.cc:3493
std::vector< std::vector< CellData< dim > > > cell_infos