deal.II version GIT relicensing-3083-g7b89508ac7 2025-04-18 12:50: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\}}\)
Loading...
Searching...
No Matches
tria.cc
Go to the documentation of this file.
1// ------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: LGPL-2.1-or-later
4// Copyright (C) 1999 - 2024 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Part of the source code is dual licensed under Apache-2.0 WITH
9// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
10// governing the source code and code contributions can be found in
11// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
12//
13// ------------------------------------------------------------------------
14
15
18#include <deal.II/base/mpi.templates.h>
23
26
31#include <deal.II/grid/tria.h>
37
38#include <boost/archive/text_iarchive.hpp>
39#include <boost/archive/text_oarchive.hpp>
40
41#include <algorithm>
42#include <array>
43#include <cmath>
44#include <cstdint>
45#include <fstream>
46#include <functional>
47#include <limits>
48#include <list>
49#include <map>
50#include <memory>
51#include <numeric>
52
53
55
56
57namespace internal
58{
59 namespace TriangulationImplementation
60 {
62 : n_levels(0)
63 , n_lines(0)
64 , n_active_lines(0)
65 // all other fields are
66 // default constructed
67 {}
68
69
70
71 std::size_t
73 {
74 std::size_t mem =
79 MemoryConsumption::memory_consumption(n_active_lines_level);
80
81 if (active_cell_index_partitioner)
82 mem += active_cell_index_partitioner->memory_consumption();
83
84 for (const auto &partitioner : level_cell_index_partitioners)
85 if (partitioner)
86 mem += partitioner->memory_consumption();
87
88 return mem;
89 }
90
91
93 : n_quads(0)
94 , n_active_quads(0)
95 // all other fields are
96 // default constructed
97 {}
98
99
100
101 std::size_t
110
111
112
114 : n_hexes(0)
115 , n_active_hexes(0)
116 // all other fields are
117 // default constructed
118 {}
119
120
121
122 std::size_t
131 } // namespace TriangulationImplementation
132
133
134 template <int dim, int spacedim>
137 : variable_size_data_stored(false)
138 {}
139
140
141 template <int dim, int spacedim>
143 void CellAttachedDataSerializer<dim, spacedim>::pack_data(
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 faces. As these are stored globally,
5990 // declare them outside the loop over all levels. We need lines
5991 // and faces in pairs for refinement of old lines/face. And lines and
5992 // faces stored individually for the ones created in the interior
5993 // of an existing cell
5994 {
5995 unsigned int needed_vertices = 0;
5996 unsigned int needed_lines_single = 0;
5997 unsigned int needed_faces_single = 0;
5998 unsigned int needed_lines_pair = 0;
5999 unsigned int needed_faces_pair = 0;
6000 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
6001 {
6002 unsigned int new_cells = 0;
6003
6004 for (const auto &cell :
6005 triangulation.active_cell_iterators_on_level(level))
6006 if (cell->refine_flag_set())
6007 {
6008 // Only support isotropic refinement
6009 Assert(cell->refine_flag_set() ==
6012
6013 // Now count up how many new cells, faces, edges, and
6014 // vertices we will need to allocate to do this refinement.
6015 new_cells += cell->reference_cell().n_isotropic_children();
6016
6017 if (cell->reference_cell() == ReferenceCells::Hexahedron)
6018 {
6019 ++needed_vertices;
6020 needed_lines_single += 6;
6021 needed_faces_single += 12;
6022 }
6023 else if (cell->reference_cell() ==
6025 {
6026 needed_lines_single += 1;
6027 needed_faces_single += 8;
6028 }
6029 else
6030 {
6032 }
6033
6034 // Also check whether we have to refine any of the faces and
6035 // edges that bound this cell. They may of course already be
6036 // refined, so we only *mark* them for refinement by setting
6037 // the user flags
6038 for (const auto face : cell->face_indices())
6039 if (cell->face(face)->n_children() == 0)
6040 cell->face(face)->set_user_flag();
6041 else
6042 Assert(cell->face(face)->n_children() ==
6043 cell->reference_cell()
6044 .face_reference_cell(face)
6045 .n_isotropic_children(),
6047
6048 for (const auto line : cell->line_indices())
6049 if (cell->line(line)->has_children() == false)
6050 cell->line(line)->set_user_flag();
6051 else
6052 Assert(cell->line(line)->n_children() == 2,
6054 }
6055
6056 const unsigned int used_cells =
6057 std::count(triangulation.levels[level + 1]->cells.used.begin(),
6058 triangulation.levels[level + 1]->cells.used.end(),
6059 true);
6060
6061 if (triangulation.all_reference_cells_are_hyper_cube())
6062 reserve_space(*triangulation.levels[level + 1],
6063 used_cells + new_cells,
6064 spacedim,
6065 false);
6066 else
6067 reserve_space(*triangulation.levels[level + 1],
6068 used_cells + new_cells,
6069 spacedim,
6070 true);
6071
6072 reserve_space(triangulation.levels[level + 1]->cells, new_cells);
6073 }
6074
6075 // now count the faces and lines which were flagged for
6076 // refinement
6079 quad != triangulation.end_quad();
6080 ++quad)
6081 {
6082 if (quad->user_flag_set() == false)
6083 continue;
6084
6085 if (quad->reference_cell() == ReferenceCells::Quadrilateral)
6086 {
6087 needed_faces_pair += 4;
6088 needed_lines_pair += 4;
6089 needed_vertices += 1;
6090 }
6091 else if (quad->reference_cell() == ReferenceCells::Triangle)
6092 {
6093 needed_faces_pair += 4;
6094 needed_lines_single += 3;
6095 }
6096 else
6097 {
6099 }
6100 }
6101
6104 line != triangulation.end_line();
6105 ++line)
6106 {
6107 if (line->user_flag_set() == false)
6108 continue;
6109
6110 needed_lines_pair += 2;
6111 needed_vertices += 1;
6112 }
6113
6114 reserve_space(triangulation.faces->lines,
6115 needed_lines_pair,
6116 needed_lines_single);
6118 needed_faces_pair,
6119 needed_faces_single);
6120 reserve_space(triangulation.faces->quads,
6121 needed_faces_pair,
6122 needed_faces_single);
6123
6124
6125 // add to needed vertices how many vertices are already in use
6126 needed_vertices += std::count(triangulation.vertices_used.begin(),
6127 triangulation.vertices_used.end(),
6128 true);
6129
6130 if (needed_vertices > triangulation.vertices.size())
6131 {
6132 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
6133 triangulation.vertices_used.resize(needed_vertices, false);
6134 }
6135 }
6136
6137 //-----------------------------------------
6138 // Before we start with the actual refinement, we do some
6139 // sanity checks if in debug mode. especially, we try to catch
6140 // the notorious problem with lines being twice refined,
6141 // i.e. there are cells adjacent at one line ("around the
6142 // edge", but not at a face), with two cells differing by more
6143 // than one refinement level
6144 //
6145 // this check is very simple to implement here, since we have
6146 // all lines flagged if they shall be refined
6147 if constexpr (running_in_debug_mode())
6148 {
6149 for (const auto &cell : triangulation.active_cell_iterators())
6150 if (!cell->refine_flag_set())
6151 for (unsigned int line_n = 0; line_n < cell->n_lines();
6152 ++line_n)
6153 if (cell->line(line_n)->has_children())
6154 for (unsigned int c = 0; c < 2; ++c)
6155 Assert(cell->line(line_n)->child(c)->user_flag_set() ==
6156 false,
6158 }
6159
6160 unsigned int current_vertex = 0;
6161
6162 // helper function - find the next available vertex number and mark it
6163 // as used.
6164 auto get_next_unused_vertex = [](const unsigned int current_vertex,
6165 std::vector<bool> &vertices_used) {
6166 unsigned int next_vertex = current_vertex;
6167 while (next_vertex < vertices_used.size() &&
6168 vertices_used[next_vertex] == true)
6169 ++next_vertex;
6170 Assert(next_vertex < vertices_used.size(), ExcInternalError());
6171 vertices_used[next_vertex] = true;
6172
6173 return next_vertex;
6174 };
6175
6176 // LINES
6177 {
6180 endl = triangulation.end_line();
6181 raw_line_iterator next_unused_line = triangulation.begin_raw_line();
6182
6183 for (; line != endl; ++line)
6184 {
6185 if (line->user_flag_set() == false)
6186 continue;
6187
6188 next_unused_line =
6189 triangulation.faces->lines.template next_free_pair_object<1>(
6191 Assert(next_unused_line.state() == IteratorState::valid,
6193
6194 // now we found two consecutive unused lines, such
6195 // that the children of a line will be consecutive.
6196 // then set the child pointer of the present line
6197 line->set_children(0, next_unused_line->index());
6198
6199 const std::array<raw_line_iterator, 2> children{
6200 {next_unused_line, ++next_unused_line}};
6201
6202 AssertIsNotUsed(children[0]);
6203 AssertIsNotUsed(children[1]);
6204
6205 current_vertex =
6206 get_next_unused_vertex(current_vertex,
6207 triangulation.vertices_used);
6208 triangulation.vertices[current_vertex] = line->center(true);
6209
6210 children[0]->set_bounding_object_indices(
6211 {line->vertex_index(0), current_vertex});
6212 children[1]->set_bounding_object_indices(
6213 {current_vertex, line->vertex_index(1)});
6214
6215 const auto manifold_id = line->manifold_id();
6216 const auto boundary_id = line->boundary_id();
6217 for (const auto &child : children)
6218 {
6219 child->set_used_flag();
6220 child->clear_children();
6221 child->clear_user_data();
6222 child->clear_user_flag();
6223 child->set_boundary_id_internal(boundary_id);
6224 child->set_manifold_id(manifold_id);
6225 }
6226
6227 line->clear_user_flag();
6228 }
6229 }
6230
6231 // QUADS
6232 {
6234 quad = triangulation.begin_quad(),
6235 endq = triangulation.end_quad();
6236
6237 for (; quad != endq; ++quad)
6238 {
6239 if (quad->user_flag_set() == false)
6240 continue;
6241
6242 const auto reference_face_type = quad->reference_cell();
6243
6244 // 1) create new lines (property is set later)
6245 // maximum of 4 new lines (4 quadrilateral, 3 triangle)
6246 std::array<raw_line_iterator, 4> new_lines;
6247 if (reference_face_type == ReferenceCells::Quadrilateral)
6248 {
6249 for (unsigned int l = 0; l < 2; ++l)
6250 {
6251 auto next_unused_line =
6252 triangulation.faces->lines
6253 .template next_free_pair_object<1>(triangulation);
6254 new_lines[2 * l] = next_unused_line;
6255 new_lines[2 * l + 1] = ++next_unused_line;
6256 }
6257 }
6258 else if (reference_face_type == ReferenceCells::Triangle)
6259 {
6260 for (unsigned int l = 0; l < 3; ++l)
6261 new_lines[l] =
6262 triangulation.faces->lines
6263 .template next_free_single_object<1>(triangulation);
6264 }
6265 else
6266 {
6268 }
6269
6270 if constexpr (running_in_debug_mode())
6271 {
6272 for (const unsigned int line : quad->line_indices())
6273 AssertIsNotUsed(new_lines[line]);
6274 }
6275
6276 // 2) create new quads (properties are set below). Both triangles
6277 // and quads are divided in four.
6278 std::array<raw_quad_iterator, 4> new_quads;
6279 for (unsigned int q = 0; q < 2; ++q)
6280 {
6281 auto next_unused_quad =
6282 triangulation.faces->quads
6283 .template next_free_pair_object<2>(triangulation);
6284
6285 new_quads[2 * q] = next_unused_quad;
6286 new_quads[2 * q + 1] = ++next_unused_quad;
6287
6288 quad->set_children(2 * q, new_quads[2 * q]->index());
6289 }
6290 quad->set_refinement_case(RefinementCase<2>::cut_xy);
6291
6292 if constexpr (running_in_debug_mode())
6293 {
6294 for (const auto &quad : new_quads)
6295 AssertIsNotUsed(quad);
6296 }
6297
6298 // 3) set vertex indices and set new vertex
6299
6300 // Maximum of 9 vertices per refined quad (9 for Quadrilateral, 6
6301 // for Triangle)
6302 std::array<unsigned int, 9> vertex_indices = {};
6303 unsigned int k = 0;
6304 for (const auto i : quad->vertex_indices())
6305 vertex_indices[k++] = quad->vertex_index(i);
6306
6307 for (const auto i : quad->line_indices())
6308 vertex_indices[k++] = quad->line(i)->child(0)->vertex_index(1);
6309
6310 if (reference_face_type == ReferenceCells::Quadrilateral)
6311 {
6312 current_vertex =
6313 get_next_unused_vertex(current_vertex,
6314 triangulation.vertices_used);
6315 vertex_indices[k++] = current_vertex;
6316
6317 triangulation.vertices[current_vertex] =
6318 quad->center(true, true);
6319 }
6320
6321 // 4) set new lines on quads and their properties
6322 std::array<raw_line_iterator, 12> lines;
6323 unsigned int n_lines = 0;
6324 for (unsigned int l = 0; l < quad->n_lines(); ++l)
6325 for (unsigned int c = 0; c < 2; ++c)
6326 lines[n_lines++] = quad->line(l)->child(
6327 child_line_index(c, quad->line_orientation(l)));
6328
6329 for (unsigned int l = 0; l < quad->n_lines(); ++l)
6330 lines[n_lines++] = new_lines[l];
6331
6332 std::array<int, 12> line_indices;
6333 for (unsigned int i = 0; i < n_lines; ++i)
6334 line_indices[i] = lines[i]->index();
6335
6336 static constexpr ::ndarray<unsigned int, 12, 2>
6337 line_vertices_quad{{{{0, 4}},
6338 {{4, 2}},
6339 {{1, 5}},
6340 {{5, 3}},
6341 {{0, 6}},
6342 {{6, 1}},
6343 {{2, 7}},
6344 {{7, 3}},
6345 {{6, 8}},
6346 {{8, 7}},
6347 {{4, 8}},
6348 {{8, 5}}}};
6349
6350 static constexpr ::ndarray<unsigned int, 4, 4>
6351 quad_lines_quad{{{{0, 8, 4, 10}},
6352 {{8, 2, 5, 11}},
6353 {{1, 9, 10, 6}},
6354 {{9, 3, 11, 7}}}};
6355
6356 static constexpr ::ndarray<unsigned int, 12, 2>
6357 line_vertices_tri{{{{0, 3}},
6358 {{3, 1}},
6359 {{1, 4}},
6360 {{4, 2}},
6361 {{2, 5}},
6362 {{5, 0}},
6363 {{3, 4}},
6364 {{4, 5}},
6365 {{3, 5}},
6366 {{X, X}},
6367 {{X, X}},
6368 {{X, X}}}};
6369
6370 static constexpr ::ndarray<unsigned int, 4, 4>
6371 quad_lines_tri{{{{0, 8, 5, X}},
6372 {{1, 2, 6, X}},
6373 {{7, 3, 4, X}},
6374 {{6, 7, 8, X}}}};
6375
6376 static constexpr ::ndarray<unsigned int, 4, 4, 2>
6377 quad_line_vertices_tri{
6378 {{{{{0, 3}}, {{3, 5}}, {{5, 0}}, {{X, X}}}},
6379 {{{{3, 1}}, {{1, 4}}, {{4, 3}}, {{X, X}}}},
6380 {{{{5, 4}}, {{4, 2}}, {{2, 5}}, {{X, X}}}},
6381 {{{{3, 4}}, {{4, 5}}, {{5, 3}}, {{X, X}}}}}};
6382
6383 const auto &line_vertices =
6384 (reference_face_type == ReferenceCells::Quadrilateral) ?
6385 line_vertices_quad :
6386 line_vertices_tri;
6387 const auto &quad_lines =
6388 (reference_face_type == ReferenceCells::Quadrilateral) ?
6389 quad_lines_quad :
6390 quad_lines_tri;
6391
6392 for (unsigned int i = 0, j = 2 * quad->n_lines();
6393 i < quad->n_lines();
6394 ++i, ++j)
6395 {
6396 auto &new_line = new_lines[i];
6397 new_line->set_bounding_object_indices(
6398 {vertex_indices[line_vertices[j][0]],
6399 vertex_indices[line_vertices[j][1]]});
6400 new_line->set_used_flag();
6401 new_line->clear_user_flag();
6402 new_line->clear_user_data();
6403 new_line->clear_children();
6404 new_line->set_boundary_id_internal(quad->boundary_id());
6405 new_line->set_manifold_id(quad->manifold_id());
6406 }
6407
6408 // 5) set properties of quads
6409 for (unsigned int i = 0; i < new_quads.size(); ++i)
6410 {
6411 auto &new_quad = new_quads[i];
6412
6413 // TODO: we assume here that all children have the same type
6414 // as the parent
6415 triangulation.faces->set_quad_type(new_quad->index(),
6416 reference_face_type);
6417
6418 if (reference_face_type == ReferenceCells::Triangle)
6419 new_quad->set_bounding_object_indices(
6420 {line_indices[quad_lines[i][0]],
6421 line_indices[quad_lines[i][1]],
6422 line_indices[quad_lines[i][2]]});
6423 else if (reference_face_type == ReferenceCells::Quadrilateral)
6424 new_quad->set_bounding_object_indices(
6425 {line_indices[quad_lines[i][0]],
6426 line_indices[quad_lines[i][1]],
6427 line_indices[quad_lines[i][2]],
6428 line_indices[quad_lines[i][3]]});
6429 else
6431
6432 new_quad->set_used_flag();
6433 new_quad->clear_user_flag();
6434 new_quad->clear_user_data();
6435 new_quad->clear_children();
6436 new_quad->set_boundary_id_internal(quad->boundary_id());
6437 new_quad->set_manifold_id(quad->manifold_id());
6438
6439 [[maybe_unused]] std::set<unsigned int> s;
6440
6441 // ... and fix orientation of lines of face for triangles,
6442 // using an expensive algorithm, quadrilaterals are treated
6443 // a few lines below by a cheaper algorithm
6444 if (reference_face_type == ReferenceCells::Triangle)
6445 {
6446 for (const auto f : new_quad->line_indices())
6447 {
6448 const std::array<unsigned int, 2> vertices_0 = {
6449 {lines[quad_lines[i][f]]->vertex_index(0),
6450 lines[quad_lines[i][f]]->vertex_index(1)}};
6451
6452 const std::array<unsigned int, 2> vertices_1 = {
6453 {vertex_indices[quad_line_vertices_tri[i][f][0]],
6454 vertex_indices[quad_line_vertices_tri[i][f][1]]}};
6455
6456 const auto orientation =
6458 make_array_view(vertices_0),
6459 make_array_view(vertices_1));
6460
6461 if constexpr (library_build_mode ==
6463 {
6464 for (const auto i : vertices_0)
6465 s.insert(i);
6466 for (const auto i : vertices_1)
6467 s.insert(i);
6468 }
6469
6470 new_quad->set_line_orientation(f, orientation);
6471 }
6472 if constexpr (library_build_mode ==
6474 {
6475 AssertDimension(s.size(), 3);
6476 }
6477 }
6478 }
6479
6480 // fix orientation of lines of faces for quadrilaterals with
6481 // cheap algorithm
6482 if (reference_face_type == ReferenceCells::Quadrilateral)
6483 {
6484 static constexpr ::ndarray<unsigned int, 4, 2>
6485 quad_child_boundary_lines{
6486 {{{0, 2}}, {{1, 3}}, {{0, 1}}, {{2, 3}}}};
6487
6488 for (unsigned int i = 0; i < 4; ++i)
6489 for (unsigned int j = 0; j < 2; ++j)
6490 new_quads[quad_child_boundary_lines[i][j]]
6491 ->set_line_orientation(i, quad->line_orientation(i));
6492 }
6493
6494 quad->clear_user_flag();
6495 }
6496 }
6497
6499 cells_with_distorted_children;
6500
6503 for (unsigned int level = 0; level != triangulation.levels.size() - 1;
6504 ++level)
6505 {
6507 next_unused_hex = triangulation.begin_raw_hex(level + 1);
6508 Assert(hex == triangulation.end() ||
6509 hex->level() >= static_cast<int>(level),
6511
6512 for (; hex != triangulation.end() &&
6513 hex->level() == static_cast<int>(level);
6514 ++hex)
6515 {
6516 if (hex->refine_flag_set() ==
6518 continue;
6519
6520 const auto &reference_cell_type = hex->reference_cell();
6521
6522 const RefinementCase<dim> ref_case = hex->refine_flag_set();
6523 hex->clear_refine_flag();
6524 hex->set_refinement_case(ref_case);
6525
6526 unsigned int n_new_lines = 0;
6527 unsigned int n_new_quads = 0;
6528 unsigned int n_new_hexes = 0;
6529
6530 if (reference_cell_type == ReferenceCells::Hexahedron)
6531 {
6532 n_new_lines = 6;
6533 n_new_quads = 12;
6534 n_new_hexes = 8;
6535 }
6536 else if (reference_cell_type == ReferenceCells::Tetrahedron)
6537 {
6538 n_new_lines = 1;
6539 n_new_quads = 8;
6540 n_new_hexes = 8;
6541 }
6542 else
6544
6545 std::array<raw_line_iterator, 6> new_lines;
6546 for (unsigned int i = 0; i < n_new_lines; ++i)
6547 {
6548 new_lines[i] =
6549 triangulation.faces->lines
6550 .template next_free_single_object<1>(triangulation);
6551
6552 AssertIsNotUsed(new_lines[i]);
6553 new_lines[i]->set_used_flag();
6554 new_lines[i]->clear_user_flag();
6555 new_lines[i]->clear_user_data();
6556 new_lines[i]->clear_children();
6557 new_lines[i]->set_boundary_id_internal(
6559 new_lines[i]->set_manifold_id(hex->manifold_id());
6560 }
6561
6562 std::array<raw_quad_iterator, 12> new_quads;
6563 for (unsigned int i = 0; i < n_new_quads; ++i)
6564 {
6565 new_quads[i] =
6566 triangulation.faces->quads
6567 .template next_free_single_object<2>(triangulation);
6568
6569 auto &new_quad = new_quads[i];
6570
6571 // TODO: faces of children have the same type as the faces
6572 // of the parent
6573 triangulation.faces->set_quad_type(
6574 new_quad->index(),
6575 reference_cell_type.face_reference_cell(0));
6576
6577 AssertIsNotUsed(new_quad);
6578 new_quad->set_used_flag();
6579 new_quad->clear_user_flag();
6580 new_quad->clear_user_data();
6581 new_quad->clear_children();
6582 new_quad->set_boundary_id_internal(
6584 new_quad->set_manifold_id(hex->manifold_id());
6585 for (const auto j : new_quads[i]->line_indices())
6586 new_quad->set_line_orientation(
6588 }
6589
6590 // we always get 8 children per refined cell
6591 std::array<
6593 8>
6594 new_hexes;
6595 {
6596 for (unsigned int i = 0; i < n_new_hexes; ++i)
6597 {
6598 if (i % 2 == 0)
6599 next_unused_hex =
6600 triangulation.levels[level + 1]->cells.next_free_hex(
6601 triangulation, level + 1);
6602 else
6603 ++next_unused_hex;
6604
6605 new_hexes[i] = next_unused_hex;
6606
6607 auto &new_hex = new_hexes[i];
6608
6609 // children have the same type as the parent
6610 triangulation.levels[new_hex->level()]
6611 ->reference_cell[new_hex->index()] =
6612 reference_cell_type;
6613
6614 AssertIsNotUsed(new_hex);
6615 new_hex->set_used_flag();
6616 new_hex->clear_user_flag();
6617 new_hex->clear_user_data();
6618 new_hex->clear_children();
6619 new_hex->set_material_id(hex->material_id());
6620 new_hex->set_manifold_id(hex->manifold_id());
6621 new_hex->set_subdomain_id(hex->subdomain_id());
6622
6623 if (i % 2)
6624 new_hex->set_parent(hex->index());
6625
6626 // set the orientation flag to its default state for all
6627 // faces initially. later on go the other way round and
6628 // reset faces that are at the boundary of the mother cube
6629 for (const auto f : new_hex->face_indices())
6630 new_hex->set_combined_face_orientation(
6632 }
6633 for (unsigned int i = 0; i < n_new_hexes / 2; ++i)
6634 hex->set_children(2 * i, new_hexes[2 * i]->index());
6635 }
6636
6637 {
6638 // load vertex indices
6639 std::array<unsigned int, 27> vertex_indices = {};
6640
6641 {
6642 unsigned int k = 0;
6643
6644 // avoid a compiler warning by fixing the max number of
6645 // loop iterations to 8
6646 const unsigned int n_vertices =
6647 std::min(hex->n_vertices(), 8u);
6648 for (unsigned int i = 0; i < n_vertices; ++i)
6649 vertex_indices[k++] = hex->vertex_index(i);
6650
6651 const std::array<unsigned int, 12> line_indices =
6652 TriaAccessorImplementation::Implementation::
6653 get_line_indices_of_cell(*hex);
6654
6655 // For the tetrahedron the parent consists of the vertices
6656 // 0,1,2,3, the new vertices 4-9 are defined as the
6657 // midpoints of the edges: 4 -> (0,1), 5 -> (1,2), 6 ->
6658 // (2,0), 7 -> (0,3), 8 -> (1,3), 9 -> (2,3).
6659 // Order is defined by the reference cell, see
6660 // https://dealii.org/developer/doxygen/deal.II/group__simplex.html#simplex_reference_cells.
6661
6662 // Avoid a compiler warning by fixing the max number of loop
6663 // iterations to 12
6664 const unsigned int n_lines = std::min(hex->n_lines(), 12u);
6665 for (unsigned int l = 0; l < n_lines; ++l)
6666 {
6667 raw_line_iterator line(&triangulation,
6668 0,
6669 line_indices[l]);
6670 vertex_indices[k++] = line->child(0)->vertex_index(1);
6671 }
6672
6673 if (reference_cell_type == ReferenceCells::Hexahedron)
6674 {
6675 for (const unsigned int i : hex->face_indices())
6676 vertex_indices[k++] =
6677 hex->face(i)->child(0)->vertex_index(3);
6678
6679 // Set single new vertex in the center
6680 current_vertex =
6681 get_next_unused_vertex(current_vertex,
6682 triangulation.vertices_used);
6683 vertex_indices[k++] = current_vertex;
6684
6685 triangulation.vertices[current_vertex] =
6686 hex->center(true, true);
6687 }
6688 }
6689
6690 unsigned int chosen_line_tetrahedron = 0;
6691 // set up new lines
6692 if (reference_cell_type == ReferenceCells::Hexahedron)
6693 {
6694 static constexpr ::ndarray<unsigned int, 6, 2>
6695 new_line_vertices = {{{{22, 26}},
6696 {{26, 23}},
6697 {{20, 26}},
6698 {{26, 21}},
6699 {{24, 26}},
6700 {{26, 25}}}};
6701 for (unsigned int i = 0; i < n_new_lines; ++i)
6702 new_lines[i]->set_bounding_object_indices(
6703 {vertex_indices[new_line_vertices[i][0]],
6704 vertex_indices[new_line_vertices[i][1]]});
6705 }
6706 else if (reference_cell_type == ReferenceCells::Tetrahedron)
6707 {
6708 // in the tetrahedron case, we have the three
6709 // possibilities (6,8), (5,7), (4,9) -> pick the
6710 // shortest line to guarantee the best possible aspect
6711 // ratios
6712 static constexpr ::ndarray<unsigned int, 3, 2>
6713 new_line_vertices = {{{{6, 8}}, {{5, 7}}, {{4, 9}}}};
6714
6715 // choose line to cut either by refinement case or by
6716 // shortest distance between edge midpoints
6717 std::uint8_t refinement_choice = hex->refine_choice();
6718 if (refinement_choice ==
6719 static_cast<char>(
6721 {
6722 const auto &vertices = triangulation.get_vertices();
6723 double min_distance =
6724 std::numeric_limits<double>::infinity();
6725 for (unsigned int i = 0; i < new_line_vertices.size();
6726 ++i)
6727 {
6728 const double current_distance =
6729 vertices
6730 [vertex_indices[new_line_vertices[i][0]]]
6731 .distance(
6732 vertices[vertex_indices
6733 [new_line_vertices[i][1]]]);
6734 if (current_distance < min_distance)
6735 {
6736 chosen_line_tetrahedron = i;
6737 min_distance = current_distance;
6738 }
6739 }
6740 }
6741 else if (refinement_choice ==
6742 static_cast<char>(
6744 chosen_line_tetrahedron = 0;
6745 else if (refinement_choice ==
6746 static_cast<char>(
6748 chosen_line_tetrahedron = 1;
6749 else if (refinement_choice ==
6750 static_cast<char>(
6752 chosen_line_tetrahedron = 2;
6753 else
6755
6756 hex->set_refinement_case(
6757 RefinementCase<dim>(chosen_line_tetrahedron + 1));
6758
6759 new_lines[0]->set_bounding_object_indices(
6761 [new_line_vertices[chosen_line_tetrahedron][0]],
6763 [new_line_vertices[chosen_line_tetrahedron][1]]});
6764 }
6765
6766 // set up new quads
6767 {
6768 boost::container::small_vector<raw_line_iterator, 30>
6769 relevant_lines;
6770
6771 if (reference_cell_type == ReferenceCells::Hexahedron)
6772 {
6773 relevant_lines.resize(30);
6774 for (unsigned int f = 0, k = 0; f < 6; ++f)
6775 for (unsigned int c = 0; c < 4; ++c, ++k)
6776 {
6777 static constexpr ::
6778 ndarray<unsigned int, 4, 2>
6779 temp = {
6780 {{{0, 1}}, {{3, 0}}, {{0, 3}}, {{3, 2}}}};
6781
6782 relevant_lines[k] =
6783 hex->face(f)
6784 ->isotropic_child(
6786 standard_to_real_face_vertex(
6787 temp[c][0],
6788 hex->face_orientation(f),
6789 hex->face_flip(f),
6790 hex->face_rotation(f)))
6791 ->line(GeometryInfo<dim>::
6792 standard_to_real_face_line(
6793 temp[c][1],
6794 hex->face_orientation(f),
6795 hex->face_flip(f),
6796 hex->face_rotation(f)));
6797 }
6798
6799 for (unsigned int i = 0, k = 24; i < 6; ++i, ++k)
6800 relevant_lines[k] = new_lines[i];
6801 }
6802 else if (reference_cell_type == ReferenceCells::Tetrahedron)
6803 {
6804 // The order of the lines is defined by the ordering
6805 // of the faces of the reference cell and the ordering
6806 // of the lines within a face.
6807 // Each face is split into 4 child triangles, the
6808 // relevant lines are defined by the vertices of the
6809 // center triangles: 0 -> (4,5), 1 -> (5,6), 2 -> (4,6),
6810 // 3 -> (4,7), 4 -> (7,8), 5 -> (4,8), 6 -> (6,9), 7 ->
6811 // (9,7), 8 -> (6,7), 9 -> (5,8), 10 -> (8,9), 11 ->
6812 // (5,9), Line 12 is determined by
6813 // chosen_line_tetrahedron i.e. (6,8), (5,7) or (4,9)
6814
6815 relevant_lines.resize(13);
6816
6817 unsigned int k = 0;
6818 for (unsigned int f = 0; f < 4; ++f)
6819 for (unsigned int l = 0; l < 3; ++l, ++k)
6820 {
6821 // TODO: add comment
6822 static const std::
6823 array<std::array<unsigned int, 3>, 6>
6824 table = {{{{0, 1, 2}}, // 0
6825 {{1, 0, 2}},
6826 {{1, 2, 0}}, // 2
6827 {{0, 2, 1}},
6828 {{2, 0, 1}}, // 4
6829 {{2, 1, 0}}}};
6830
6831 const auto combined_orientation =
6832 hex->combined_face_orientation(f);
6833 relevant_lines[k] =
6834 hex->face(f)
6835 ->child(3 /*center triangle*/)
6836 ->line(table[combined_orientation][l]);
6837 }
6838
6839 relevant_lines[k++] = new_lines[0];
6840 AssertDimension(k, 13);
6841 }
6842 else
6844
6845 boost::container::small_vector<unsigned int, 30>
6846 relevant_line_indices(relevant_lines.size());
6847 for (unsigned int i = 0; i < relevant_line_indices.size();
6848 ++i)
6849 relevant_line_indices[i] = relevant_lines[i]->index();
6850
6851 // It is easierst to start at table cell_vertices,
6852 // there the vertices are listed which build up the
6853 // 8 child tets. To build the child tets, 8 new faces are
6854 // needed. The the vertices, which define the lines of these
6855 // new faces are listed in table_tet. Now only the
6856 // corresponding index of the lines and quads have to be
6857 // listed in new_quad_lines_tet and cell_quads_tet.
6858 const auto &new_quad_lines =
6859 hex->reference_cell().new_isotropic_child_face_lines(
6860 chosen_line_tetrahedron);
6861
6862 // The first 4 define the faces which cut off the
6863 // parent tetrahedron at the edges. the numbers are the
6864 // index of the relevant_lines defined above the last 4
6865 // faces cut apart the remaining octahedron, such that all
6866 // of these contain line number 12. the ordering of the
6867 // faces is arbitrary, the ordering within the faces has to
6868 // follow the righthand convention for triangles
6869 // The table defines the vertices of the lines above
6870 // see relevant_lines for mapping between line indices and
6871 // vertex numbering
6872 const auto &table =
6873 hex->reference_cell()
6874 .new_isotropic_child_face_line_vertices(
6875 chosen_line_tetrahedron);
6876
6877 static constexpr ::ndarray<unsigned int, 4, 2>
6878 representative_lines{
6879 {{{0, 2}}, {{2, 0}}, {{3, 3}}, {{1, 1}}}};
6880
6881 for (unsigned int q = 0; q < n_new_quads; ++q)
6882 {
6883 auto &new_quad = new_quads[q];
6884
6885 if (new_quad->n_lines() == 3)
6886 new_quad->set_bounding_object_indices(
6887 {relevant_line_indices[new_quad_lines[q][0]],
6888 relevant_line_indices[new_quad_lines[q][1]],
6889 relevant_line_indices[new_quad_lines[q][2]]});
6890 else if (new_quad->n_lines() == 4)
6891 new_quad->set_bounding_object_indices(
6892 {relevant_line_indices[new_quad_lines[q][0]],
6893 relevant_line_indices[new_quad_lines[q][1]],
6894 relevant_line_indices[new_quad_lines[q][2]],
6895 relevant_line_indices[new_quad_lines[q][3]]});
6896 else
6898
6899 // On hexes, we must only determine a single line
6900 // according to the representative_lines array above
6901 // (this saves expensive operations), for tets we do
6902 // all lines manually
6903 const unsigned int n_compute_lines =
6904 reference_cell_type == ReferenceCells::Hexahedron ?
6905 1 :
6906 new_quad->n_lines();
6907 for (unsigned int line = 0; line < n_compute_lines;
6908 ++line)
6909 {
6910 const unsigned int l =
6911 (reference_cell_type ==
6913 representative_lines[q % 4][0] :
6914 line;
6915
6916 const std::array<unsigned int, 2> vertices_0 = {
6917 {relevant_lines[new_quad_lines[q][l]]
6918 ->vertex_index(0),
6919 relevant_lines[new_quad_lines[q][l]]
6920 ->vertex_index(1)}};
6921
6922 const std::array<unsigned int, 2> vertices_1 = {
6923 {vertex_indices[table[q][l][0]],
6924 vertex_indices[table[q][l][1]]}};
6925
6926 const auto orientation =
6928 make_array_view(vertices_0),
6929 make_array_view(vertices_1));
6930
6931 new_quad->set_line_orientation(l, orientation);
6932
6933 // on a hex, inject the status of the current line
6934 // also to the line on the other quad along the
6935 // same direction
6936 if (reference_cell_type ==
6938 new_quads[representative_lines[q % 4][1] + q -
6939 (q % 4)]
6940 ->set_line_orientation(l, orientation);
6941 }
6942 }
6943 }
6944
6945 // set up new hex
6946 {
6947 std::array<int, 36> quad_indices;
6948
6949 if (reference_cell_type == ReferenceCells::Hexahedron)
6950 {
6951 for (unsigned int i = 0; i < n_new_quads; ++i)
6952 quad_indices[i] = new_quads[i]->index();
6953
6954 for (unsigned int f = 0, k = n_new_quads; f < 6; ++f)
6955 for (unsigned int c = 0; c < 4; ++c, ++k)
6956 quad_indices[k] =
6957 hex->face(f)->isotropic_child_index(
6959 c,
6960 hex->face_orientation(f),
6961 hex->face_flip(f),
6962 hex->face_rotation(f)));
6963 }
6964 else if (reference_cell_type == ReferenceCells::Tetrahedron)
6965 {
6966 // list of the indices of the surfaces which define the
6967 // 8 new tets. the indices 0-7 are the new quads defined
6968 // above (so 0-3 cut off the corners and 4-7 separate
6969 // the remaining octahedral), the indices between 8-11
6970 // are the children of the first face, from 12-15 of the
6971 // second, etc.
6972 for (unsigned int i = 0; i < n_new_quads; ++i)
6973 quad_indices[i] = new_quads[i]->index();
6974
6975 for (unsigned int f = 0, k = n_new_quads; f < 4; ++f)
6976 for (unsigned int c = 0; c < 4; ++c, ++k)
6977 {
6978 const auto combined_orientation =
6979 hex->combined_face_orientation(f);
6980 quad_indices[k] = hex->face(f)->child_index(
6981 (c == 3) ? 3 :
6982 reference_cell_type
6983 .standard_to_real_face_vertex(
6984 c, f, combined_orientation));
6985 }
6986 }
6987 else
6988 {
6990 }
6991
6992 // indices of the faces which define the new tets
6993 // the ordering of the tets is arbitrary
6994 // the first 4 determine the tets cutting of the corners
6995 // the last 4 are ordered after their appearance in the
6996 // faces.
6997 // the ordering within the faces is determined by
6998 // convention for the tetrahedron unit cell, see
6999 // cell_vertices_tet below
7000 const auto &cell_quads =
7001 hex->reference_cell().new_isotropic_child_cell_faces(
7002 chosen_line_tetrahedron);
7003
7004 for (unsigned int c = 0;
7005 c < GeometryInfo<dim>::max_children_per_cell;
7006 ++c)
7007 {
7008 auto &new_hex = new_hexes[c];
7009 const auto reference_cell = new_hex->reference_cell();
7010
7011 if (reference_cell == ReferenceCells::Tetrahedron)
7012 {
7013 new_hex->set_bounding_object_indices(
7014 {quad_indices[cell_quads[c][0]],
7015 quad_indices[cell_quads[c][1]],
7016 quad_indices[cell_quads[c][2]],
7017 quad_indices[cell_quads[c][3]]});
7018
7019
7020 // for tets, we need to go through the faces and
7021 // figure the orientation out the hard way
7022 for (const auto f : new_hex->face_indices())
7023 {
7024 const auto &face = new_hex->face(f);
7025
7026 Assert(face->n_vertices() == 3,
7028
7029 const std::array<unsigned int, 3> vertices_0 = {
7030 {face->vertex_index(0),
7031 face->vertex_index(1),
7032 face->vertex_index(2)}};
7033
7034 // the 8 child tets are each defined by 4
7035 // vertices the ordering of the tets has to be
7036 // consistent with above the ordering within the
7037 // tets is given by the reference tet i.e.
7038 // looking at the fifth line the first 3
7039 // vertices are given by face 11, the last
7040 // vertex is the remaining of the tet
7041 const auto new_hex_vertices =
7042 hex->reference_cell()
7043 .new_isotropic_child_cell_vertices(
7044 chosen_line_tetrahedron)[c];
7045
7046 // arrange after vertices of the faces of the
7047 // unit cell
7048 std::array<unsigned int, 3> vertices_1;
7049 for (unsigned int face_vertex_no :
7050 face->vertex_indices())
7051 {
7052 const auto cell_vertex_no =
7053 reference_cell.face_to_cell_vertices(
7054 f,
7055 face_vertex_no,
7057 vertices_1[face_vertex_no] = vertex_indices
7058 [new_hex_vertices[cell_vertex_no]];
7059 }
7060
7061 new_hex->set_combined_face_orientation(
7062 f,
7063 face->reference_cell()
7064 .get_combined_orientation(
7065 make_const_array_view(vertices_1),
7066 make_array_view(vertices_0)));
7067 }
7068 }
7069 else if (new_hex->n_faces() == 6)
7070 new_hex->set_bounding_object_indices(
7071 {quad_indices[cell_quads[c][0]],
7072 quad_indices[cell_quads[c][1]],
7073 quad_indices[cell_quads[c][2]],
7074 quad_indices[cell_quads[c][3]],
7075 quad_indices[cell_quads[c][4]],
7076 quad_indices[cell_quads[c][5]]});
7077 else
7079 }
7080
7081 // for hexes, we can simply inherit the orientation values
7082 // from the parent on the outer faces; the inner faces can
7083 // be skipped as their orientation is always the default
7084 // one set above
7085 static constexpr ::ndarray<unsigned int, 6, 4>
7086 face_to_child_indices_hex{{{{0, 2, 4, 6}},
7087 {{1, 3, 5, 7}},
7088 {{0, 1, 4, 5}},
7089 {{2, 3, 6, 7}},
7090 {{0, 1, 2, 3}},
7091 {{4, 5, 6, 7}}}};
7092 if (hex->n_faces() == 6)
7093 for (const auto f : hex->face_indices())
7094 {
7095 const auto combined_orientation =
7096 hex->combined_face_orientation(f);
7097 for (unsigned int c = 0; c < 4; ++c)
7098 new_hexes[face_to_child_indices_hex[f][c]]
7099 ->set_combined_face_orientation(
7100 f, combined_orientation);
7101 }
7102 }
7103 }
7104
7105 if (check_for_distorted_cells &&
7106 has_distorted_children<dim, spacedim>(hex))
7107 cells_with_distorted_children.distorted_cells.push_back(hex);
7108
7109 triangulation.signals.post_refinement_on_cell(hex);
7110 }
7111 }
7112
7113 triangulation.faces->quads.clear_user_data();
7114
7115 return cells_with_distorted_children;
7116 }
7117
7122 template <int spacedim>
7125 const bool check_for_distorted_cells)
7126 {
7127 const unsigned int dim = 3;
7128
7129 {
7130 bool flag_isotropic_mesh = true;
7132 cell = triangulation.begin(),
7133 endc = triangulation.end();
7134 for (; cell != endc; ++cell)
7135 if (cell->used())
7136 if (triangulation.get_anisotropic_refinement_flag() ||
7137 cell->refine_flag_set() == RefinementCase<dim>::cut_x ||
7138 cell->refine_flag_set() == RefinementCase<dim>::cut_y ||
7139 cell->refine_flag_set() == RefinementCase<dim>::cut_z ||
7140 cell->refine_flag_set() == RefinementCase<dim>::cut_xy ||
7141 cell->refine_flag_set() == RefinementCase<dim>::cut_xz ||
7142 cell->refine_flag_set() == RefinementCase<dim>::cut_yz)
7143 {
7144 flag_isotropic_mesh = false;
7145 break;
7146 }
7147
7148 if (flag_isotropic_mesh)
7149 return execute_refinement_isotropic(triangulation,
7150 check_for_distorted_cells);
7151 }
7152
7153 // this function probably also works for spacedim>3 but it
7154 // isn't tested. it will probably be necessary to pull new
7155 // vertices onto the manifold just as we do for the other
7156 // functions above.
7157 Assert(spacedim == 3, ExcNotImplemented());
7158
7159 // Check whether a new level is needed. We have to check for
7160 // this on the highest level only
7161 for (const auto &cell : triangulation.active_cell_iterators_on_level(
7162 triangulation.levels.size() - 1))
7163 if (cell->refine_flag_set())
7164 {
7165 triangulation.levels.push_back(
7166 std::make_unique<
7168 break;
7169 }
7170
7171
7172 // first clear user flags for quads and lines; we're going to
7173 // use them to flag which lines and quads need refinement
7174 triangulation.faces->quads.clear_user_data();
7175
7178 line != triangulation.end_line();
7179 ++line)
7180 line->clear_user_flag();
7183 quad != triangulation.end_quad();
7184 ++quad)
7185 quad->clear_user_flag();
7186
7187 // create an array of face refine cases. User indices of faces
7188 // will be set to values corresponding with indices in this
7189 // array.
7190 const RefinementCase<dim - 1> face_refinement_cases[4] = {
7191 RefinementCase<dim - 1>::no_refinement,
7192 RefinementCase<dim - 1>::cut_x,
7193 RefinementCase<dim - 1>::cut_y,
7194 RefinementCase<dim - 1>::cut_xy};
7195
7196 // check how much space is needed on every level. We need not
7197 // check the highest level since either
7198 // - on the highest level no cells are flagged for refinement
7199 // - there are, but prepare_refinement added another empty
7200 // level which then is the highest level
7201
7202 // variables to hold the number of newly to be created
7203 // vertices, lines and quads. as these are stored globally,
7204 // declare them outside the loop over al levels. we need lines
7205 // and quads in pairs for refinement of old ones and lines and
7206 // quads, that can be stored as single ones, as they are newly
7207 // created in the inside of an existing cell
7208 unsigned int needed_vertices = 0;
7209 unsigned int needed_lines_single = 0;
7210 unsigned int needed_quads_single = 0;
7211 unsigned int needed_lines_pair = 0;
7212 unsigned int needed_quads_pair = 0;
7213 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
7214 {
7215 // count number of flagged cells on this level and compute
7216 // how many new vertices and new lines will be needed
7217 unsigned int new_cells = 0;
7218
7219 for (const auto &acell :
7220 triangulation.active_cell_iterators_on_level(level))
7221 if (acell->refine_flag_set())
7222 {
7223 RefinementCase<dim> ref_case = acell->refine_flag_set();
7224
7225 // now for interior vertices, lines and quads, which
7226 // are needed in any case
7227 if (ref_case == RefinementCase<dim>::cut_x ||
7228 ref_case == RefinementCase<dim>::cut_y ||
7229 ref_case == RefinementCase<dim>::cut_z)
7230 {
7231 ++needed_quads_single;
7232 new_cells += 2;
7233 triangulation.anisotropic_refinement = true;
7234 }
7235 else if (ref_case == RefinementCase<dim>::cut_xy ||
7236 ref_case == RefinementCase<dim>::cut_xz ||
7237 ref_case == RefinementCase<dim>::cut_yz)
7238 {
7239 ++needed_lines_single;
7240 needed_quads_single += 4;
7241 new_cells += 4;
7242 triangulation.anisotropic_refinement = true;
7243 }
7244 else if (ref_case == RefinementCase<dim>::cut_xyz)
7245 {
7246 ++needed_vertices;
7247 needed_lines_single += 6;
7248 needed_quads_single += 12;
7249 new_cells += 8;
7250 }
7251 else
7252 {
7253 // we should never get here
7255 }
7256
7257 // mark all faces for refinement; checking locally
7258 // if and how the neighbor would like to refine
7259 // these is difficult so we only flag them and after
7260 // visiting all cells, we decide which faces need
7261 // which refinement;
7262 for (const unsigned int face :
7264 {
7266 aface = acell->face(face);
7267 // get the RefineCase this faces has for the
7268 // given RefineCase of the cell
7269 RefinementCase<dim - 1> face_ref_case =
7271 ref_case,
7272 face,
7273 acell->face_orientation(face),
7274 acell->face_flip(face),
7275 acell->face_rotation(face));
7276 // only do something, if this face has to be
7277 // refined
7278 if (face_ref_case)
7279 {
7280 if (face_ref_case ==
7282 {
7283 if (aface->n_active_descendants() < 4)
7284 // we use user_flags to denote needed
7285 // isotropic refinement
7286 aface->set_user_flag();
7287 }
7288 else if (aface->refinement_case() != face_ref_case)
7289 // we use user_indices to denote needed
7290 // anisotropic refinement. note, that we
7291 // can have at most one anisotropic
7292 // refinement case for this face, as
7293 // otherwise prepare_refinement() would
7294 // have changed one of the cells to yield
7295 // isotropic refinement at this
7296 // face. therefore we set the user_index
7297 // uniquely
7298 {
7299 Assert(aface->refinement_case() ==
7301 dim - 1>::isotropic_refinement ||
7302 aface->refinement_case() ==
7305 aface->set_user_index(face_ref_case);
7306 }
7307 }
7308 } // for all faces
7309
7310 // flag all lines, that have to be refined
7311 for (unsigned int line = 0;
7312 line < GeometryInfo<dim>::lines_per_cell;
7313 ++line)
7315 line) &&
7316 !acell->line(line)->has_children())
7317 acell->line(line)->set_user_flag();
7318
7319 } // if refine_flag set and for all cells on this level
7320
7321
7322 // count number of used cells on the next higher level
7323 const unsigned int used_cells =
7324 std::count(triangulation.levels[level + 1]->cells.used.begin(),
7325 triangulation.levels[level + 1]->cells.used.end(),
7326 true);
7327
7328
7329 // reserve space for the used_cells cells already existing
7330 // on the next higher level as well as for the
7331 // 8*flagged_cells that will be created on that level
7332 reserve_space(*triangulation.levels[level + 1],
7333 used_cells + new_cells,
7334 spacedim);
7335 // reserve space for 8*flagged_cells new hexes on the next
7336 // higher level
7337 reserve_space(triangulation.levels[level + 1]->cells, new_cells);
7338 } // for all levels
7339 // now count the quads and lines which were flagged for
7340 // refinement
7343 quad != triangulation.end_quad();
7344 ++quad)
7345 {
7346 if (quad->user_flag_set())
7347 {
7348 // isotropic refinement: 1 interior vertex, 4 quads
7349 // and 4 interior lines. we store the interior lines
7350 // in pairs in case the face is already or will be
7351 // refined anisotropically
7352 needed_quads_pair += 4;
7353 needed_lines_pair += 4;
7354 needed_vertices += 1;
7355 }
7356 if (quad->user_index())
7357 {
7358 // anisotropic refinement: 1 interior
7359 // line and two quads
7360 needed_quads_pair += 2;
7361 needed_lines_single += 1;
7362 // there is a kind of complicated situation here which
7363 // requires our attention. if the quad is refined
7364 // isotropcally, two of the interior lines will get a
7365 // new mother line - the interior line of our
7366 // anisotropically refined quad. if those two lines
7367 // are not consecutive, we cannot do so and have to
7368 // replace them by two lines that are consecutive. we
7369 // try to avoid that situation, but it may happen
7370 // nevertheless through repeated refinement and
7371 // coarsening. thus we have to check here, as we will
7372 // need some additional space to store those new lines
7373 // in case we need them...
7374 if (quad->has_children())
7375 {
7376 Assert(quad->refinement_case() ==
7379 if ((face_refinement_cases[quad->user_index()] ==
7381 (quad->child(0)->line_index(1) + 1 !=
7382 quad->child(2)->line_index(1))) ||
7383 (face_refinement_cases[quad->user_index()] ==
7385 (quad->child(0)->line_index(3) + 1 !=
7386 quad->child(1)->line_index(3))))
7387 needed_lines_pair += 2;
7388 }
7389 }
7390 }
7391
7394 line != triangulation.end_line();
7395 ++line)
7396 if (line->user_flag_set())
7397 {
7398 needed_lines_pair += 2;
7399 needed_vertices += 1;
7400 }
7401
7402 // reserve space for needed_lines new lines stored in pairs
7403 reserve_space(triangulation.faces->lines,
7404 needed_lines_pair,
7405 needed_lines_single);
7406 // reserve space for needed_quads new quads stored in pairs
7408 needed_quads_pair,
7409 needed_quads_single);
7410 reserve_space(triangulation.faces->quads,
7411 needed_quads_pair,
7412 needed_quads_single);
7413
7414
7415 // add to needed vertices how many vertices are already in use
7416 needed_vertices += std::count(triangulation.vertices_used.begin(),
7417 triangulation.vertices_used.end(),
7418 true);
7419 // if we need more vertices: create them, if not: leave the
7420 // array as is, since shrinking is not really possible because
7421 // some of the vertices at the end may be in use
7422 if (needed_vertices > triangulation.vertices.size())
7423 {
7424 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
7425 triangulation.vertices_used.resize(needed_vertices, false);
7426 }
7427
7428
7429 //-----------------------------------------
7430 // Before we start with the actual refinement, we do some
7431 // sanity checks if in debug mode. especially, we try to catch
7432 // the notorious problem with lines being twice refined,
7433 // i.e. there are cells adjacent at one line ("around the
7434 // edge", but not at a face), with two cells differing by more
7435 // than one refinement level
7436 //
7437 // this check is very simple to implement here, since we have
7438 // all lines flagged if they shall be refined
7439 if constexpr (running_in_debug_mode())
7440 {
7441 for (const auto &cell : triangulation.active_cell_iterators())
7442 if (!cell->refine_flag_set())
7443 for (unsigned int line = 0;
7444 line < GeometryInfo<dim>::lines_per_cell;
7445 ++line)
7446 if (cell->line(line)->has_children())
7447 for (unsigned int c = 0; c < 2; ++c)
7448 Assert(cell->line(line)->child(c)->user_flag_set() ==
7449 false,
7451 }
7452
7453 //-----------------------------------------
7454 // Do refinement on every level
7455 //
7456 // To make life a bit easier, we first refine those lines and
7457 // quads that were flagged for refinement and then compose the
7458 // newly to be created cells.
7459 //
7460 // index of next unused vertex
7461 unsigned int next_unused_vertex = 0;
7462
7463 // first for lines
7464 {
7465 // only active objects can be refined further
7468 endl = triangulation.end_line();
7470 next_unused_line = triangulation.begin_raw_line();
7471
7472 for (; line != endl; ++line)
7473 if (line->user_flag_set())
7474 {
7475 // this line needs to be refined
7476
7477 // find the next unused vertex and set it
7478 // appropriately
7479 while (triangulation.vertices_used[next_unused_vertex] == true)
7480 ++next_unused_vertex;
7481 Assert(
7482 next_unused_vertex < triangulation.vertices.size(),
7483 ExcMessage(
7484 "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."));
7485 triangulation.vertices_used[next_unused_vertex] = true;
7486
7487 triangulation.vertices[next_unused_vertex] = line->center(true);
7488
7489 // now that we created the right point, make up the
7490 // two child lines (++ takes care of the end of the
7491 // vector)
7492 next_unused_line =
7493 triangulation.faces->lines.template next_free_pair_object<1>(
7495 Assert(next_unused_line.state() == IteratorState::valid,
7497
7498 // now we found two consecutive unused lines, such
7499 // that the children of a line will be consecutive.
7500 // then set the child pointer of the present line
7501 line->set_children(0, next_unused_line->index());
7502
7503 // set the two new lines
7505 children[2] = {next_unused_line, ++next_unused_line};
7506
7507 // some tests; if any of the iterators should be
7508 // invalid, then already dereferencing will fail
7509 AssertIsNotUsed(children[0]);
7510 AssertIsNotUsed(children[1]);
7511
7512 children[0]->set_bounding_object_indices(
7513 {line->vertex_index(0), next_unused_vertex});
7514 children[1]->set_bounding_object_indices(
7515 {next_unused_vertex, line->vertex_index(1)});
7516
7517 children[0]->set_used_flag();
7518 children[1]->set_used_flag();
7519 children[0]->clear_children();
7520 children[1]->clear_children();
7521 children[0]->clear_user_data();
7522 children[1]->clear_user_data();
7523 children[0]->clear_user_flag();
7524 children[1]->clear_user_flag();
7525
7526 children[0]->set_boundary_id_internal(line->boundary_id());
7527 children[1]->set_boundary_id_internal(line->boundary_id());
7528
7529 children[0]->set_manifold_id(line->manifold_id());
7530 children[1]->set_manifold_id(line->manifold_id());
7531
7532 // finally clear flag
7533 // indicating the need
7534 // for refinement
7535 line->clear_user_flag();
7536 }
7537 }
7538
7539
7540 //-------------------------------------
7541 // now refine marked quads
7542 //-------------------------------------
7543
7544 // here we encounter several cases:
7545
7546 // a) the quad is unrefined and shall be refined isotropically
7547
7548 // b) the quad is unrefined and shall be refined
7549 // anisotropically
7550
7551 // c) the quad is unrefined and shall be refined both
7552 // anisotropically and isotropically (this is reduced to case
7553 // b) and then case b) for the children again)
7554
7555 // d) the quad is refined anisotropically and shall be refined
7556 // isotropically (this is reduced to case b) for the
7557 // anisotropic children)
7558
7559 // e) the quad is refined isotropically and shall be refined
7560 // anisotropically (this is transformed to case c), however we
7561 // might have to renumber/rename children...)
7562
7563 // we need a loop in cases c) and d), as the anisotropic
7564 // children might have a lower index than the mother quad
7565 for (unsigned int loop = 0; loop < 2; ++loop)
7566 {
7567 // usually, only active objects can be refined
7568 // further. however, in cases d) and e) that is not true,
7569 // so we have to use 'normal' iterators here
7571 quad = triangulation.begin_quad(),
7572 endq = triangulation.end_quad();
7574 next_unused_line = triangulation.begin_raw_line();
7576 next_unused_quad = triangulation.begin_raw_quad();
7577
7578 for (; quad != endq; ++quad)
7579 {
7580 if (quad->user_index())
7581 {
7582 RefinementCase<dim - 1> aniso_quad_ref_case =
7583 face_refinement_cases[quad->user_index()];
7584 // there is one unlikely event here, where we
7585 // already have refind the face: if the face was
7586 // refined anisotropically and we want to refine
7587 // it isotropically, both children are flagged for
7588 // anisotropic refinement. however, if those
7589 // children were already flagged for anisotropic
7590 // refinement, they might already be processed and
7591 // refined.
7592 if (aniso_quad_ref_case == quad->refinement_case())
7593 continue;
7594
7595 Assert(quad->refinement_case() ==
7597 quad->refinement_case() ==
7600
7601 // this quad needs to be refined anisotropically
7602 Assert(quad->user_index() ==
7604 quad->user_index() ==
7607
7608 // make the new line interior to the quad
7610 new_line;
7611
7612 new_line =
7613 triangulation.faces->lines
7614 .template next_free_single_object<1>(triangulation);
7615 AssertIsNotUsed(new_line);
7616
7617 // first collect the
7618 // indices of the vertices:
7619 // *--1--*
7620 // | | |
7621 // | | | cut_x
7622 // | | |
7623 // *--0--*
7624 //
7625 // *-----*
7626 // | |
7627 // 0-----1 cut_y
7628 // | |
7629 // *-----*
7630 unsigned int vertex_indices[2];
7631 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
7632 {
7633 vertex_indices[0] =
7634 quad->line(2)->child(0)->vertex_index(1);
7635 vertex_indices[1] =
7636 quad->line(3)->child(0)->vertex_index(1);
7637 }
7638 else
7639 {
7640 vertex_indices[0] =
7641 quad->line(0)->child(0)->vertex_index(1);
7642 vertex_indices[1] =
7643 quad->line(1)->child(0)->vertex_index(1);
7644 }
7645
7646 new_line->set_bounding_object_indices(
7648 new_line->set_used_flag();
7649 new_line->clear_user_flag();
7650 new_line->clear_user_data();
7651 new_line->clear_children();
7652 new_line->set_boundary_id_internal(quad->boundary_id());
7653 new_line->set_manifold_id(quad->manifold_id());
7654
7655 // find some space (consecutive) for the two newly
7656 // to be created quads.
7658 new_quads[2];
7659
7660 next_unused_quad =
7661 triangulation.faces->quads
7662 .template next_free_pair_object<2>(triangulation);
7663 new_quads[0] = next_unused_quad;
7664 AssertIsNotUsed(new_quads[0]);
7665
7666 ++next_unused_quad;
7667 new_quads[1] = next_unused_quad;
7668 AssertIsNotUsed(new_quads[1]);
7669
7670 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
7671 {
7672 new_quads[0]->set_bounding_object_indices(
7673 {static_cast<int>(quad->line_index(0)),
7674 new_line->index(),
7675 quad->line(2)
7676 ->child(
7677 child_line_index(0, quad->line_orientation(2)))
7678 ->index(),
7679 quad->line(3)
7680 ->child(
7681 child_line_index(0, quad->line_orientation(3)))
7682 ->index()});
7683 new_quads[1]->set_bounding_object_indices(
7684 {new_line->index(),
7685 static_cast<int>(quad->line_index(1)),
7686 quad->line(2)
7687 ->child(
7688 child_line_index(1, quad->line_orientation(2)))
7689 ->index(),
7690 quad->line(3)
7691 ->child(
7692 child_line_index(1, quad->line_orientation(3)))
7693 ->index()});
7694 }
7695 else
7696 {
7697 new_quads[0]->set_bounding_object_indices(
7698 {quad->line(0)
7699 ->child(
7700 child_line_index(0, quad->line_orientation(0)))
7701 ->index(),
7702 quad->line(1)
7703 ->child(
7704 child_line_index(0, quad->line_orientation(1)))
7705 ->index(),
7706 static_cast<int>(quad->line_index(2)),
7707 new_line->index()});
7708 new_quads[1]->set_bounding_object_indices(
7709 {quad->line(0)
7710 ->child(
7711 child_line_index(1, quad->line_orientation(0)))
7712 ->index(),
7713 quad->line(1)
7714 ->child(
7715 child_line_index(1, quad->line_orientation(1)))
7716 ->index(),
7717 new_line->index(),
7718 static_cast<int>(quad->line_index(3))});
7719 }
7720
7721 for (const auto &new_quad : new_quads)
7722 {
7723 new_quad->set_used_flag();
7724 new_quad->clear_user_flag();
7725 new_quad->clear_user_data();
7726 new_quad->clear_children();
7727 new_quad->set_boundary_id_internal(quad->boundary_id());
7728 new_quad->set_manifold_id(quad->manifold_id());
7729 // set all line orientations to true, change
7730 // this after the loop, as we have to consider
7731 // different lines for each child
7732 for (unsigned int j = 0;
7733 j < GeometryInfo<dim>::lines_per_face;
7734 ++j)
7735 new_quad->set_line_orientation(
7737 }
7738 // now set the line orientation of children of
7739 // outer lines correctly, the lines in the
7740 // interior of the refined quad are automatically
7741 // oriented conforming to the standard
7742 new_quads[0]->set_line_orientation(
7743 0, quad->line_orientation(0));
7744 new_quads[0]->set_line_orientation(
7745 2, quad->line_orientation(2));
7746 new_quads[1]->set_line_orientation(
7747 1, quad->line_orientation(1));
7748 new_quads[1]->set_line_orientation(
7749 3, quad->line_orientation(3));
7750 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
7751 {
7752 new_quads[0]->set_line_orientation(
7753 3, quad->line_orientation(3));
7754 new_quads[1]->set_line_orientation(
7755 2, quad->line_orientation(2));
7756 }
7757 else
7758 {
7759 new_quads[0]->set_line_orientation(
7760 1, quad->line_orientation(1));
7761 new_quads[1]->set_line_orientation(
7762 0, quad->line_orientation(0));
7763 }
7764
7765 // test, whether this face is refined
7766 // isotropically already. if so, set the correct
7767 // children pointers.
7768 if (quad->refinement_case() ==
7769 RefinementCase<dim - 1>::cut_xy)
7770 {
7771 // we will put a new refinemnt level of
7772 // anisotropic refinement between the
7773 // unrefined and isotropically refined quad
7774 // ending up with the same fine quads but
7775 // introducing anisotropically refined ones as
7776 // children of the unrefined quad and mother
7777 // cells of the original fine ones.
7778
7779 // this process includes the creation of a new
7780 // middle line which we will assign as the
7781 // mother line of two of the existing inner
7782 // lines. If those inner lines are not
7783 // consecutive in memory, we won't find them
7784 // later on, so we have to create new ones
7785 // instead and replace all occurrences of the
7786 // old ones with those new ones. As this is
7787 // kind of ugly, we hope we don't have to do
7788 // it often...
7790 old_child[2];
7791 if (aniso_quad_ref_case ==
7793 {
7794 old_child[0] = quad->child(0)->line(1);
7795 old_child[1] = quad->child(2)->line(1);
7796 }
7797 else
7798 {
7799 Assert(aniso_quad_ref_case ==
7802
7803 old_child[0] = quad->child(0)->line(3);
7804 old_child[1] = quad->child(1)->line(3);
7805 }
7806
7807 if (old_child[0]->index() + 1 != old_child[1]->index())
7808 {
7809 // this is exactly the ugly case we talked
7810 // about. so, no complaining, lets get
7811 // two new lines and copy all info
7812 typename Triangulation<dim,
7813 spacedim>::raw_line_iterator
7814 new_child[2];
7815
7816 new_child[0] = new_child[1] =
7817 triangulation.faces->lines
7818 .template next_free_pair_object<1>(
7820 ++new_child[1];
7821
7822 new_child[0]->set_used_flag();
7823 new_child[1]->set_used_flag();
7824
7825 const int old_index_0 = old_child[0]->index(),
7826 old_index_1 = old_child[1]->index(),
7827 new_index_0 = new_child[0]->index(),
7828 new_index_1 = new_child[1]->index();
7829
7830 // loop over all quads and replace the old
7831 // lines
7832 for (unsigned int q = 0;
7833 q < triangulation.faces->quads.n_objects();
7834 ++q)
7835 for (unsigned int l = 0;
7836 l < GeometryInfo<dim>::lines_per_face;
7837 ++l)
7838 {
7839 const int this_index =
7840 triangulation.faces->quads
7841 .get_bounding_object_indices(q)[l];
7842 if (this_index == old_index_0)
7843 triangulation.faces->quads
7844 .get_bounding_object_indices(q)[l] =
7845 new_index_0;
7846 else if (this_index == old_index_1)
7847 triangulation.faces->quads
7848 .get_bounding_object_indices(q)[l] =
7849 new_index_1;
7850 }
7851 // now we have to copy all information of
7852 // the two lines
7853 for (unsigned int i = 0; i < 2; ++i)
7854 {
7855 Assert(!old_child[i]->has_children(),
7857
7858 new_child[i]->set_bounding_object_indices(
7859 {old_child[i]->vertex_index(0),
7860 old_child[i]->vertex_index(1)});
7861 new_child[i]->set_boundary_id_internal(
7862 old_child[i]->boundary_id());
7863 new_child[i]->set_manifold_id(
7864 old_child[i]->manifold_id());
7865 new_child[i]->set_user_index(
7866 old_child[i]->user_index());
7867 if (old_child[i]->user_flag_set())
7868 new_child[i]->set_user_flag();
7869 else
7870 new_child[i]->clear_user_flag();
7871
7872 new_child[i]->clear_children();
7873
7874 old_child[i]->clear_user_flag();
7875 old_child[i]->clear_user_index();
7876 old_child[i]->clear_used_flag();
7877 }
7878 }
7879 // now that we cared about the lines, go on
7880 // with the quads themselves, where we might
7881 // encounter similar situations...
7882 if (aniso_quad_ref_case ==
7884 {
7885 new_line->set_children(
7886 0, quad->child(0)->line_index(1));
7887 Assert(new_line->child(1) ==
7888 quad->child(2)->line(1),
7890 // now evereything is quite
7891 // complicated. we have the children
7892 // numbered according to
7893 //
7894 // *---*---*
7895 // |n+2|n+3|
7896 // *---*---*
7897 // | n |n+1|
7898 // *---*---*
7899 //
7900 // from the original isotropic
7901 // refinement. we have to reorder them as
7902 //
7903 // *---*---*
7904 // |n+1|n+3|
7905 // *---*---*
7906 // | n |n+2|
7907 // *---*---*
7908 //
7909 // such that n and n+1 are consecutive
7910 // children of m and n+2 and n+3 are
7911 // consecutive children of m+1, where m
7912 // and m+1 are given as in
7913 //
7914 // *---*---*
7915 // | | |
7916 // | m |m+1|
7917 // | | |
7918 // *---*---*
7919 //
7920 // this is a bit ugly, of course: loop
7921 // over all cells on all levels and look
7922 // for faces n+1 (switch_1) and n+2
7923 // (switch_2).
7924 const typename Triangulation<dim, spacedim>::
7925 quad_iterator switch_1 = quad->child(1),
7926 switch_2 = quad->child(2);
7927 const int switch_1_index = switch_1->index();
7928 const int switch_2_index = switch_2->index();
7929 for (unsigned int l = 0;
7930 l < triangulation.levels.size();
7931 ++l)
7932 for (unsigned int h = 0;
7933 h <
7934 triangulation.levels[l]->cells.n_objects();
7935 ++h)
7936 for (const unsigned int q :
7938 {
7939 const int face_index =
7941 ->cells.get_bounding_object_indices(
7942 h)[q];
7943 if (face_index == switch_1_index)
7944 triangulation.levels[l]
7945 ->cells.get_bounding_object_indices(
7946 h)[q] = switch_2_index;
7947 else if (face_index == switch_2_index)
7948 triangulation.levels[l]
7949 ->cells.get_bounding_object_indices(
7950 h)[q] = switch_1_index;
7951 }
7952 // now we have to copy all information of
7953 // the two quads
7954 const unsigned int switch_1_lines[4] = {
7955 switch_1->line_index(0),
7956 switch_1->line_index(1),
7957 switch_1->line_index(2),
7958 switch_1->line_index(3)};
7960 switch_1_line_orientations[4] = {
7961 switch_1->line_orientation(0),
7962 switch_1->line_orientation(1),
7963 switch_1->line_orientation(2),
7964 switch_1->line_orientation(3)};
7965 const types::boundary_id switch_1_boundary_id =
7966 switch_1->boundary_id();
7967 const unsigned int switch_1_user_index =
7968 switch_1->user_index();
7969 const bool switch_1_user_flag =
7970 switch_1->user_flag_set();
7971 const RefinementCase<dim - 1>
7972 switch_1_refinement_case =
7973 switch_1->refinement_case();
7974 const int switch_1_first_child_pair =
7975 (switch_1_refinement_case ?
7976 switch_1->child_index(0) :
7977 -1);
7978 const int switch_1_second_child_pair =
7979 (switch_1_refinement_case ==
7980 RefinementCase<dim - 1>::cut_xy ?
7981 switch_1->child_index(2) :
7982 -1);
7983
7984 switch_1->set_bounding_object_indices(
7985 {switch_2->line_index(0),
7986 switch_2->line_index(1),
7987 switch_2->line_index(2),
7988 switch_2->line_index(3)});
7989 switch_1->set_line_orientation(
7990 0, switch_2->line_orientation(0));
7991 switch_1->set_line_orientation(
7992 1, switch_2->line_orientation(1));
7993 switch_1->set_line_orientation(
7994 2, switch_2->line_orientation(2));
7995 switch_1->set_line_orientation(
7996 3, switch_2->line_orientation(3));
7997 switch_1->set_boundary_id_internal(
7998 switch_2->boundary_id());
7999 switch_1->set_manifold_id(switch_2->manifold_id());
8000 switch_1->set_user_index(switch_2->user_index());
8001 if (switch_2->user_flag_set())
8002 switch_1->set_user_flag();
8003 else
8004 switch_1->clear_user_flag();
8005 switch_1->clear_refinement_case();
8006 switch_1->set_refinement_case(
8007 switch_2->refinement_case());
8008 switch_1->clear_children();
8009 if (switch_2->refinement_case())
8010 switch_1->set_children(0,
8011 switch_2->child_index(0));
8012 if (switch_2->refinement_case() ==
8013 RefinementCase<dim - 1>::cut_xy)
8014 switch_1->set_children(2,
8015 switch_2->child_index(2));
8016
8017 switch_2->set_bounding_object_indices(
8018 {switch_1_lines[0],
8019 switch_1_lines[1],
8020 switch_1_lines[2],
8021 switch_1_lines[3]});
8022 switch_2->set_line_orientation(
8023 0, switch_1_line_orientations[0]);
8024 switch_2->set_line_orientation(
8025 1, switch_1_line_orientations[1]);
8026 switch_2->set_line_orientation(
8027 2, switch_1_line_orientations[2]);
8028 switch_2->set_line_orientation(
8029 3, switch_1_line_orientations[3]);
8030 switch_2->set_boundary_id_internal(
8031 switch_1_boundary_id);
8032 switch_2->set_manifold_id(switch_1->manifold_id());
8033 switch_2->set_user_index(switch_1_user_index);
8034 if (switch_1_user_flag)
8035 switch_2->set_user_flag();
8036 else
8037 switch_2->clear_user_flag();
8038 switch_2->clear_refinement_case();
8039 switch_2->set_refinement_case(
8040 switch_1_refinement_case);
8041 switch_2->clear_children();
8042 switch_2->set_children(0,
8043 switch_1_first_child_pair);
8044 switch_2->set_children(2,
8045 switch_1_second_child_pair);
8046
8047 new_quads[0]->set_refinement_case(
8049 new_quads[0]->set_children(0, quad->child_index(0));
8050 new_quads[1]->set_refinement_case(
8052 new_quads[1]->set_children(0, quad->child_index(2));
8053 }
8054 else
8055 {
8056 new_quads[0]->set_refinement_case(
8058 new_quads[0]->set_children(0, quad->child_index(0));
8059 new_quads[1]->set_refinement_case(
8061 new_quads[1]->set_children(0, quad->child_index(2));
8062 new_line->set_children(
8063 0, quad->child(0)->line_index(3));
8064 Assert(new_line->child(1) ==
8065 quad->child(1)->line(3),
8067 }
8068 quad->clear_children();
8069 }
8070
8071 // note these quads as children to the present one
8072 quad->set_children(0, new_quads[0]->index());
8073
8074 quad->set_refinement_case(aniso_quad_ref_case);
8075
8076 // finally clear flag indicating the need for
8077 // refinement
8078 quad->clear_user_data();
8079 } // if (anisotropic refinement)
8080
8081 if (quad->user_flag_set())
8082 {
8083 // this quad needs to be refined isotropically
8084
8085 // first of all: we only get here in the first run
8086 // of the loop
8087 Assert(loop == 0, ExcInternalError());
8088
8089 // find the next unused vertex. we'll need this in
8090 // any case
8091 while (triangulation.vertices_used[next_unused_vertex] ==
8092 true)
8093 ++next_unused_vertex;
8094 Assert(
8095 next_unused_vertex < triangulation.vertices.size(),
8096 ExcMessage(
8097 "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."));
8098
8099 // now: if the quad is refined anisotropically
8100 // already, set the anisotropic refinement flag
8101 // for both children. Additionally, we have to
8102 // refine the inner line, as it is an outer line
8103 // of the two (anisotropic) children
8104 const RefinementCase<dim - 1> quad_ref_case =
8105 quad->refinement_case();
8106
8107 if (quad_ref_case == RefinementCase<dim - 1>::cut_x ||
8108 quad_ref_case == RefinementCase<dim - 1>::cut_y)
8109 {
8110 // set the 'opposite' refine case for children
8111 quad->child(0)->set_user_index(
8112 RefinementCase<dim - 1>::cut_xy - quad_ref_case);
8113 quad->child(1)->set_user_index(
8114 RefinementCase<dim - 1>::cut_xy - quad_ref_case);
8115 // refine the inner line
8117 middle_line;
8118 if (quad_ref_case == RefinementCase<dim - 1>::cut_x)
8119 middle_line = quad->child(0)->line(1);
8120 else
8121 middle_line = quad->child(0)->line(3);
8122
8123 // if the face has been refined
8124 // anisotropically in the last refinement step
8125 // it might be, that it is flagged already and
8126 // that the middle line is thus refined
8127 // already. if not create children.
8128 if (!middle_line->has_children())
8129 {
8130 // set the middle vertex
8131 // appropriately. double refinement of
8132 // quads can only happen in the interior
8133 // of the domain, so we need not care
8134 // about boundary quads here
8135 triangulation.vertices[next_unused_vertex] =
8136 middle_line->center(true);
8137 triangulation.vertices_used[next_unused_vertex] =
8138 true;
8139
8140 // now search a slot for the two
8141 // child lines
8142 next_unused_line =
8143 triangulation.faces->lines
8144 .template next_free_pair_object<1>(
8146
8147 // set the child pointer of the present
8148 // line
8149 middle_line->set_children(
8150 0, next_unused_line->index());
8151
8152 // set the two new lines
8153 const typename Triangulation<dim, spacedim>::
8154 raw_line_iterator children[2] = {
8155 next_unused_line, ++next_unused_line};
8156
8157 // some tests; if any of the iterators
8158 // should be invalid, then already
8159 // dereferencing will fail
8160 AssertIsNotUsed(children[0]);
8161 AssertIsNotUsed(children[1]);
8162
8163 children[0]->set_bounding_object_indices(
8164 {middle_line->vertex_index(0),
8165 next_unused_vertex});
8166 children[1]->set_bounding_object_indices(
8167 {next_unused_vertex,
8168 middle_line->vertex_index(1)});
8169
8170 children[0]->set_used_flag();
8171 children[1]->set_used_flag();
8172 children[0]->clear_children();
8173 children[1]->clear_children();
8174 children[0]->clear_user_data();
8175 children[1]->clear_user_data();
8176 children[0]->clear_user_flag();
8177 children[1]->clear_user_flag();
8178
8179 children[0]->set_boundary_id_internal(
8180 middle_line->boundary_id());
8181 children[1]->set_boundary_id_internal(
8182 middle_line->boundary_id());
8183
8184 children[0]->set_manifold_id(
8185 middle_line->manifold_id());
8186 children[1]->set_manifold_id(
8187 middle_line->manifold_id());
8188 }
8189 // now remove the flag from the quad and go to
8190 // the next quad, the actual refinement of the
8191 // quad takes place later on in this pass of
8192 // the loop or in the next one
8193 quad->clear_user_flag();
8194 continue;
8195 } // if (several refinement cases)
8196
8197 // if we got here, we have an unrefined quad and
8198 // have to do the usual work like in an purely
8199 // isotropic refinement
8200 Assert(quad_ref_case ==
8203
8204 // set the middle vertex appropriately: it might be that
8205 // the quad itself is not at the boundary, but that one of
8206 // its lines actually is. in this case, the newly created
8207 // vertices at the centers of the lines are not
8208 // necessarily the mean values of the adjacent vertices,
8209 // so do not compute the new vertex as the mean value of
8210 // the 4 vertices of the face, but rather as a weighted
8211 // mean value of the 8 vertices which we already have (the
8212 // four old ones, and the four ones inserted as middle
8213 // points for the four lines). summing up some more points
8214 // is generally cheaper than first asking whether one of
8215 // the lines is at the boundary
8216 //
8217 // note that the exact weights are chosen such as to
8218 // minimize the distortion of the four new quads from the
8219 // optimal shape. their description uses the formulas
8220 // underlying the TransfiniteInterpolationManifold
8221 // implementation
8222 triangulation.vertices[next_unused_vertex] =
8223 quad->center(true, true);
8224 triangulation.vertices_used[next_unused_vertex] = true;
8225
8226 // now that we created the right point, make up
8227 // the four lines interior to the quad (++ takes
8228 // care of the end of the vector)
8230 new_lines[4];
8231
8232 for (unsigned int i = 0; i < 4; ++i)
8233 {
8234 if (i % 2 == 0)
8235 // search a free pair of lines for 0. and
8236 // 2. line, so that two of them end up
8237 // together, which is necessary if later on
8238 // we want to refine the quad
8239 // anisotropically and the two lines end up
8240 // as children of new line
8241 next_unused_line =
8242 triangulation.faces->lines
8243 .template next_free_pair_object<1>(triangulation);
8244
8245 new_lines[i] = next_unused_line;
8246 ++next_unused_line;
8247
8248 AssertIsNotUsed(new_lines[i]);
8249 }
8250
8251 // set the data of the four lines. first collect
8252 // the indices of the five vertices:
8253 //
8254 // *--3--*
8255 // | | |
8256 // 0--4--1
8257 // | | |
8258 // *--2--*
8259 //
8260 // the lines are numbered as follows:
8261 //
8262 // *--*--*
8263 // | 1 |
8264 // *2-*-3*
8265 // | 0 |
8266 // *--*--*
8267
8268 const unsigned int vertex_indices[5] = {
8269 quad->line(0)->child(0)->vertex_index(1),
8270 quad->line(1)->child(0)->vertex_index(1),
8271 quad->line(2)->child(0)->vertex_index(1),
8272 quad->line(3)->child(0)->vertex_index(1),
8273 next_unused_vertex};
8274
8275 new_lines[0]->set_bounding_object_indices(
8277 new_lines[1]->set_bounding_object_indices(
8279 new_lines[2]->set_bounding_object_indices(
8281 new_lines[3]->set_bounding_object_indices(
8283
8284 for (const auto &new_line : new_lines)
8285 {
8286 new_line->set_used_flag();
8287 new_line->clear_user_flag();
8288 new_line->clear_user_data();
8289 new_line->clear_children();
8290 new_line->set_boundary_id_internal(quad->boundary_id());
8291 new_line->set_manifold_id(quad->manifold_id());
8292 }
8293
8294 // now for the quads. again, first collect some
8295 // data about the indices of the lines, with the
8296 // following numbering:
8297 //
8298 // .-6-.-7-.
8299 // 1 9 3
8300 // .-10.11-.
8301 // 0 8 2
8302 // .-4-.-5-.
8303
8304 const int line_indices[12] = {
8305 quad->line(0)
8306 ->child(child_line_index(0, quad->line_orientation(0)))
8307 ->index(),
8308 quad->line(0)
8309 ->child(child_line_index(1, quad->line_orientation(0)))
8310 ->index(),
8311 quad->line(1)
8312 ->child(child_line_index(0, quad->line_orientation(1)))
8313 ->index(),
8314 quad->line(1)
8315 ->child(child_line_index(1, quad->line_orientation(1)))
8316 ->index(),
8317 quad->line(2)
8318 ->child(child_line_index(0, quad->line_orientation(2)))
8319 ->index(),
8320 quad->line(2)
8321 ->child(child_line_index(1, quad->line_orientation(2)))
8322 ->index(),
8323 quad->line(3)
8324 ->child(child_line_index(0, quad->line_orientation(3)))
8325 ->index(),
8326 quad->line(3)
8327 ->child(child_line_index(1, quad->line_orientation(3)))
8328 ->index(),
8329 new_lines[0]->index(),
8330 new_lines[1]->index(),
8331 new_lines[2]->index(),
8332 new_lines[3]->index()};
8333
8334 // find some space (consecutive)
8335 // for the first two newly to be
8336 // created quads.
8338 new_quads[4];
8339
8340 next_unused_quad =
8341 triangulation.faces->quads
8342 .template next_free_pair_object<2>(triangulation);
8343
8344 new_quads[0] = next_unused_quad;
8345 AssertIsNotUsed(new_quads[0]);
8346
8347 ++next_unused_quad;
8348 new_quads[1] = next_unused_quad;
8349 AssertIsNotUsed(new_quads[1]);
8350
8351 next_unused_quad =
8352 triangulation.faces->quads
8353 .template next_free_pair_object<2>(triangulation);
8354 new_quads[2] = next_unused_quad;
8355 AssertIsNotUsed(new_quads[2]);
8356
8357 ++next_unused_quad;
8358 new_quads[3] = next_unused_quad;
8359 AssertIsNotUsed(new_quads[3]);
8360
8361 // note these quads as children to the present one
8362 quad->set_children(0, new_quads[0]->index());
8363 quad->set_children(2, new_quads[2]->index());
8364 quad->set_refinement_case(RefinementCase<2>::cut_xy);
8365
8366 new_quads[0]->set_bounding_object_indices(
8367 {line_indices[0],
8368 line_indices[8],
8369 line_indices[4],
8370 line_indices[10]});
8371 new_quads[1]->set_bounding_object_indices(
8372 {line_indices[8],
8373 line_indices[2],
8374 line_indices[5],
8375 line_indices[11]});
8376 new_quads[2]->set_bounding_object_indices(
8377 {line_indices[1],
8378 line_indices[9],
8379 line_indices[10],
8380 line_indices[6]});
8381 new_quads[3]->set_bounding_object_indices(
8382 {line_indices[9],
8383 line_indices[3],
8384 line_indices[11],
8385 line_indices[7]});
8386 for (const auto &new_quad : new_quads)
8387 {
8388 new_quad->set_used_flag();
8389 new_quad->clear_user_flag();
8390 new_quad->clear_user_data();
8391 new_quad->clear_children();
8392 new_quad->set_boundary_id_internal(quad->boundary_id());
8393 new_quad->set_manifold_id(quad->manifold_id());
8394 // set all line orientations to true, change
8395 // this after the loop, as we have to consider
8396 // different lines for each child
8397 for (unsigned int j = 0;
8398 j < GeometryInfo<dim>::lines_per_face;
8399 ++j)
8400 new_quad->set_line_orientation(
8402 }
8403 // now set the line orientation of children of
8404 // outer lines correctly, the lines in the
8405 // interior of the refined quad are automatically
8406 // oriented conforming to the standard
8407 new_quads[0]->set_line_orientation(
8408 0, quad->line_orientation(0));
8409 new_quads[0]->set_line_orientation(
8410 2, quad->line_orientation(2));
8411 new_quads[1]->set_line_orientation(
8412 1, quad->line_orientation(1));
8413 new_quads[1]->set_line_orientation(
8414 2, quad->line_orientation(2));
8415 new_quads[2]->set_line_orientation(
8416 0, quad->line_orientation(0));
8417 new_quads[2]->set_line_orientation(
8418 3, quad->line_orientation(3));
8419 new_quads[3]->set_line_orientation(
8420 1, quad->line_orientation(1));
8421 new_quads[3]->set_line_orientation(
8422 3, quad->line_orientation(3));
8423
8424 // finally clear flag indicating the need for
8425 // refinement
8426 quad->clear_user_flag();
8427 } // if (isotropic refinement)
8428 } // for all quads
8429 } // looped two times over all quads, all quads refined now
8430
8431 //---------------------------------
8432 // Now, finally, set up the new
8433 // cells
8434 //---------------------------------
8435
8437 cells_with_distorted_children;
8438
8439 for (unsigned int level = 0; level != triangulation.levels.size() - 1;
8440 ++level)
8441 {
8442 // only active objects can be refined further; remember
8443 // that we won't operate on the finest level, so
8444 // triangulation.begin_*(level+1) is allowed
8447 endh = triangulation.begin_active_hex(level + 1);
8449 next_unused_hex = triangulation.begin_raw_hex(level + 1);
8450
8451 for (; hex != endh; ++hex)
8452 if (hex->refine_flag_set())
8453 {
8454 // this hex needs to be refined
8455
8456 // clear flag indicating the need for refinement. do
8457 // it here already, since we can't do it anymore
8458 // once the cell has children
8459 const RefinementCase<dim> ref_case = hex->refine_flag_set();
8460 hex->clear_refine_flag();
8461 hex->set_refinement_case(ref_case);
8462
8463 // depending on the refine case we might have to
8464 // create additional vertices, lines and quads
8465 // interior of the hex before the actual children
8466 // can be set up.
8467
8468 // in a first step: reserve the needed space for
8469 // lines, quads and hexes and initialize them
8470 // correctly
8471
8472 unsigned int n_new_lines = 0;
8473 unsigned int n_new_quads = 0;
8474 unsigned int n_new_hexes = 0;
8475 switch (ref_case)
8476 {
8480 n_new_lines = 0;
8481 n_new_quads = 1;
8482 n_new_hexes = 2;
8483 break;
8487 n_new_lines = 1;
8488 n_new_quads = 4;
8489 n_new_hexes = 4;
8490 break;
8492 n_new_lines = 6;
8493 n_new_quads = 12;
8494 n_new_hexes = 8;
8495 break;
8496 default:
8498 break;
8499 }
8500
8501 // find some space for the newly to be created
8502 // interior lines and initialize them.
8503 std::vector<
8505 new_lines(n_new_lines);
8506 for (unsigned int i = 0; i < n_new_lines; ++i)
8507 {
8508 new_lines[i] =
8509 triangulation.faces->lines
8510 .template next_free_single_object<1>(triangulation);
8511
8512 AssertIsNotUsed(new_lines[i]);
8513 new_lines[i]->set_used_flag();
8514 new_lines[i]->clear_user_flag();
8515 new_lines[i]->clear_user_data();
8516 new_lines[i]->clear_children();
8517 // interior line
8518 new_lines[i]->set_boundary_id_internal(
8520 // they inherit geometry description of the hex they
8521 // belong to
8522 new_lines[i]->set_manifold_id(hex->manifold_id());
8523 }
8524
8525 // find some space for the newly to be created
8526 // interior quads and initialize them.
8527 std::vector<
8529 new_quads(n_new_quads);
8530 for (unsigned int i = 0; i < n_new_quads; ++i)
8531 {
8532 new_quads[i] =
8533 triangulation.faces->quads
8534 .template next_free_single_object<2>(triangulation);
8535
8536 AssertIsNotUsed(new_quads[i]);
8537 new_quads[i]->set_used_flag();
8538 new_quads[i]->clear_user_flag();
8539 new_quads[i]->clear_user_data();
8540 new_quads[i]->clear_children();
8541 // interior quad
8542 new_quads[i]->set_boundary_id_internal(
8544 // they inherit geometry description of the hex they
8545 // belong to
8546 new_quads[i]->set_manifold_id(hex->manifold_id());
8547 // set all line orientation flags to true by
8548 // default, change this afterwards, if necessary
8549 for (unsigned int j = 0;
8550 j < GeometryInfo<dim>::lines_per_face;
8551 ++j)
8552 new_quads[i]->set_line_orientation(
8554 }
8555
8556 types::subdomain_id subdomainid = hex->subdomain_id();
8557
8558 // find some space for the newly to be created hexes
8559 // and initialize them.
8560 std::vector<
8562 new_hexes(n_new_hexes);
8563 for (unsigned int i = 0; i < n_new_hexes; ++i)
8564 {
8565 if (i % 2 == 0)
8566 next_unused_hex =
8567 triangulation.levels[level + 1]->cells.next_free_hex(
8568 triangulation, level + 1);
8569 else
8570 ++next_unused_hex;
8571
8572 new_hexes[i] = next_unused_hex;
8573
8574 AssertIsNotUsed(new_hexes[i]);
8575 new_hexes[i]->set_used_flag();
8576 new_hexes[i]->clear_user_flag();
8577 new_hexes[i]->clear_user_data();
8578 new_hexes[i]->clear_children();
8579 // inherit material
8580 // properties
8581 new_hexes[i]->set_material_id(hex->material_id());
8582 new_hexes[i]->set_manifold_id(hex->manifold_id());
8583 new_hexes[i]->set_subdomain_id(subdomainid);
8584
8585 if (i % 2)
8586 new_hexes[i]->set_parent(hex->index());
8587 // set the face_orientation flag to true for all
8588 // faces initially, as this is the default value
8589 // which is true for all faces interior to the
8590 // hex. later on go the other way round and
8591 // reset faces that are at the boundary of the
8592 // mother cube
8593 //
8594 // the same is true for the face_flip and
8595 // face_rotation flags. however, the latter two
8596 // are set to false by default as this is the
8597 // standard value
8598 for (const unsigned int f :
8600 new_hexes[i]->set_combined_face_orientation(
8602 }
8603 // note these hexes as children to the present cell
8604 for (unsigned int i = 0; i < n_new_hexes / 2; ++i)
8605 hex->set_children(2 * i, new_hexes[2 * i]->index());
8606
8607 // we have to take into account whether the
8608 // different faces are oriented correctly or in the
8609 // opposite direction, so store that up front
8610
8611 // face_orientation
8612 const bool f_or[6] = {hex->face_orientation(0),
8613 hex->face_orientation(1),
8614 hex->face_orientation(2),
8615 hex->face_orientation(3),
8616 hex->face_orientation(4),
8617 hex->face_orientation(5)};
8618
8619 // face_flip
8620 const bool f_fl[6] = {hex->face_flip(0),
8621 hex->face_flip(1),
8622 hex->face_flip(2),
8623 hex->face_flip(3),
8624 hex->face_flip(4),
8625 hex->face_flip(5)};
8626
8627 // face_rotation
8628 const bool f_ro[6] = {hex->face_rotation(0),
8629 hex->face_rotation(1),
8630 hex->face_rotation(2),
8631 hex->face_rotation(3),
8632 hex->face_rotation(4),
8633 hex->face_rotation(5)};
8634
8635 // combined orientation
8636 const types::geometric_orientation f_co[6] = {
8637 hex->combined_face_orientation(0),
8638 hex->combined_face_orientation(1),
8639 hex->combined_face_orientation(2),
8640 hex->combined_face_orientation(3),
8641 hex->combined_face_orientation(4),
8642 hex->combined_face_orientation(5)};
8643
8644 // little helper table, indicating, whether the
8645 // child with index 0 or with index 1 can be found
8646 // at the standard origin of an anisotropically
8647 // refined quads in real orientation index 1:
8648 // (RefineCase - 1) index 2: face_flip
8649
8650 // index 3: face rotation
8651 // note: face orientation has no influence
8652 const unsigned int child_at_origin[2][2][2] = {
8653 {{0, 0}, // RefinementCase<dim>::cut_x, face_flip=false,
8654 // face_rotation=false and true
8655 {1, 1}}, // RefinementCase<dim>::cut_x, face_flip=true,
8656 // face_rotation=false and true
8657 {{0, 1}, // RefinementCase<dim>::cut_y, face_flip=false,
8658 // face_rotation=false and true
8659 {1, 0}}}; // RefinementCase<dim>::cut_y, face_flip=true,
8660 // face_rotation=false and true
8661
8662 //-------------------------------------
8663 //
8664 // in the following we will do the same thing for
8665 // each refinement case: create a new vertex (if
8666 // needed), create new interior lines (if needed),
8667 // create new interior quads and afterwards build
8668 // the children hexes out of these and the existing
8669 // subfaces of the outer quads (which have been
8670 // created above). However, even if the steps are
8671 // quite similar, the actual work strongly depends
8672 // on the actual refinement case. therefore, we use
8673 // separate blocks of code for each of these cases,
8674 // which hopefully increases the readability to some
8675 // extend.
8676
8677 switch (ref_case)
8678 {
8680 {
8681 //----------------------------
8682 //
8683 // RefinementCase<dim>::cut_x
8684 //
8685 // the refined cube will look
8686 // like this:
8687 //
8688 // *----*----*
8689 // / / /|
8690 // / / / |
8691 // / / / |
8692 // *----*----* |
8693 // | | | |
8694 // | | | *
8695 // | | | /
8696 // | | | /
8697 // | | |/
8698 // *----*----*
8699 //
8700 // again, first collect some data about the
8701 // indices of the lines, with the following
8702 // numbering:
8703
8704 // face 2: front plane
8705 // (note: x,y exchanged)
8706 // *---*---*
8707 // | | |
8708 // | 0 |
8709 // | | |
8710 // *---*---*
8711 // m0
8712 // face 3: back plane
8713 // (note: x,y exchanged)
8714 // m1
8715 // *---*---*
8716 // | | |
8717 // | 1 |
8718 // | | |
8719 // *---*---*
8720 // face 4: bottom plane
8721 // *---*---*
8722 // / / /
8723 // / 2 /
8724 // / / /
8725 // *---*---*
8726 // m0
8727 // face 5: top plane
8728 // m1
8729 // *---*---*
8730 // / / /
8731 // / 3 /
8732 // / / /
8733 // *---*---*
8734
8735 // set up a list of line iterators first. from
8736 // this, construct lists of line_indices and
8737 // line orientations later on
8738 const typename Triangulation<dim, spacedim>::
8739 raw_line_iterator lines[4] = {
8740 hex->face(2)->child(0)->line(
8741 (hex->face(2)->refinement_case() ==
8743 1 :
8744 3), // 0
8745 hex->face(3)->child(0)->line(
8746 (hex->face(3)->refinement_case() ==
8748 1 :
8749 3), // 1
8750 hex->face(4)->child(0)->line(
8751 (hex->face(4)->refinement_case() ==
8753 1 :
8754 3), // 2
8755 hex->face(5)->child(0)->line(
8756 (hex->face(5)->refinement_case() ==
8758 1 :
8759 3) // 3
8760 };
8761
8762 unsigned int line_indices[4];
8763 for (unsigned int i = 0; i < 4; ++i)
8764 line_indices[i] = lines[i]->index();
8765
8766 // the orientation of lines for the inner quads
8767 // is quite tricky. as these lines are newly
8768 // created ones and thus have no parents, they
8769 // cannot inherit this property. set up an array
8770 // and fill it with the respective values
8771 types::geometric_orientation line_orientation[4]{};
8772
8773 // the middle vertex marked as m0 above is the
8774 // start vertex for lines 0 and 2 in standard
8775 // orientation, whereas m1 is the end vertex of
8776 // lines 1 and 3 in standard orientation
8777 const unsigned int middle_vertices[2] = {
8778 hex->line(2)->child(0)->vertex_index(1),
8779 hex->line(7)->child(0)->vertex_index(1)};
8780
8781 for (unsigned int i = 0; i < 4; ++i)
8782 if (lines[i]->vertex_index(i % 2) ==
8783 middle_vertices[i % 2])
8784 line_orientation[i] =
8786 else
8787 {
8788 // it must be the other way round then
8789 Assert(lines[i]->vertex_index((i + 1) % 2) ==
8790 middle_vertices[i % 2],
8792 line_orientation[i] =
8794 }
8795
8796 // set up the new quad, line numbering is as
8797 // indicated above
8798 new_quads[0]->set_bounding_object_indices(
8799 {line_indices[0],
8800 line_indices[1],
8801 line_indices[2],
8802 line_indices[3]});
8803
8804 new_quads[0]->set_line_orientation(
8805 0, line_orientation[0]);
8806 new_quads[0]->set_line_orientation(
8807 1, line_orientation[1]);
8808 new_quads[0]->set_line_orientation(
8809 2, line_orientation[2]);
8810 new_quads[0]->set_line_orientation(
8811 3, line_orientation[3]);
8812
8813 // the quads are numbered as follows:
8814 //
8815 // planes in the interior of the old hex:
8816 //
8817 // *
8818 // /|
8819 // / | x
8820 // / | *-------* *---------*
8821 // * | | | / /
8822 // | 0 | | | / /
8823 // | * | | / /
8824 // | / *-------*y *---------*x
8825 // | /
8826 // |/
8827 // *
8828 //
8829 // children of the faces of the old hex
8830 //
8831 // *---*---* *---*---*
8832 // /| | | / / /|
8833 // / | | | / 9 / 10/ |
8834 // / | 5 | 6 | / / / |
8835 // * | | | *---*---* |
8836 // | 1 *---*---* | | | 2 *
8837 // | / / / | | | /
8838 // | / 7 / 8 / | 3 | 4 | /
8839 // |/ / / | | |/
8840 // *---*---* *---*---*
8841 //
8842 // note that we have to take care of the
8843 // orientation of faces.
8844 const int quad_indices[11] = {
8845 new_quads[0]->index(), // 0
8846
8847 hex->face(0)->index(), // 1
8848
8849 hex->face(1)->index(), // 2
8850
8851 hex->face(2)->child_index(
8852 child_at_origin[hex->face(2)->refinement_case() -
8853 1][f_fl[2]][f_ro[2]]), // 3
8854 hex->face(2)->child_index(
8855 1 -
8856 child_at_origin[hex->face(2)->refinement_case() -
8857 1][f_fl[2]][f_ro[2]]),
8858
8859 hex->face(3)->child_index(
8860 child_at_origin[hex->face(3)->refinement_case() -
8861 1][f_fl[3]][f_ro[3]]), // 5
8862 hex->face(3)->child_index(
8863 1 -
8864 child_at_origin[hex->face(3)->refinement_case() -
8865 1][f_fl[3]][f_ro[3]]),
8866
8867 hex->face(4)->child_index(
8868 child_at_origin[hex->face(4)->refinement_case() -
8869 1][f_fl[4]][f_ro[4]]), // 7
8870 hex->face(4)->child_index(
8871 1 -
8872 child_at_origin[hex->face(4)->refinement_case() -
8873 1][f_fl[4]][f_ro[4]]),
8874
8875 hex->face(5)->child_index(
8876 child_at_origin[hex->face(5)->refinement_case() -
8877 1][f_fl[5]][f_ro[5]]), // 9
8878 hex->face(5)->child_index(
8879 1 -
8880 child_at_origin[hex->face(5)->refinement_case() -
8881 1][f_fl[5]][f_ro[5]])
8882
8883 };
8884
8885 new_hexes[0]->set_bounding_object_indices(
8886 {quad_indices[1],
8887 quad_indices[0],
8888 quad_indices[3],
8889 quad_indices[5],
8890 quad_indices[7],
8891 quad_indices[9]});
8892 new_hexes[1]->set_bounding_object_indices(
8893 {quad_indices[0],
8894 quad_indices[2],
8895 quad_indices[4],
8896 quad_indices[6],
8897 quad_indices[8],
8898 quad_indices[10]});
8899 break;
8900 }
8901
8903 {
8904 //----------------------------
8905 //
8906 // RefinementCase<dim>::cut_y
8907 //
8908 // the refined cube will look like this:
8909 //
8910 // *---------*
8911 // / /|
8912 // *---------* |
8913 // / /| |
8914 // *---------* | |
8915 // | | | |
8916 // | | | *
8917 // | | |/
8918 // | | *
8919 // | |/
8920 // *---------*
8921 //
8922 // again, first collect some data about the
8923 // indices of the lines, with the following
8924 // numbering:
8925
8926 // face 0: left plane
8927 // *
8928 // /|
8929 // * |
8930 // /| |
8931 // * | |
8932 // | 0 |
8933 // | | *
8934 // | |/
8935 // | *m0
8936 // |/
8937 // *
8938 // face 1: right plane
8939 // *
8940 // /|
8941 // m1* |
8942 // /| |
8943 // * | |
8944 // | 1 |
8945 // | | *
8946 // | |/
8947 // | *
8948 // |/
8949 // *
8950 // face 4: bottom plane
8951 // *-------*
8952 // / /
8953 // m0*---2---*
8954 // / /
8955 // *-------*
8956 // face 5: top plane
8957 // *-------*
8958 // / /
8959 // *---3---*m1
8960 // / /
8961 // *-------*
8962
8963 // set up a list of line iterators first. from
8964 // this, construct lists of line_indices and
8965 // line orientations later on
8966 const typename Triangulation<dim, spacedim>::
8967 raw_line_iterator lines[4] = {
8968 hex->face(0)->child(0)->line(
8969 (hex->face(0)->refinement_case() ==
8971 1 :
8972 3), // 0
8973 hex->face(1)->child(0)->line(
8974 (hex->face(1)->refinement_case() ==
8976 1 :
8977 3), // 1
8978 hex->face(4)->child(0)->line(
8979 (hex->face(4)->refinement_case() ==
8981 1 :
8982 3), // 2
8983 hex->face(5)->child(0)->line(
8984 (hex->face(5)->refinement_case() ==
8986 1 :
8987 3) // 3
8988 };
8989
8990 unsigned int line_indices[4];
8991 for (unsigned int i = 0; i < 4; ++i)
8992 line_indices[i] = lines[i]->index();
8993
8994 // the orientation of lines for the inner quads
8995 // is quite tricky. as these lines are newly
8996 // created ones and thus have no parents, they
8997 // cannot inherit this property. set up an array
8998 // and fill it with the respective values
8999 types::geometric_orientation line_orientation[4]{};
9000
9001 // the middle vertex marked as m0 above is the
9002 // start vertex for lines 0 and 2 in standard
9003 // orientation, whereas m1 is the end vertex of
9004 // lines 1 and 3 in standard orientation
9005 const unsigned int middle_vertices[2] = {
9006 hex->line(0)->child(0)->vertex_index(1),
9007 hex->line(5)->child(0)->vertex_index(1)};
9008
9009 for (unsigned int i = 0; i < 4; ++i)
9010 if (lines[i]->vertex_index(i % 2) ==
9011 middle_vertices[i % 2])
9012 line_orientation[i] =
9014 else
9015 {
9016 // it must be the other way round then
9017 Assert(lines[i]->vertex_index((i + 1) % 2) ==
9018 middle_vertices[i % 2],
9020 line_orientation[i] =
9022 }
9023
9024 // set up the new quad, line numbering is as
9025 // indicated above
9026 new_quads[0]->set_bounding_object_indices(
9027 {line_indices[2],
9028 line_indices[3],
9029 line_indices[0],
9030 line_indices[1]});
9031
9032 new_quads[0]->set_line_orientation(
9033 0, line_orientation[2]);
9034 new_quads[0]->set_line_orientation(
9035 1, line_orientation[3]);
9036 new_quads[0]->set_line_orientation(
9037 2, line_orientation[0]);
9038 new_quads[0]->set_line_orientation(
9039 3, line_orientation[1]);
9040
9041 // the quads are numbered as follows:
9042 //
9043 // planes in the interior of the old hex:
9044 //
9045 // *
9046 // /|
9047 // / | x
9048 // / | *-------* *---------*
9049 // * | | | / /
9050 // | | | 0 | / /
9051 // | * | | / /
9052 // | / *-------*y *---------*x
9053 // | /
9054 // |/
9055 // *
9056 //
9057 // children of the faces of the old hex
9058 //
9059 // *-------* *-------*
9060 // /| | / 10 /|
9061 // * | | *-------* |
9062 // /| | 6 | / 9 /| |
9063 // * |2| | *-------* |4|
9064 // | | *-------* | | | *
9065 // |1|/ 8 / | |3|/
9066 // | *-------* | 5 | *
9067 // |/ 7 / | |/
9068 // *-------* *-------*
9069 //
9070 // note that we have to take care of the
9071 // orientation of faces.
9072 const int quad_indices[11] = {
9073 new_quads[0]->index(), // 0
9074
9075 hex->face(0)->child_index(
9076 child_at_origin[hex->face(0)->refinement_case() -
9077 1][f_fl[0]][f_ro[0]]), // 1
9078 hex->face(0)->child_index(
9079 1 -
9080 child_at_origin[hex->face(0)->refinement_case() -
9081 1][f_fl[0]][f_ro[0]]),
9082
9083 hex->face(1)->child_index(
9084 child_at_origin[hex->face(1)->refinement_case() -
9085 1][f_fl[1]][f_ro[1]]), // 3
9086 hex->face(1)->child_index(
9087 1 -
9088 child_at_origin[hex->face(1)->refinement_case() -
9089 1][f_fl[1]][f_ro[1]]),
9090
9091 hex->face(2)->index(), // 5
9092
9093 hex->face(3)->index(), // 6
9094
9095 hex->face(4)->child_index(
9096 child_at_origin[hex->face(4)->refinement_case() -
9097 1][f_fl[4]][f_ro[4]]), // 7
9098 hex->face(4)->child_index(
9099 1 -
9100 child_at_origin[hex->face(4)->refinement_case() -
9101 1][f_fl[4]][f_ro[4]]),
9102
9103 hex->face(5)->child_index(
9104 child_at_origin[hex->face(5)->refinement_case() -
9105 1][f_fl[5]][f_ro[5]]), // 9
9106 hex->face(5)->child_index(
9107 1 -
9108 child_at_origin[hex->face(5)->refinement_case() -
9109 1][f_fl[5]][f_ro[5]])
9110
9111 };
9112
9113 new_hexes[0]->set_bounding_object_indices(
9114 {quad_indices[1],
9115 quad_indices[3],
9116 quad_indices[5],
9117 quad_indices[0],
9118 quad_indices[7],
9119 quad_indices[9]});
9120 new_hexes[1]->set_bounding_object_indices(
9121 {quad_indices[2],
9122 quad_indices[4],
9123 quad_indices[0],
9124 quad_indices[6],
9125 quad_indices[8],
9126 quad_indices[10]});
9127 break;
9128 }
9129
9131 {
9132 //----------------------------
9133 //
9134 // RefinementCase<dim>::cut_z
9135 //
9136 // the refined cube will look like this:
9137 //
9138 // *---------*
9139 // / /|
9140 // / / |
9141 // / / *
9142 // *---------* /|
9143 // | | / |
9144 // | |/ *
9145 // *---------* /
9146 // | | /
9147 // | |/
9148 // *---------*
9149 //
9150 // again, first collect some data about the
9151 // indices of the lines, with the following
9152 // numbering:
9153
9154 // face 0: left plane
9155 // *
9156 // /|
9157 // / |
9158 // / *
9159 // * /|
9160 // | 0 |
9161 // |/ *
9162 // m0* /
9163 // | /
9164 // |/
9165 // *
9166 // face 1: right plane
9167 // *
9168 // /|
9169 // / |
9170 // / *m1
9171 // * /|
9172 // | 1 |
9173 // |/ *
9174 // * /
9175 // | /
9176 // |/
9177 // *
9178 // face 2: front plane
9179 // (note: x,y exchanged)
9180 // *-------*
9181 // | |
9182 // m0*---2---*
9183 // | |
9184 // *-------*
9185 // face 3: back plane
9186 // (note: x,y exchanged)
9187 // *-------*
9188 // | |
9189 // *---3---*m1
9190 // | |
9191 // *-------*
9192
9193 // set up a list of line iterators first. from
9194 // this, construct lists of line_indices and
9195 // line orientations later on
9196 const typename Triangulation<dim, spacedim>::
9197 raw_line_iterator lines[4] = {
9198 hex->face(0)->child(0)->line(
9199 (hex->face(0)->refinement_case() ==
9201 1 :
9202 3), // 0
9203 hex->face(1)->child(0)->line(
9204 (hex->face(1)->refinement_case() ==
9206 1 :
9207 3), // 1
9208 hex->face(2)->child(0)->line(
9209 (hex->face(2)->refinement_case() ==
9211 1 :
9212 3), // 2
9213 hex->face(3)->child(0)->line(
9214 (hex->face(3)->refinement_case() ==
9216 1 :
9217 3) // 3
9218 };
9219
9220 unsigned int line_indices[4];
9221 for (unsigned int i = 0; i < 4; ++i)
9222 line_indices[i] = lines[i]->index();
9223
9224 // the orientation of lines for the inner quads
9225 // is quite tricky. as these lines are newly
9226 // created ones and thus have no parents, they
9227 // cannot inherit this property. set up an array
9228 // and fill it with the respective values
9229 types::geometric_orientation line_orientation[4]{};
9230
9231 // the middle vertex marked as m0 above is the
9232 // start vertex for lines 0 and 2 in standard
9233 // orientation, whereas m1 is the end vertex of
9234 // lines 1 and 3 in standard orientation
9235 const unsigned int middle_vertices[2] = {
9236 middle_vertex_index<dim, spacedim>(hex->line(8)),
9237 middle_vertex_index<dim, spacedim>(hex->line(11))};
9238
9239 for (unsigned int i = 0; i < 4; ++i)
9240 if (lines[i]->vertex_index(i % 2) ==
9241 middle_vertices[i % 2])
9242 line_orientation[i] =
9244 else
9245 {
9246 // it must be the other way round then
9247 Assert(lines[i]->vertex_index((i + 1) % 2) ==
9248 middle_vertices[i % 2],
9250 line_orientation[i] =
9252 }
9253
9254 // set up the new quad, line numbering is as
9255 // indicated above
9256 new_quads[0]->set_bounding_object_indices(
9257 {line_indices[0],
9258 line_indices[1],
9259 line_indices[2],
9260 line_indices[3]});
9261
9262 new_quads[0]->set_line_orientation(
9263 0, line_orientation[0]);
9264 new_quads[0]->set_line_orientation(
9265 1, line_orientation[1]);
9266 new_quads[0]->set_line_orientation(
9267 2, line_orientation[2]);
9268 new_quads[0]->set_line_orientation(
9269 3, line_orientation[3]);
9270
9271 // the quads are numbered as follows:
9272 //
9273 // planes in the interior of the old hex:
9274 //
9275 // *
9276 // /|
9277 // / | x
9278 // / | *-------* *---------*
9279 // * | | | / /
9280 // | | | | / 0 /
9281 // | * | | / /
9282 // | / *-------*y *---------*x
9283 // | /
9284 // |/
9285 // *
9286 //
9287 // children of the faces of the old hex
9288 //
9289 // *---*---* *-------*
9290 // /| 8 | / /|
9291 // / | | / 10 / |
9292 // / *-------* / / *
9293 // * 2/| | *-------* 4/|
9294 // | / | 7 | | 6 | / |
9295 // |/1 *-------* | |/3 *
9296 // * / / *-------* /
9297 // | / 9 / | | /
9298 // |/ / | 5 |/
9299 // *-------* *---*---*
9300 //
9301 // note that we have to take care of the
9302 // orientation of faces.
9303 const int quad_indices[11] = {
9304 new_quads[0]->index(), // 0
9305
9306 hex->face(0)->child_index(
9307 child_at_origin[hex->face(0)->refinement_case() -
9308 1][f_fl[0]][f_ro[0]]), // 1
9309 hex->face(0)->child_index(
9310 1 -
9311 child_at_origin[hex->face(0)->refinement_case() -
9312 1][f_fl[0]][f_ro[0]]),
9313
9314 hex->face(1)->child_index(
9315 child_at_origin[hex->face(1)->refinement_case() -
9316 1][f_fl[1]][f_ro[1]]), // 3
9317 hex->face(1)->child_index(
9318 1 -
9319 child_at_origin[hex->face(1)->refinement_case() -
9320 1][f_fl[1]][f_ro[1]]),
9321
9322 hex->face(2)->child_index(
9323 child_at_origin[hex->face(2)->refinement_case() -
9324 1][f_fl[2]][f_ro[2]]), // 5
9325 hex->face(2)->child_index(
9326 1 -
9327 child_at_origin[hex->face(2)->refinement_case() -
9328 1][f_fl[2]][f_ro[2]]),
9329
9330 hex->face(3)->child_index(
9331 child_at_origin[hex->face(3)->refinement_case() -
9332 1][f_fl[3]][f_ro[3]]), // 7
9333 hex->face(3)->child_index(
9334 1 -
9335 child_at_origin[hex->face(3)->refinement_case() -
9336 1][f_fl[3]][f_ro[3]]),
9337
9338 hex->face(4)->index(), // 9
9339
9340 hex->face(5)->index() // 10
9341 };
9342
9343 new_hexes[0]->set_bounding_object_indices(
9344 {quad_indices[1],
9345 quad_indices[3],
9346 quad_indices[5],
9347 quad_indices[7],
9348 quad_indices[9],
9349 quad_indices[0]});
9350 new_hexes[1]->set_bounding_object_indices(
9351 {quad_indices[2],
9352 quad_indices[4],
9353 quad_indices[6],
9354 quad_indices[8],
9355 quad_indices[0],
9356 quad_indices[10]});
9357 break;
9358 }
9359
9361 {
9362 //----------------------------
9363 //
9364 // RefinementCase<dim>::cut_xy
9365 //
9366 // the refined cube will look like this:
9367 //
9368 // *----*----*
9369 // / / /|
9370 // *----*----* |
9371 // / / /| |
9372 // *----*----* | |
9373 // | | | | |
9374 // | | | | *
9375 // | | | |/
9376 // | | | *
9377 // | | |/
9378 // *----*----*
9379 //
9380
9381 // first, create the new internal line
9382 new_lines[0]->set_bounding_object_indices(
9383 {middle_vertex_index<dim, spacedim>(hex->face(4)),
9384 middle_vertex_index<dim, spacedim>(hex->face(5))});
9385
9386 // again, first collect some data about the
9387 // indices of the lines, with the following
9388 // numbering:
9389
9390 // face 0: left plane
9391 // *
9392 // /|
9393 // * |
9394 // /| |
9395 // * | |
9396 // | 0 |
9397 // | | *
9398 // | |/
9399 // | *
9400 // |/
9401 // *
9402 // face 1: right plane
9403 // *
9404 // /|
9405 // * |
9406 // /| |
9407 // * | |
9408 // | 1 |
9409 // | | *
9410 // | |/
9411 // | *
9412 // |/
9413 // *
9414 // face 2: front plane
9415 // (note: x,y exchanged)
9416 // *---*---*
9417 // | | |
9418 // | 2 |
9419 // | | |
9420 // *-------*
9421 // face 3: back plane
9422 // (note: x,y exchanged)
9423 // *---*---*
9424 // | | |
9425 // | 3 |
9426 // | | |
9427 // *---*---*
9428 // face 4: bottom plane
9429 // *---*---*
9430 // / 5 /
9431 // *-6-*-7-*
9432 // / 4 /
9433 // *---*---*
9434 // face 5: top plane
9435 // *---*---*
9436 // / 9 /
9437 // *10-*-11*
9438 // / 8 /
9439 // *---*---*
9440 // middle planes
9441 // *-------* *---*---*
9442 // / / | | |
9443 // / / | 12 |
9444 // / / | | |
9445 // *-------* *---*---*
9446
9447 // set up a list of line iterators first. from
9448 // this, construct lists of line_indices and
9449 // line orientations later on
9450 const typename Triangulation<
9451 dim,
9452 spacedim>::raw_line_iterator lines[13] = {
9453 hex->face(0)->child(0)->line(
9454 (hex->face(0)->refinement_case() ==
9456 1 :
9457 3), // 0
9458 hex->face(1)->child(0)->line(
9459 (hex->face(1)->refinement_case() ==
9461 1 :
9462 3), // 1
9463 hex->face(2)->child(0)->line(
9464 (hex->face(2)->refinement_case() ==
9466 1 :
9467 3), // 2
9468 hex->face(3)->child(0)->line(
9469 (hex->face(3)->refinement_case() ==
9471 1 :
9472 3), // 3
9473
9474 hex->face(4)
9475 ->isotropic_child(
9477 0, f_or[4], f_fl[4], f_ro[4]))
9478 ->line(
9480 1, f_or[4], f_fl[4], f_ro[4])), // 4
9481 hex->face(4)
9482 ->isotropic_child(
9484 3, f_or[4], f_fl[4], f_ro[4]))
9485 ->line(
9487 0, f_or[4], f_fl[4], f_ro[4])), // 5
9488 hex->face(4)
9489 ->isotropic_child(
9491 0, f_or[4], f_fl[4], f_ro[4]))
9492 ->line(
9494 3, f_or[4], f_fl[4], f_ro[4])), // 6
9495 hex->face(4)
9496 ->isotropic_child(
9498 3, f_or[4], f_fl[4], f_ro[4]))
9499 ->line(
9501 2, f_or[4], f_fl[4], f_ro[4])), // 7
9502
9503 hex->face(5)
9504 ->isotropic_child(
9506 0, f_or[5], f_fl[5], f_ro[5]))
9507 ->line(
9509 1, f_or[5], f_fl[5], f_ro[5])), // 8
9510 hex->face(5)
9511 ->isotropic_child(
9513 3, f_or[5], f_fl[5], f_ro[5]))
9514 ->line(
9516 0, f_or[5], f_fl[5], f_ro[5])), // 9
9517 hex->face(5)
9518 ->isotropic_child(
9520 0, f_or[5], f_fl[5], f_ro[5]))
9521 ->line(
9523 3, f_or[5], f_fl[5], f_ro[5])), // 10
9524 hex->face(5)
9525 ->isotropic_child(
9527 3, f_or[5], f_fl[5], f_ro[5]))
9528 ->line(
9530 2, f_or[5], f_fl[5], f_ro[5])), // 11
9531
9532 new_lines[0] // 12
9533 };
9534
9535 unsigned int line_indices[13];
9536 for (unsigned int i = 0; i < 13; ++i)
9537 line_indices[i] = lines[i]->index();
9538
9539 // the orientation of lines for the inner quads
9540 // is quite tricky. as these lines are newly
9541 // created ones and thus have no parents, they
9542 // cannot inherit this property. set up an array
9543 // and fill it with the respective values
9544 types::geometric_orientation line_orientation[13]{};
9545
9546 // the middle vertices of the lines of our
9547 // bottom face
9548 const unsigned int middle_vertices[4] = {
9549 hex->line(0)->child(0)->vertex_index(1),
9550 hex->line(1)->child(0)->vertex_index(1),
9551 hex->line(2)->child(0)->vertex_index(1),
9552 hex->line(3)->child(0)->vertex_index(1),
9553 };
9554
9555 // note: for lines 0 to 3 the orientation of the
9556 // line is 'true', if vertex 0 is on the bottom
9557 // face
9558 for (unsigned int i = 0; i < 4; ++i)
9559 if (lines[i]->vertex_index(0) == middle_vertices[i])
9560 line_orientation[i] =
9562 else
9563 {
9564 // it must be the other way round then
9565 Assert(lines[i]->vertex_index(1) ==
9566 middle_vertices[i],
9568 line_orientation[i] =
9570 }
9571
9572 // note: for lines 4 to 11 (inner lines of the
9573 // outer quads) the following holds: the second
9574 // vertex of the even lines in standard
9575 // orientation is the vertex in the middle of
9576 // the quad, whereas for odd lines the first
9577 // vertex is the same middle vertex.
9578 for (unsigned int i = 4; i < 12; ++i)
9579 if (lines[i]->vertex_index((i + 1) % 2) ==
9580 middle_vertex_index<dim, spacedim>(
9581 hex->face(3 + i / 4)))
9582 line_orientation[i] =
9584 else
9585 {
9586 // it must be the other way round then
9587 Assert(lines[i]->vertex_index(i % 2) ==
9588 (middle_vertex_index<dim, spacedim>(
9589 hex->face(3 + i / 4))),
9591 line_orientation[i] =
9593 }
9594 // for the last line the line orientation is
9595 // always true, since it was just constructed
9596 // that way
9597 line_orientation[12] =
9599
9600 // set up the 4 quads, numbered as follows (left
9601 // quad numbering, right line numbering
9602 // extracted from above)
9603 //
9604 // * *
9605 // /| 9|
9606 // * | * |
9607 // y/| | 8| 3
9608 // * |1| * | |
9609 // | | |x | 12|
9610 // |0| * | | *
9611 // | |/ 2 |5
9612 // | * | *
9613 // |/ |4
9614 // * *
9615 //
9616 // x
9617 // *---*---* *10-*-11*
9618 // | | | | | |
9619 // | 2 | 3 | 0 12 1
9620 // | | | | | |
9621 // *---*---*y *-6-*-7-*
9622
9623 new_quads[0]->set_bounding_object_indices(
9624 {line_indices[2],
9625 line_indices[12],
9626 line_indices[4],
9627 line_indices[8]});
9628 new_quads[1]->set_bounding_object_indices(
9629 {line_indices[12],
9630 line_indices[3],
9631 line_indices[5],
9632 line_indices[9]});
9633 new_quads[2]->set_bounding_object_indices(
9634 {line_indices[6],
9635 line_indices[10],
9636 line_indices[0],
9637 line_indices[12]});
9638 new_quads[3]->set_bounding_object_indices(
9639 {line_indices[7],
9640 line_indices[11],
9641 line_indices[12],
9642 line_indices[1]});
9643
9644 new_quads[0]->set_line_orientation(
9645 0, line_orientation[2]);
9646 new_quads[0]->set_line_orientation(
9647 2, line_orientation[4]);
9648 new_quads[0]->set_line_orientation(
9649 3, line_orientation[8]);
9650
9651 new_quads[1]->set_line_orientation(
9652 1, line_orientation[3]);
9653 new_quads[1]->set_line_orientation(
9654 2, line_orientation[5]);
9655 new_quads[1]->set_line_orientation(
9656 3, line_orientation[9]);
9657
9658 new_quads[2]->set_line_orientation(
9659 0, line_orientation[6]);
9660 new_quads[2]->set_line_orientation(
9661 1, line_orientation[10]);
9662 new_quads[2]->set_line_orientation(
9663 2, line_orientation[0]);
9664
9665 new_quads[3]->set_line_orientation(
9666 0, line_orientation[7]);
9667 new_quads[3]->set_line_orientation(
9668 1, line_orientation[11]);
9669 new_quads[3]->set_line_orientation(
9670 3, line_orientation[1]);
9671
9672 // the quads are numbered as follows:
9673 //
9674 // planes in the interior of the old hex:
9675 //
9676 // *
9677 // /|
9678 // * | x
9679 // /| | *---*---* *---------*
9680 // * |1| | | | / /
9681 // | | | | 2 | 3 | / /
9682 // |0| * | | | / /
9683 // | |/ *---*---*y *---------*x
9684 // | *
9685 // |/
9686 // *
9687 //
9688 // children of the faces of the old hex
9689 //
9690 // *---*---* *---*---*
9691 // /| | | /18 / 19/|
9692 // * |10 | 11| /---/---* |
9693 // /| | | | /16 / 17/| |
9694 // * |5| | | *---*---* |7|
9695 // | | *---*---* | | | | *
9696 // |4|/14 / 15/ | | |6|/
9697 // | *---/---/ | 8 | 9 | *
9698 // |/12 / 13/ | | |/
9699 // *---*---* *---*---*
9700 //
9701 // note that we have to take care of the
9702 // orientation of faces.
9703 const int quad_indices[20] = {
9704 new_quads[0]->index(), // 0
9705 new_quads[1]->index(),
9706 new_quads[2]->index(),
9707 new_quads[3]->index(),
9708
9709 hex->face(0)->child_index(
9710 child_at_origin[hex->face(0)->refinement_case() -
9711 1][f_fl[0]][f_ro[0]]), // 4
9712 hex->face(0)->child_index(
9713 1 -
9714 child_at_origin[hex->face(0)->refinement_case() -
9715 1][f_fl[0]][f_ro[0]]),
9716
9717 hex->face(1)->child_index(
9718 child_at_origin[hex->face(1)->refinement_case() -
9719 1][f_fl[1]][f_ro[1]]), // 6
9720 hex->face(1)->child_index(
9721 1 -
9722 child_at_origin[hex->face(1)->refinement_case() -
9723 1][f_fl[1]][f_ro[1]]),
9724
9725 hex->face(2)->child_index(
9726 child_at_origin[hex->face(2)->refinement_case() -
9727 1][f_fl[2]][f_ro[2]]), // 8
9728 hex->face(2)->child_index(
9729 1 -
9730 child_at_origin[hex->face(2)->refinement_case() -
9731 1][f_fl[2]][f_ro[2]]),
9732
9733 hex->face(3)->child_index(
9734 child_at_origin[hex->face(3)->refinement_case() -
9735 1][f_fl[3]][f_ro[3]]), // 10
9736 hex->face(3)->child_index(
9737 1 -
9738 child_at_origin[hex->face(3)->refinement_case() -
9739 1][f_fl[3]][f_ro[3]]),
9740
9741 hex->face(4)->isotropic_child_index(
9743 0, f_or[4], f_fl[4], f_ro[4])), // 12
9744 hex->face(4)->isotropic_child_index(
9746 1, f_or[4], f_fl[4], f_ro[4])),
9747 hex->face(4)->isotropic_child_index(
9749 2, f_or[4], f_fl[4], f_ro[4])),
9750 hex->face(4)->isotropic_child_index(
9752 3, f_or[4], f_fl[4], f_ro[4])),
9753
9754 hex->face(5)->isotropic_child_index(
9756 0, f_or[5], f_fl[5], f_ro[5])), // 16
9757 hex->face(5)->isotropic_child_index(
9759 1, f_or[5], f_fl[5], f_ro[5])),
9760 hex->face(5)->isotropic_child_index(
9762 2, f_or[5], f_fl[5], f_ro[5])),
9763 hex->face(5)->isotropic_child_index(
9765 3, f_or[5], f_fl[5], f_ro[5]))};
9766
9767 new_hexes[0]->set_bounding_object_indices(
9768 {quad_indices[4],
9769 quad_indices[0],
9770 quad_indices[8],
9771 quad_indices[2],
9772 quad_indices[12],
9773 quad_indices[16]});
9774 new_hexes[1]->set_bounding_object_indices(
9775 {quad_indices[0],
9776 quad_indices[6],
9777 quad_indices[9],
9778 quad_indices[3],
9779 quad_indices[13],
9780 quad_indices[17]});
9781 new_hexes[2]->set_bounding_object_indices(
9782 {quad_indices[5],
9783 quad_indices[1],
9784 quad_indices[2],
9785 quad_indices[10],
9786 quad_indices[14],
9787 quad_indices[18]});
9788 new_hexes[3]->set_bounding_object_indices(
9789 {quad_indices[1],
9790 quad_indices[7],
9791 quad_indices[3],
9792 quad_indices[11],
9793 quad_indices[15],
9794 quad_indices[19]});
9795 break;
9796 }
9797
9799 {
9800 //----------------------------
9801 //
9802 // RefinementCase<dim>::cut_xz
9803 //
9804 // the refined cube will look like this:
9805 //
9806 // *----*----*
9807 // / / /|
9808 // / / / |
9809 // / / / *
9810 // *----*----* /|
9811 // | | | / |
9812 // | | |/ *
9813 // *----*----* /
9814 // | | | /
9815 // | | |/
9816 // *----*----*
9817 //
9818
9819 // first, create the new internal line
9820 new_lines[0]->set_bounding_object_indices(
9821 {middle_vertex_index<dim, spacedim>(hex->face(2)),
9822 middle_vertex_index<dim, spacedim>(hex->face(3))});
9823
9824 // again, first collect some data about the
9825 // indices of the lines, with the following
9826 // numbering:
9827
9828 // face 0: left plane
9829 // *
9830 // /|
9831 // / |
9832 // / *
9833 // * /|
9834 // | 0 |
9835 // |/ *
9836 // * /
9837 // | /
9838 // |/
9839 // *
9840 // face 1: right plane
9841 // *
9842 // /|
9843 // / |
9844 // / *
9845 // * /|
9846 // | 1 |
9847 // |/ *
9848 // * /
9849 // | /
9850 // |/
9851 // *
9852 // face 2: front plane
9853 // (note: x,y exchanged)
9854 // *---*---*
9855 // | 5 |
9856 // *-6-*-7-*
9857 // | 4 |
9858 // *---*---*
9859 // face 3: back plane
9860 // (note: x,y exchanged)
9861 // *---*---*
9862 // | 9 |
9863 // *10-*-11*
9864 // | 8 |
9865 // *---*---*
9866 // face 4: bottom plane
9867 // *---*---*
9868 // / / /
9869 // / 2 /
9870 // / / /
9871 // *---*---*
9872 // face 5: top plane
9873 // *---*---*
9874 // / / /
9875 // / 3 /
9876 // / / /
9877 // *---*---*
9878 // middle planes
9879 // *---*---* *-------*
9880 // / / / | |
9881 // / 12 / | |
9882 // / / / | |
9883 // *---*---* *-------*
9884
9885 // set up a list of line iterators first. from
9886 // this, construct lists of line_indices and
9887 // line orientations later on
9888 const typename Triangulation<
9889 dim,
9890 spacedim>::raw_line_iterator lines[13] = {
9891 hex->face(0)->child(0)->line(
9892 (hex->face(0)->refinement_case() ==
9894 1 :
9895 3), // 0
9896 hex->face(1)->child(0)->line(
9897 (hex->face(1)->refinement_case() ==
9899 1 :
9900 3), // 1
9901 hex->face(4)->child(0)->line(
9902 (hex->face(4)->refinement_case() ==
9904 1 :
9905 3), // 2
9906 hex->face(5)->child(0)->line(
9907 (hex->face(5)->refinement_case() ==
9909 1 :
9910 3), // 3
9911
9912 hex->face(2)
9913 ->isotropic_child(
9915 0, f_or[2], f_fl[2], f_ro[2]))
9916 ->line(
9918 3, f_or[2], f_fl[2], f_ro[2])), // 4
9919 hex->face(2)
9920 ->isotropic_child(
9922 3, f_or[2], f_fl[2], f_ro[2]))
9923 ->line(
9925 2, f_or[2], f_fl[2], f_ro[2])), // 5
9926 hex->face(2)
9927 ->isotropic_child(
9929 0, f_or[2], f_fl[2], f_ro[2]))
9930 ->line(
9932 1, f_or[2], f_fl[2], f_ro[2])), // 6
9933 hex->face(2)
9934 ->isotropic_child(
9936 3, f_or[2], f_fl[2], f_ro[2]))
9937 ->line(
9939 0, f_or[2], f_fl[2], f_ro[2])), // 7
9940
9941 hex->face(3)
9942 ->isotropic_child(
9944 0, f_or[3], f_fl[3], f_ro[3]))
9945 ->line(
9947 3, f_or[3], f_fl[3], f_ro[3])), // 8
9948 hex->face(3)
9949 ->isotropic_child(
9951 3, f_or[3], f_fl[3], f_ro[3]))
9952 ->line(
9954 2, f_or[3], f_fl[3], f_ro[3])), // 9
9955 hex->face(3)
9956 ->isotropic_child(
9958 0, f_or[3], f_fl[3], f_ro[3]))
9959 ->line(
9961 1, f_or[3], f_fl[3], f_ro[3])), // 10
9962 hex->face(3)
9963 ->isotropic_child(
9965 3, f_or[3], f_fl[3], f_ro[3]))
9966 ->line(
9968 0, f_or[3], f_fl[3], f_ro[3])), // 11
9969
9970 new_lines[0] // 12
9971 };
9972
9973 unsigned int line_indices[13];
9974 for (unsigned int i = 0; i < 13; ++i)
9975 line_indices[i] = lines[i]->index();
9976
9977 // the orientation of lines for the inner quads
9978 // is quite tricky. as these lines are newly
9979 // created ones and thus have no parents, they
9980 // cannot inherit this property. set up an array
9981 // and fill it with the respective values
9982 types::geometric_orientation line_orientation[13]{};
9983
9984 // the middle vertices of the
9985 // lines of our front face
9986 const unsigned int middle_vertices[4] = {
9987 hex->line(8)->child(0)->vertex_index(1),
9988 hex->line(9)->child(0)->vertex_index(1),
9989 hex->line(2)->child(0)->vertex_index(1),
9990 hex->line(6)->child(0)->vertex_index(1),
9991 };
9992
9993 // note: for lines 0 to 3 the orientation of the
9994 // line is 'true', if vertex 0 is on the front
9995 for (unsigned int i = 0; i < 4; ++i)
9996 if (lines[i]->vertex_index(0) == middle_vertices[i])
9997 line_orientation[i] =
9999 else
10000 {
10001 // it must be the other way round then
10002 Assert(lines[i]->vertex_index(1) ==
10003 middle_vertices[i],
10005 line_orientation[i] =
10007 }
10008
10009 // note: for lines 4 to 11 (inner lines of the
10010 // outer quads) the following holds: the second
10011 // vertex of the even lines in standard
10012 // orientation is the vertex in the middle of
10013 // the quad, whereas for odd lines the first
10014 // vertex is the same middle vertex.
10015 for (unsigned int i = 4; i < 12; ++i)
10016 if (lines[i]->vertex_index((i + 1) % 2) ==
10017 middle_vertex_index<dim, spacedim>(
10018 hex->face(1 + i / 4)))
10019 line_orientation[i] =
10021 else
10022 {
10023 // it must be the other way
10024 // round then
10025 Assert(lines[i]->vertex_index(i % 2) ==
10026 (middle_vertex_index<dim, spacedim>(
10027 hex->face(1 + i / 4))),
10029 line_orientation[i] =
10031 }
10032 // for the last line the line orientation is
10033 // always true, since it was just constructed
10034 // that way
10035 line_orientation[12] =
10037
10038 // set up the 4 quads, numbered as follows (left
10039 // quad numbering, right line numbering
10040 // extracted from above), the drawings denote
10041 // middle planes
10042 //
10043 // * *
10044 // /| /|
10045 // / | 3 9
10046 // y/ * / *
10047 // * 3/| * /|
10048 // | / |x 5 12|8
10049 // |/ * |/ *
10050 // * 2/ * /
10051 // | / 4 2
10052 // |/ |/
10053 // * *
10054 //
10055 // y
10056 // *----*----* *-10-*-11-*
10057 // / / / / / /
10058 // / 0 / 1 / 0 12 1
10059 // / / / / / /
10060 // *----*----*x *--6-*--7-*
10061
10062 new_quads[0]->set_bounding_object_indices(
10063 {line_indices[0],
10064 line_indices[12],
10065 line_indices[6],
10066 line_indices[10]});
10067 new_quads[1]->set_bounding_object_indices(
10068 {line_indices[12],
10069 line_indices[1],
10070 line_indices[7],
10071 line_indices[11]});
10072 new_quads[2]->set_bounding_object_indices(
10073 {line_indices[4],
10074 line_indices[8],
10075 line_indices[2],
10076 line_indices[12]});
10077 new_quads[3]->set_bounding_object_indices(
10078 {line_indices[5],
10079 line_indices[9],
10080 line_indices[12],
10081 line_indices[3]});
10082
10083 new_quads[0]->set_line_orientation(
10084 0, line_orientation[0]);
10085 new_quads[0]->set_line_orientation(
10086 2, line_orientation[6]);
10087 new_quads[0]->set_line_orientation(
10088 3, line_orientation[10]);
10089
10090 new_quads[1]->set_line_orientation(
10091 1, line_orientation[1]);
10092 new_quads[1]->set_line_orientation(
10093 2, line_orientation[7]);
10094 new_quads[1]->set_line_orientation(
10095 3, line_orientation[11]);
10096
10097 new_quads[2]->set_line_orientation(
10098 0, line_orientation[4]);
10099 new_quads[2]->set_line_orientation(
10100 1, line_orientation[8]);
10101 new_quads[2]->set_line_orientation(
10102 2, line_orientation[2]);
10103
10104 new_quads[3]->set_line_orientation(
10105 0, line_orientation[5]);
10106 new_quads[3]->set_line_orientation(
10107 1, line_orientation[9]);
10108 new_quads[3]->set_line_orientation(
10109 3, line_orientation[3]);
10110
10111 // the quads are numbered as follows:
10112 //
10113 // planes in the interior of the old hex:
10114 //
10115 // *
10116 // /|
10117 // / | x
10118 // /3 * *-------* *----*----*
10119 // * /| | | / / /
10120 // | / | | | / 0 / 1 /
10121 // |/ * | | / / /
10122 // * 2/ *-------*y *----*----*x
10123 // | /
10124 // |/
10125 // *
10126 //
10127 // children of the faces
10128 // of the old hex
10129 // *---*---* *---*---*
10130 // /|13 | 15| / / /|
10131 // / | | | /18 / 19/ |
10132 // / *---*---* / / / *
10133 // * 5/| | | *---*---* 7/|
10134 // | / |12 | 14| | 9 | 11| / |
10135 // |/4 *---*---* | | |/6 *
10136 // * / / / *---*---* /
10137 // | /16 / 17/ | | | /
10138 // |/ / / | 8 | 10|/
10139 // *---*---* *---*---*
10140 //
10141 // note that we have to take care of the
10142 // orientation of faces.
10143 const int quad_indices[20] = {
10144 new_quads[0]->index(), // 0
10145 new_quads[1]->index(),
10146 new_quads[2]->index(),
10147 new_quads[3]->index(),
10148
10149 hex->face(0)->child_index(
10150 child_at_origin[hex->face(0)->refinement_case() -
10151 1][f_fl[0]][f_ro[0]]), // 4
10152 hex->face(0)->child_index(
10153 1 -
10154 child_at_origin[hex->face(0)->refinement_case() -
10155 1][f_fl[0]][f_ro[0]]),
10156
10157 hex->face(1)->child_index(
10158 child_at_origin[hex->face(1)->refinement_case() -
10159 1][f_fl[1]][f_ro[1]]), // 6
10160 hex->face(1)->child_index(
10161 1 -
10162 child_at_origin[hex->face(1)->refinement_case() -
10163 1][f_fl[1]][f_ro[1]]),
10164
10165 hex->face(2)->isotropic_child_index(
10167 0, f_or[2], f_fl[2], f_ro[2])), // 8
10168 hex->face(2)->isotropic_child_index(
10170 1, f_or[2], f_fl[2], f_ro[2])),
10171 hex->face(2)->isotropic_child_index(
10173 2, f_or[2], f_fl[2], f_ro[2])),
10174 hex->face(2)->isotropic_child_index(
10176 3, f_or[2], f_fl[2], f_ro[2])),
10177
10178 hex->face(3)->isotropic_child_index(
10180 0, f_or[3], f_fl[3], f_ro[3])), // 12
10181 hex->face(3)->isotropic_child_index(
10183 1, f_or[3], f_fl[3], f_ro[3])),
10184 hex->face(3)->isotropic_child_index(
10186 2, f_or[3], f_fl[3], f_ro[3])),
10187 hex->face(3)->isotropic_child_index(
10189 3, f_or[3], f_fl[3], f_ro[3])),
10190
10191 hex->face(4)->child_index(
10192 child_at_origin[hex->face(4)->refinement_case() -
10193 1][f_fl[4]][f_ro[4]]), // 16
10194 hex->face(4)->child_index(
10195 1 -
10196 child_at_origin[hex->face(4)->refinement_case() -
10197 1][f_fl[4]][f_ro[4]]),
10198
10199 hex->face(5)->child_index(
10200 child_at_origin[hex->face(5)->refinement_case() -
10201 1][f_fl[5]][f_ro[5]]), // 18
10202 hex->face(5)->child_index(
10203 1 -
10204 child_at_origin[hex->face(5)->refinement_case() -
10205 1][f_fl[5]][f_ro[5]])};
10206
10207 // due to the exchange of x and y for the front
10208 // and back face, we order the children
10209 // according to
10210 //
10211 // *---*---*
10212 // | 1 | 3 |
10213 // *---*---*
10214 // | 0 | 2 |
10215 // *---*---*
10216 new_hexes[0]->set_bounding_object_indices(
10217 {quad_indices[4],
10218 quad_indices[2],
10219 quad_indices[8],
10220 quad_indices[12],
10221 quad_indices[16],
10222 quad_indices[0]});
10223 new_hexes[1]->set_bounding_object_indices(
10224 {quad_indices[5],
10225 quad_indices[3],
10226 quad_indices[9],
10227 quad_indices[13],
10228 quad_indices[0],
10229 quad_indices[18]});
10230 new_hexes[2]->set_bounding_object_indices(
10231 {quad_indices[2],
10232 quad_indices[6],
10233 quad_indices[10],
10234 quad_indices[14],
10235 quad_indices[17],
10236 quad_indices[1]});
10237 new_hexes[3]->set_bounding_object_indices(
10238 {quad_indices[3],
10239 quad_indices[7],
10240 quad_indices[11],
10241 quad_indices[15],
10242 quad_indices[1],
10243 quad_indices[19]});
10244 break;
10245 }
10246
10248 {
10249 //----------------------------
10250 //
10251 // RefinementCase<dim>::cut_yz
10252 //
10253 // the refined cube will look like this:
10254 //
10255 // *---------*
10256 // / /|
10257 // *---------* |
10258 // / /| |
10259 // *---------* |/|
10260 // | | * |
10261 // | |/| *
10262 // *---------* |/
10263 // | | *
10264 // | |/
10265 // *---------*
10266 //
10267
10268 // first, create the new
10269 // internal line
10270 new_lines[0]->set_bounding_object_indices(
10271
10272 {middle_vertex_index<dim, spacedim>(hex->face(0)),
10273 middle_vertex_index<dim, spacedim>(hex->face(1))});
10274
10275 // again, first collect some data about the
10276 // indices of the lines, with the following
10277 // numbering: (note that face 0 and 1 each are
10278 // shown twice for better readability)
10279
10280 // face 0: left plane
10281 // * *
10282 // /| /|
10283 // * | * |
10284 // /| * /| *
10285 // * 5/| * |7|
10286 // | * | | * |
10287 // |/| * |6| *
10288 // * 4/ * |/
10289 // | * | *
10290 // |/ |/
10291 // * *
10292 // face 1: right plane
10293 // * *
10294 // /| /|
10295 // * | * |
10296 // /| * /| *
10297 // * 9/| * |11
10298 // | * | | * |
10299 // |/| * |10 *
10300 // * 8/ * |/
10301 // | * | *
10302 // |/ |/
10303 // * *
10304 // face 2: front plane
10305 // (note: x,y exchanged)
10306 // *-------*
10307 // | |
10308 // *---0---*
10309 // | |
10310 // *-------*
10311 // face 3: back plane
10312 // (note: x,y exchanged)
10313 // *-------*
10314 // | |
10315 // *---1---*
10316 // | |
10317 // *-------*
10318 // face 4: bottom plane
10319 // *-------*
10320 // / /
10321 // *---2---*
10322 // / /
10323 // *-------*
10324 // face 5: top plane
10325 // *-------*
10326 // / /
10327 // *---3---*
10328 // / /
10329 // *-------*
10330 // middle planes
10331 // *-------* *-------*
10332 // / / | |
10333 // *---12--* | |
10334 // / / | |
10335 // *-------* *-------*
10336
10337 // set up a list of line iterators first. from
10338 // this, construct lists of line_indices and
10339 // line orientations later on
10340 const typename Triangulation<
10341 dim,
10342 spacedim>::raw_line_iterator lines[13] = {
10343 hex->face(2)->child(0)->line(
10344 (hex->face(2)->refinement_case() ==
10346 1 :
10347 3), // 0
10348 hex->face(3)->child(0)->line(
10349 (hex->face(3)->refinement_case() ==
10351 1 :
10352 3), // 1
10353 hex->face(4)->child(0)->line(
10354 (hex->face(4)->refinement_case() ==
10356 1 :
10357 3), // 2
10358 hex->face(5)->child(0)->line(
10359 (hex->face(5)->refinement_case() ==
10361 1 :
10362 3), // 3
10363
10364 hex->face(0)
10365 ->isotropic_child(
10367 0, f_or[0], f_fl[0], f_ro[0]))
10368 ->line(
10370 1, f_or[0], f_fl[0], f_ro[0])), // 4
10371 hex->face(0)
10372 ->isotropic_child(
10374 3, f_or[0], f_fl[0], f_ro[0]))
10375 ->line(
10377 0, f_or[0], f_fl[0], f_ro[0])), // 5
10378 hex->face(0)
10379 ->isotropic_child(
10381 0, f_or[0], f_fl[0], f_ro[0]))
10382 ->line(
10384 3, f_or[0], f_fl[0], f_ro[0])), // 6
10385 hex->face(0)
10386 ->isotropic_child(
10388 3, f_or[0], f_fl[0], f_ro[0]))
10389 ->line(
10391 2, f_or[0], f_fl[0], f_ro[0])), // 7
10392
10393 hex->face(1)
10394 ->isotropic_child(
10396 0, f_or[1], f_fl[1], f_ro[1]))
10397 ->line(
10399 1, f_or[1], f_fl[1], f_ro[1])), // 8
10400 hex->face(1)
10401 ->isotropic_child(
10403 3, f_or[1], f_fl[1], f_ro[1]))
10404 ->line(
10406 0, f_or[1], f_fl[1], f_ro[1])), // 9
10407 hex->face(1)
10408 ->isotropic_child(
10410 0, f_or[1], f_fl[1], f_ro[1]))
10411 ->line(
10413 3, f_or[1], f_fl[1], f_ro[1])), // 10
10414 hex->face(1)
10415 ->isotropic_child(
10417 3, f_or[1], f_fl[1], f_ro[1]))
10418 ->line(
10420 2, f_or[1], f_fl[1], f_ro[1])), // 11
10421
10422 new_lines[0] // 12
10423 };
10424
10425 unsigned int line_indices[13];
10426
10427 for (unsigned int i = 0; i < 13; ++i)
10428 line_indices[i] = lines[i]->index();
10429
10430 // the orientation of lines for the inner quads
10431 // is quite tricky. as these lines are newly
10432 // created ones and thus have no parents, they
10433 // cannot inherit this property. set up an array
10434 // and fill it with the respective values
10435 types::geometric_orientation line_orientation[13]{};
10436
10437 // the middle vertices of the lines of our front
10438 // face
10439 const unsigned int middle_vertices[4] = {
10440 hex->line(8)->child(0)->vertex_index(1),
10441 hex->line(10)->child(0)->vertex_index(1),
10442 hex->line(0)->child(0)->vertex_index(1),
10443 hex->line(4)->child(0)->vertex_index(1),
10444 };
10445
10446 // note: for lines 0 to 3 the orientation of the
10447 // line is 'true', if vertex 0 is on the front
10448 for (unsigned int i = 0; i < 4; ++i)
10449 if (lines[i]->vertex_index(0) == middle_vertices[i])
10450 line_orientation[i] =
10452 else
10453 {
10454 // it must be the other way round then
10455 Assert(lines[i]->vertex_index(1) ==
10456 middle_vertices[i],
10458 line_orientation[i] =
10460 }
10461
10462 // note: for lines 4 to 11 (inner lines of the
10463 // outer quads) the following holds: the second
10464 // vertex of the even lines in standard
10465 // orientation is the vertex in the middle of
10466 // the quad, whereas for odd lines the first
10467 // vertex is the same middle vertex.
10468 for (unsigned int i = 4; i < 12; ++i)
10469 if (lines[i]->vertex_index((i + 1) % 2) ==
10470 middle_vertex_index<dim, spacedim>(
10471 hex->face(i / 4 - 1)))
10472 line_orientation[i] =
10474 else
10475 {
10476 // it must be the other way round then
10477 Assert(lines[i]->vertex_index(i % 2) ==
10478 (middle_vertex_index<dim, spacedim>(
10479 hex->face(i / 4 - 1))),
10481 line_orientation[i] =
10483 }
10484 // for the last line the line orientation is always
10485 // the default, since it was just constructed that way
10486 line_orientation[12] =
10488
10489 // set up the 4 quads, numbered as follows (left
10490 // quad numbering, right line numbering
10491 // extracted from above)
10492 //
10493 // x
10494 // *-------* *---3---*
10495 // | 3 | 5 9
10496 // *-------* *---12--*
10497 // | 2 | 4 8
10498 // *-------*y *---2---*
10499 //
10500 // y
10501 // *---------* *----1----*
10502 // / 1 / 7 11
10503 // *---------* *----12---*
10504 // / 0 / 6 10
10505 // *---------*x *----0----*
10506
10507 new_quads[0]->set_bounding_object_indices(
10508 {line_indices[6],
10509 line_indices[10],
10510 line_indices[0],
10511 line_indices[12]});
10512 new_quads[1]->set_bounding_object_indices(
10513 {line_indices[7],
10514 line_indices[11],
10515 line_indices[12],
10516 line_indices[1]});
10517 new_quads[2]->set_bounding_object_indices(
10518 {line_indices[2],
10519 line_indices[12],
10520 line_indices[4],
10521 line_indices[8]});
10522 new_quads[3]->set_bounding_object_indices(
10523 {line_indices[12],
10524 line_indices[3],
10525 line_indices[5],
10526 line_indices[9]});
10527
10528 new_quads[0]->set_line_orientation(
10529 0, line_orientation[6]);
10530 new_quads[0]->set_line_orientation(
10531 1, line_orientation[10]);
10532 new_quads[0]->set_line_orientation(
10533 2, line_orientation[0]);
10534
10535 new_quads[1]->set_line_orientation(
10536 0, line_orientation[7]);
10537 new_quads[1]->set_line_orientation(
10538 1, line_orientation[11]);
10539 new_quads[1]->set_line_orientation(
10540 3, line_orientation[1]);
10541
10542 new_quads[2]->set_line_orientation(
10543 0, line_orientation[2]);
10544 new_quads[2]->set_line_orientation(
10545 2, line_orientation[4]);
10546 new_quads[2]->set_line_orientation(
10547 3, line_orientation[8]);
10548
10549 new_quads[3]->set_line_orientation(
10550 1, line_orientation[3]);
10551 new_quads[3]->set_line_orientation(
10552 2, line_orientation[5]);
10553 new_quads[3]->set_line_orientation(
10554 3, line_orientation[9]);
10555
10556 // the quads are numbered as follows:
10557 //
10558 // planes in the interior of the old hex:
10559 //
10560 // *
10561 // /|
10562 // / | x
10563 // / | *-------* *---------*
10564 // * | | 3 | / 1 /
10565 // | | *-------* *---------*
10566 // | * | 2 | / 0 /
10567 // | / *-------*y *---------*x
10568 // | /
10569 // |/
10570 // *
10571 //
10572 // children of the faces
10573 // of the old hex
10574 // *-------* *-------*
10575 // /| | / 19 /|
10576 // * | 15 | *-------* |
10577 // /|7*-------* / 18 /|11
10578 // * |/| | *-------* |/|
10579 // |6* | 14 | | 10* |
10580 // |/|5*-------* | 13 |/|9*
10581 // * |/ 17 / *-------* |/
10582 // |4*-------* | |8*
10583 // |/ 16 / | 12 |/
10584 // *-------* *-------*
10585 //
10586 // note that we have to take care of the
10587 // orientation of faces.
10588 const int quad_indices[20] = {
10589 new_quads[0]->index(), // 0
10590 new_quads[1]->index(),
10591 new_quads[2]->index(),
10592 new_quads[3]->index(),
10593
10594 hex->face(0)->isotropic_child_index(
10596 0, f_or[0], f_fl[0], f_ro[0])), // 4
10597 hex->face(0)->isotropic_child_index(
10599 1, f_or[0], f_fl[0], f_ro[0])),
10600 hex->face(0)->isotropic_child_index(
10602 2, f_or[0], f_fl[0], f_ro[0])),
10603 hex->face(0)->isotropic_child_index(
10605 3, f_or[0], f_fl[0], f_ro[0])),
10606
10607 hex->face(1)->isotropic_child_index(
10609 0, f_or[1], f_fl[1], f_ro[1])), // 8
10610 hex->face(1)->isotropic_child_index(
10612 1, f_or[1], f_fl[1], f_ro[1])),
10613 hex->face(1)->isotropic_child_index(
10615 2, f_or[1], f_fl[1], f_ro[1])),
10616 hex->face(1)->isotropic_child_index(
10618 3, f_or[1], f_fl[1], f_ro[1])),
10619
10620 hex->face(2)->child_index(
10621 child_at_origin[hex->face(2)->refinement_case() -
10622 1][f_fl[2]][f_ro[2]]), // 12
10623 hex->face(2)->child_index(
10624 1 -
10625 child_at_origin[hex->face(2)->refinement_case() -
10626 1][f_fl[2]][f_ro[2]]),
10627
10628 hex->face(3)->child_index(
10629 child_at_origin[hex->face(3)->refinement_case() -
10630 1][f_fl[3]][f_ro[3]]), // 14
10631 hex->face(3)->child_index(
10632 1 -
10633 child_at_origin[hex->face(3)->refinement_case() -
10634 1][f_fl[3]][f_ro[3]]),
10635
10636 hex->face(4)->child_index(
10637 child_at_origin[hex->face(4)->refinement_case() -
10638 1][f_fl[4]][f_ro[4]]), // 16
10639 hex->face(4)->child_index(
10640 1 -
10641 child_at_origin[hex->face(4)->refinement_case() -
10642 1][f_fl[4]][f_ro[4]]),
10643
10644 hex->face(5)->child_index(
10645 child_at_origin[hex->face(5)->refinement_case() -
10646 1][f_fl[5]][f_ro[5]]), // 18
10647 hex->face(5)->child_index(
10648 1 -
10649 child_at_origin[hex->face(5)->refinement_case() -
10650 1][f_fl[5]][f_ro[5]])};
10651
10652 new_hexes[0]->set_bounding_object_indices(
10653 {quad_indices[4],
10654 quad_indices[8],
10655 quad_indices[12],
10656 quad_indices[2],
10657 quad_indices[16],
10658 quad_indices[0]});
10659 new_hexes[1]->set_bounding_object_indices(
10660 {quad_indices[5],
10661 quad_indices[9],
10662 quad_indices[2],
10663 quad_indices[14],
10664 quad_indices[17],
10665 quad_indices[1]});
10666 new_hexes[2]->set_bounding_object_indices(
10667 {quad_indices[6],
10668 quad_indices[10],
10669 quad_indices[13],
10670 quad_indices[3],
10671 quad_indices[0],
10672 quad_indices[18]});
10673 new_hexes[3]->set_bounding_object_indices(
10674 {quad_indices[7],
10675 quad_indices[11],
10676 quad_indices[3],
10677 quad_indices[15],
10678 quad_indices[1],
10679 quad_indices[19]});
10680 break;
10681 }
10682
10684 {
10685 //----------------------------
10686 //
10687 // RefinementCase<dim>::cut_xyz
10688 // isotropic refinement
10689 //
10690 // the refined cube will look
10691 // like this:
10692 //
10693 // *----*----*
10694 // / / /|
10695 // *----*----* |
10696 // / / /| *
10697 // *----*----* |/|
10698 // | | | * |
10699 // | | |/| *
10700 // *----*----* |/
10701 // | | | *
10702 // | | |/
10703 // *----*----*
10704 //
10705
10706 // find the next unused vertex and set it
10707 // appropriately
10708 while (
10709 triangulation.vertices_used[next_unused_vertex] ==
10710 true)
10711 ++next_unused_vertex;
10712 Assert(
10713 next_unused_vertex < triangulation.vertices.size(),
10714 ExcMessage(
10715 "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."));
10716 triangulation.vertices_used[next_unused_vertex] =
10717 true;
10718
10719 // the new vertex is definitely in the interior,
10720 // so we need not worry about the
10721 // boundary. However we need to worry about
10722 // Manifolds. Let the cell compute its own
10723 // center, by querying the underlying manifold
10724 // object.
10725 triangulation.vertices[next_unused_vertex] =
10726 hex->center(true, true);
10727
10728 // set the data of the six lines. first collect
10729 // the indices of the seven vertices (consider
10730 // the two planes to be crossed to form the
10731 // planes cutting the hex in two vertically and
10732 // horizontally)
10733 //
10734 // *--3--* *--5--*
10735 // / / / | | |
10736 // 0--6--1 0--6--1
10737 // / / / | | |
10738 // *--2--* *--4--*
10739 // the lines are numbered
10740 // as follows:
10741 // *--*--* *--*--*
10742 // / 1 / | 5 |
10743 // *2-*-3* *2-*-3*
10744 // / 0 / | 4 |
10745 // *--*--* *--*--*
10746 //
10747 const unsigned int vertex_indices[7] = {
10748 middle_vertex_index<dim, spacedim>(hex->face(0)),
10749 middle_vertex_index<dim, spacedim>(hex->face(1)),
10750 middle_vertex_index<dim, spacedim>(hex->face(2)),
10751 middle_vertex_index<dim, spacedim>(hex->face(3)),
10752 middle_vertex_index<dim, spacedim>(hex->face(4)),
10753 middle_vertex_index<dim, spacedim>(hex->face(5)),
10754 next_unused_vertex};
10755
10756 new_lines[0]->set_bounding_object_indices(
10758 new_lines[1]->set_bounding_object_indices(
10760 new_lines[2]->set_bounding_object_indices(
10762 new_lines[3]->set_bounding_object_indices(
10764 new_lines[4]->set_bounding_object_indices(
10766 new_lines[5]->set_bounding_object_indices(
10768
10769 // again, first collect some data about the
10770 // indices of the lines, with the following
10771 // numbering: (note that face 0 and 1 each are
10772 // shown twice for better readability)
10773
10774 // face 0: left plane
10775 // * *
10776 // /| /|
10777 // * | * |
10778 // /| * /| *
10779 // * 1/| * |3|
10780 // | * | | * |
10781 // |/| * |2| *
10782 // * 0/ * |/
10783 // | * | *
10784 // |/ |/
10785 // * *
10786 // face 1: right plane
10787 // * *
10788 // /| /|
10789 // * | * |
10790 // /| * /| *
10791 // * 5/| * |7|
10792 // | * | | * |
10793 // |/| * |6| *
10794 // * 4/ * |/
10795 // | * | *
10796 // |/ |/
10797 // * *
10798 // face 2: front plane
10799 // (note: x,y exchanged)
10800 // *---*---*
10801 // | 11 |
10802 // *-8-*-9-*
10803 // | 10 |
10804 // *---*---*
10805 // face 3: back plane
10806 // (note: x,y exchanged)
10807 // *---*---*
10808 // | 15 |
10809 // *12-*-13*
10810 // | 14 |
10811 // *---*---*
10812 // face 4: bottom plane
10813 // *---*---*
10814 // / 17 /
10815 // *18-*-19*
10816 // / 16 /
10817 // *---*---*
10818 // face 5: top plane
10819 // *---*---*
10820 // / 21 /
10821 // *22-*-23*
10822 // / 20 /
10823 // *---*---*
10824 // middle planes
10825 // *---*---* *---*---*
10826 // / 25 / | 29 |
10827 // *26-*-27* *26-*-27*
10828 // / 24 / | 28 |
10829 // *---*---* *---*---*
10830
10831 // set up a list of line iterators first. from
10832 // this, construct lists of line_indices and
10833 // line orientations later on
10834 const typename Triangulation<
10835 dim,
10836 spacedim>::raw_line_iterator lines[30] = {
10837 hex->face(0)
10838 ->isotropic_child(
10840 0, f_or[0], f_fl[0], f_ro[0]))
10841 ->line(
10843 1, f_or[0], f_fl[0], f_ro[0])), // 0
10844 hex->face(0)
10845 ->isotropic_child(
10847 3, f_or[0], f_fl[0], f_ro[0]))
10848 ->line(
10850 0, f_or[0], f_fl[0], f_ro[0])), // 1
10851 hex->face(0)
10852 ->isotropic_child(
10854 0, f_or[0], f_fl[0], f_ro[0]))
10855 ->line(
10857 3, f_or[0], f_fl[0], f_ro[0])), // 2
10858 hex->face(0)
10859 ->isotropic_child(
10861 3, f_or[0], f_fl[0], f_ro[0]))
10862 ->line(
10864 2, f_or[0], f_fl[0], f_ro[0])), // 3
10865
10866 hex->face(1)
10867 ->isotropic_child(
10869 0, f_or[1], f_fl[1], f_ro[1]))
10870 ->line(
10872 1, f_or[1], f_fl[1], f_ro[1])), // 4
10873 hex->face(1)
10874 ->isotropic_child(
10876 3, f_or[1], f_fl[1], f_ro[1]))
10877 ->line(
10879 0, f_or[1], f_fl[1], f_ro[1])), // 5
10880 hex->face(1)
10881 ->isotropic_child(
10883 0, f_or[1], f_fl[1], f_ro[1]))
10884 ->line(
10886 3, f_or[1], f_fl[1], f_ro[1])), // 6
10887 hex->face(1)
10888 ->isotropic_child(
10890 3, f_or[1], f_fl[1], f_ro[1]))
10891 ->line(
10893 2, f_or[1], f_fl[1], f_ro[1])), // 7
10894
10895 hex->face(2)
10896 ->isotropic_child(
10898 0, f_or[2], f_fl[2], f_ro[2]))
10899 ->line(
10901 1, f_or[2], f_fl[2], f_ro[2])), // 8
10902 hex->face(2)
10903 ->isotropic_child(
10905 3, f_or[2], f_fl[2], f_ro[2]))
10906 ->line(
10908 0, f_or[2], f_fl[2], f_ro[2])), // 9
10909 hex->face(2)
10910 ->isotropic_child(
10912 0, f_or[2], f_fl[2], f_ro[2]))
10913 ->line(
10915 3, f_or[2], f_fl[2], f_ro[2])), // 10
10916 hex->face(2)
10917 ->isotropic_child(
10919 3, f_or[2], f_fl[2], f_ro[2]))
10920 ->line(
10922 2, f_or[2], f_fl[2], f_ro[2])), // 11
10923
10924 hex->face(3)
10925 ->isotropic_child(
10927 0, f_or[3], f_fl[3], f_ro[3]))
10928 ->line(
10930 1, f_or[3], f_fl[3], f_ro[3])), // 12
10931 hex->face(3)
10932 ->isotropic_child(
10934 3, f_or[3], f_fl[3], f_ro[3]))
10935 ->line(
10937 0, f_or[3], f_fl[3], f_ro[3])), // 13
10938 hex->face(3)
10939 ->isotropic_child(
10941 0, f_or[3], f_fl[3], f_ro[3]))
10942 ->line(
10944 3, f_or[3], f_fl[3], f_ro[3])), // 14
10945 hex->face(3)
10946 ->isotropic_child(
10948 3, f_or[3], f_fl[3], f_ro[3]))
10949 ->line(
10951 2, f_or[3], f_fl[3], f_ro[3])), // 15
10952
10953 hex->face(4)
10954 ->isotropic_child(
10956 0, f_or[4], f_fl[4], f_ro[4]))
10957 ->line(
10959 1, f_or[4], f_fl[4], f_ro[4])), // 16
10960 hex->face(4)
10961 ->isotropic_child(
10963 3, f_or[4], f_fl[4], f_ro[4]))
10964 ->line(
10966 0, f_or[4], f_fl[4], f_ro[4])), // 17
10967 hex->face(4)
10968 ->isotropic_child(
10970 0, f_or[4], f_fl[4], f_ro[4]))
10971 ->line(
10973 3, f_or[4], f_fl[4], f_ro[4])), // 18
10974 hex->face(4)
10975 ->isotropic_child(
10977 3, f_or[4], f_fl[4], f_ro[4]))
10978 ->line(
10980 2, f_or[4], f_fl[4], f_ro[4])), // 19
10981
10982 hex->face(5)
10983 ->isotropic_child(
10985 0, f_or[5], f_fl[5], f_ro[5]))
10986 ->line(
10988 1, f_or[5], f_fl[5], f_ro[5])), // 20
10989 hex->face(5)
10990 ->isotropic_child(
10992 3, f_or[5], f_fl[5], f_ro[5]))
10993 ->line(
10995 0, f_or[5], f_fl[5], f_ro[5])), // 21
10996 hex->face(5)
10997 ->isotropic_child(
10999 0, f_or[5], f_fl[5], f_ro[5]))
11000 ->line(
11002 3, f_or[5], f_fl[5], f_ro[5])), // 22
11003 hex->face(5)
11004 ->isotropic_child(
11006 3, f_or[5], f_fl[5], f_ro[5]))
11007 ->line(
11009 2, f_or[5], f_fl[5], f_ro[5])), // 23
11010
11011 new_lines[0], // 24
11012 new_lines[1], // 25
11013 new_lines[2], // 26
11014 new_lines[3], // 27
11015 new_lines[4], // 28
11016 new_lines[5] // 29
11017 };
11018
11019 unsigned int line_indices[30];
11020 for (unsigned int i = 0; i < 30; ++i)
11021 line_indices[i] = lines[i]->index();
11022
11023 // the orientation of lines for the inner quads
11024 // is quite tricky. as these lines are newly
11025 // created ones and thus have no parents, they
11026 // cannot inherit this property. set up an array
11027 // and fill it with the respective values
11028 types::geometric_orientation line_orientation[30]{};
11029
11030 // note: for the first 24 lines (inner lines of
11031 // the outer quads) the following holds: the
11032 // second vertex of the even lines in standard
11033 // orientation is the vertex in the middle of
11034 // the quad, whereas for odd lines the first
11035 // vertex is the same middle vertex.
11036 for (unsigned int i = 0; i < 24; ++i)
11037 if (lines[i]->vertex_index((i + 1) % 2) ==
11038 vertex_indices[i / 4])
11039 line_orientation[i] =
11041 else
11042 {
11043 // it must be the other way
11044 // round then
11045 Assert(lines[i]->vertex_index(i % 2) ==
11046 vertex_indices[i / 4],
11048 line_orientation[i] =
11050 }
11051 // for the last 6 lines the line orientation is
11052 // always true, since they were just constructed
11053 // that way
11054 for (unsigned int i = 24; i < 30; ++i)
11055 line_orientation[i] =
11057
11058 // set up the 12 quads, numbered as follows
11059 // (left quad numbering, right line numbering
11060 // extracted from above)
11061 //
11062 // * *
11063 // /| 21|
11064 // * | * 15
11065 // y/|3* 20| *
11066 // * |/| * |/|
11067 // |2* |x 11 * 14
11068 // |/|1* |/| *
11069 // * |/ * |17
11070 // |0* 10 *
11071 // |/ |16
11072 // * *
11073 //
11074 // x
11075 // *---*---* *22-*-23*
11076 // | 5 | 7 | 1 29 5
11077 // *---*---* *26-*-27*
11078 // | 4 | 6 | 0 28 4
11079 // *---*---*y *18-*-19*
11080 //
11081 // y
11082 // *----*----* *-12-*-13-*
11083 // / 10 / 11 / 3 25 7
11084 // *----*----* *-26-*-27-*
11085 // / 8 / 9 / 2 24 6
11086 // *----*----*x *--8-*--9-*
11087
11088 new_quads[0]->set_bounding_object_indices(
11089 {line_indices[10],
11090 line_indices[28],
11091 line_indices[16],
11092 line_indices[24]});
11093 new_quads[1]->set_bounding_object_indices(
11094 {line_indices[28],
11095 line_indices[14],
11096 line_indices[17],
11097 line_indices[25]});
11098 new_quads[2]->set_bounding_object_indices(
11099 {line_indices[11],
11100 line_indices[29],
11101 line_indices[24],
11102 line_indices[20]});
11103 new_quads[3]->set_bounding_object_indices(
11104 {line_indices[29],
11105 line_indices[15],
11106 line_indices[25],
11107 line_indices[21]});
11108 new_quads[4]->set_bounding_object_indices(
11109 {line_indices[18],
11110 line_indices[26],
11111 line_indices[0],
11112 line_indices[28]});
11113 new_quads[5]->set_bounding_object_indices(
11114 {line_indices[26],
11115 line_indices[22],
11116 line_indices[1],
11117 line_indices[29]});
11118 new_quads[6]->set_bounding_object_indices(
11119 {line_indices[19],
11120 line_indices[27],
11121 line_indices[28],
11122 line_indices[4]});
11123 new_quads[7]->set_bounding_object_indices(
11124 {line_indices[27],
11125 line_indices[23],
11126 line_indices[29],
11127 line_indices[5]});
11128 new_quads[8]->set_bounding_object_indices(
11129 {line_indices[2],
11130 line_indices[24],
11131 line_indices[8],
11132 line_indices[26]});
11133 new_quads[9]->set_bounding_object_indices(
11134 {line_indices[24],
11135 line_indices[6],
11136 line_indices[9],
11137 line_indices[27]});
11138 new_quads[10]->set_bounding_object_indices(
11139 {line_indices[3],
11140 line_indices[25],
11141 line_indices[26],
11142 line_indices[12]});
11143 new_quads[11]->set_bounding_object_indices(
11144 {line_indices[25],
11145 line_indices[7],
11146 line_indices[27],
11147 line_indices[13]});
11148
11149 // now reset the line_orientation flags of outer
11150 // lines as they cannot be set in a loop (at
11151 // least not easily)
11152 new_quads[0]->set_line_orientation(
11153 0, line_orientation[10]);
11154 new_quads[0]->set_line_orientation(
11155 2, line_orientation[16]);
11156
11157 new_quads[1]->set_line_orientation(
11158 1, line_orientation[14]);
11159 new_quads[1]->set_line_orientation(
11160 2, line_orientation[17]);
11161
11162 new_quads[2]->set_line_orientation(
11163 0, line_orientation[11]);
11164 new_quads[2]->set_line_orientation(
11165 3, line_orientation[20]);
11166
11167 new_quads[3]->set_line_orientation(
11168 1, line_orientation[15]);
11169 new_quads[3]->set_line_orientation(
11170 3, line_orientation[21]);
11171
11172 new_quads[4]->set_line_orientation(
11173 0, line_orientation[18]);
11174 new_quads[4]->set_line_orientation(
11175 2, line_orientation[0]);
11176
11177 new_quads[5]->set_line_orientation(
11178 1, line_orientation[22]);
11179 new_quads[5]->set_line_orientation(
11180 2, line_orientation[1]);
11181
11182 new_quads[6]->set_line_orientation(
11183 0, line_orientation[19]);
11184 new_quads[6]->set_line_orientation(
11185 3, line_orientation[4]);
11186
11187 new_quads[7]->set_line_orientation(
11188 1, line_orientation[23]);
11189 new_quads[7]->set_line_orientation(
11190 3, line_orientation[5]);
11191
11192 new_quads[8]->set_line_orientation(
11193 0, line_orientation[2]);
11194 new_quads[8]->set_line_orientation(
11195 2, line_orientation[8]);
11196
11197 new_quads[9]->set_line_orientation(
11198 1, line_orientation[6]);
11199 new_quads[9]->set_line_orientation(
11200 2, line_orientation[9]);
11201
11202 new_quads[10]->set_line_orientation(
11203 0, line_orientation[3]);
11204 new_quads[10]->set_line_orientation(
11205 3, line_orientation[12]);
11206
11207 new_quads[11]->set_line_orientation(
11208 1, line_orientation[7]);
11209 new_quads[11]->set_line_orientation(
11210 3, line_orientation[13]);
11211
11212 //-------------------------------
11213 // create the eight new hexes
11214 //
11215 // again first collect some data. here, we need
11216 // the indices of a whole lotta quads.
11217
11218 // the quads are numbered as follows:
11219 //
11220 // planes in the interior of the old hex:
11221 //
11222 // *
11223 // /|
11224 // * |
11225 // /|3* *---*---* *----*----*
11226 // * |/| | 5 | 7 | / 10 / 11 /
11227 // |2* | *---*---* *----*----*
11228 // |/|1* | 4 | 6 | / 8 / 9 /
11229 // * |/ *---*---*y *----*----*x
11230 // |0*
11231 // |/
11232 // *
11233 //
11234 // children of the faces
11235 // of the old hex
11236 // *-------* *-------*
11237 // /|25 27| /34 35/|
11238 // 15| | / /19
11239 // / | | /32 33/ |
11240 // * |24 26| *-------*18 |
11241 // 1413*-------* |21 23| 17*
11242 // | /30 31/ | | /
11243 // 12/ / | |16
11244 // |/28 29/ |20 22|/
11245 // *-------* *-------*
11246 //
11247 // note that we have to
11248 // take care of the
11249 // orientation of
11250 // faces.
11251 const int quad_indices[36] = {
11252 new_quads[0]->index(), // 0
11253 new_quads[1]->index(),
11254 new_quads[2]->index(),
11255 new_quads[3]->index(),
11256 new_quads[4]->index(),
11257 new_quads[5]->index(),
11258 new_quads[6]->index(),
11259 new_quads[7]->index(),
11260 new_quads[8]->index(),
11261 new_quads[9]->index(),
11262 new_quads[10]->index(),
11263 new_quads[11]->index(), // 11
11264
11265 hex->face(0)->isotropic_child_index(
11267 0, f_or[0], f_fl[0], f_ro[0])), // 12
11268 hex->face(0)->isotropic_child_index(
11270 1, f_or[0], f_fl[0], f_ro[0])),
11271 hex->face(0)->isotropic_child_index(
11273 2, f_or[0], f_fl[0], f_ro[0])),
11274 hex->face(0)->isotropic_child_index(
11276 3, f_or[0], f_fl[0], f_ro[0])),
11277
11278 hex->face(1)->isotropic_child_index(
11280 0, f_or[1], f_fl[1], f_ro[1])), // 16
11281 hex->face(1)->isotropic_child_index(
11283 1, f_or[1], f_fl[1], f_ro[1])),
11284 hex->face(1)->isotropic_child_index(
11286 2, f_or[1], f_fl[1], f_ro[1])),
11287 hex->face(1)->isotropic_child_index(
11289 3, f_or[1], f_fl[1], f_ro[1])),
11290
11291 hex->face(2)->isotropic_child_index(
11293 0, f_or[2], f_fl[2], f_ro[2])), // 20
11294 hex->face(2)->isotropic_child_index(
11296 1, f_or[2], f_fl[2], f_ro[2])),
11297 hex->face(2)->isotropic_child_index(
11299 2, f_or[2], f_fl[2], f_ro[2])),
11300 hex->face(2)->isotropic_child_index(
11302 3, f_or[2], f_fl[2], f_ro[2])),
11303
11304 hex->face(3)->isotropic_child_index(
11306 0, f_or[3], f_fl[3], f_ro[3])), // 24
11307 hex->face(3)->isotropic_child_index(
11309 1, f_or[3], f_fl[3], f_ro[3])),
11310 hex->face(3)->isotropic_child_index(
11312 2, f_or[3], f_fl[3], f_ro[3])),
11313 hex->face(3)->isotropic_child_index(
11315 3, f_or[3], f_fl[3], f_ro[3])),
11316
11317 hex->face(4)->isotropic_child_index(
11319 0, f_or[4], f_fl[4], f_ro[4])), // 28
11320 hex->face(4)->isotropic_child_index(
11322 1, f_or[4], f_fl[4], f_ro[4])),
11323 hex->face(4)->isotropic_child_index(
11325 2, f_or[4], f_fl[4], f_ro[4])),
11326 hex->face(4)->isotropic_child_index(
11328 3, f_or[4], f_fl[4], f_ro[4])),
11329
11330 hex->face(5)->isotropic_child_index(
11332 0, f_or[5], f_fl[5], f_ro[5])), // 32
11333 hex->face(5)->isotropic_child_index(
11335 1, f_or[5], f_fl[5], f_ro[5])),
11336 hex->face(5)->isotropic_child_index(
11338 2, f_or[5], f_fl[5], f_ro[5])),
11339 hex->face(5)->isotropic_child_index(
11341 3, f_or[5], f_fl[5], f_ro[5]))};
11342
11343 // bottom children
11344 new_hexes[0]->set_bounding_object_indices(
11345 {quad_indices[12],
11346 quad_indices[0],
11347 quad_indices[20],
11348 quad_indices[4],
11349 quad_indices[28],
11350 quad_indices[8]});
11351 new_hexes[1]->set_bounding_object_indices(
11352 {quad_indices[0],
11353 quad_indices[16],
11354 quad_indices[22],
11355 quad_indices[6],
11356 quad_indices[29],
11357 quad_indices[9]});
11358 new_hexes[2]->set_bounding_object_indices(
11359 {quad_indices[13],
11360 quad_indices[1],
11361 quad_indices[4],
11362 quad_indices[24],
11363 quad_indices[30],
11364 quad_indices[10]});
11365 new_hexes[3]->set_bounding_object_indices(
11366 {quad_indices[1],
11367 quad_indices[17],
11368 quad_indices[6],
11369 quad_indices[26],
11370 quad_indices[31],
11371 quad_indices[11]});
11372
11373 // top children
11374 new_hexes[4]->set_bounding_object_indices(
11375 {quad_indices[14],
11376 quad_indices[2],
11377 quad_indices[21],
11378 quad_indices[5],
11379 quad_indices[8],
11380 quad_indices[32]});
11381 new_hexes[5]->set_bounding_object_indices(
11382 {quad_indices[2],
11383 quad_indices[18],
11384 quad_indices[23],
11385 quad_indices[7],
11386 quad_indices[9],
11387 quad_indices[33]});
11388 new_hexes[6]->set_bounding_object_indices(
11389 {quad_indices[15],
11390 quad_indices[3],
11391 quad_indices[5],
11392 quad_indices[25],
11393 quad_indices[10],
11394 quad_indices[34]});
11395 new_hexes[7]->set_bounding_object_indices(
11396 {quad_indices[3],
11397 quad_indices[19],
11398 quad_indices[7],
11399 quad_indices[27],
11400 quad_indices[11],
11401 quad_indices[35]});
11402 break;
11403 }
11404 default:
11405 // all refinement cases have been treated, there
11406 // only remains
11407 // RefinementCase<dim>::no_refinement as
11408 // untreated enumeration value. However, in that
11409 // case we should have aborted much
11410 // earlier. thus we should never get here
11412 break;
11413 } // switch (ref_case)
11414
11415 // and set face orientation flags. note that new
11416 // faces in the interior of the mother cell always
11417 // have a correctly oriented face, but the ones on
11418 // the outer faces will inherit this flag
11419 //
11420 // the flag have been set to true for all faces
11421 // initially, now go the other way round and reset
11422 // faces that are at the boundary of the mother cube
11423 //
11424 // the same is true for the face_flip and
11425 // face_rotation flags. however, the latter two are
11426 // set to false by default as this is the standard
11427 // value
11428
11429 // loop over all faces and all (relevant) subfaces
11430 // of that in order to set the correct values for
11431 // face_orientation, face_flip and face_rotation,
11432 // which are inherited from the corresponding face
11433 // of the mother cube
11434 for (const unsigned int f : GeometryInfo<dim>::face_indices())
11435 for (unsigned int s = 0;
11438 ref_case, f)),
11439 1U);
11440 ++s)
11441 {
11442 const unsigned int current_child =
11444 ref_case,
11445 f,
11446 s,
11447 f_or[f],
11448 f_fl[f],
11449 f_ro[f],
11451 ref_case, f, f_or[f], f_fl[f], f_ro[f]));
11452 new_hexes[current_child]->set_combined_face_orientation(
11453 f, f_co[f]);
11454 }
11455
11456 // now see if we have created cells that are
11457 // distorted and if so add them to our list
11458 if (check_for_distorted_cells &&
11459 has_distorted_children<dim, spacedim>(hex))
11460 cells_with_distorted_children.distorted_cells.push_back(
11461 hex);
11462
11463 // note that the refinement flag was already cleared
11464 // at the beginning of this loop
11465
11466 // inform all listeners that cell refinement is done
11467 triangulation.signals.post_refinement_on_cell(hex);
11468 }
11469 }
11470
11471 // clear user data on quads. we used some of this data to
11472 // indicate anisotropic refinemnt cases on faces. all data
11473 // should be cleared by now, but the information whether we
11474 // used indices or pointers is still present. reset it now to
11475 // enable the user to use whichever they like later on.
11476 triangulation.faces->quads.clear_user_data();
11477
11478 // return the list with distorted children
11479 return cells_with_distorted_children;
11480 }
11481
11482
11495 template <int spacedim>
11496 static void
11499
11500
11501
11502 template <int dim, int spacedim>
11503 static void
11506 {
11507 // If the codimension is one, we cannot perform this check
11508 // yet.
11509 if (spacedim > dim)
11510 return;
11511
11512 for (const auto &cell : triangulation.cell_iterators())
11513 if (cell->at_boundary() && cell->refine_flag_set() &&
11514 cell->refine_flag_set() !=
11516 {
11517 // The cell is at the boundary and it is flagged for
11518 // anisotropic refinement. Therefore, we have a closer
11519 // look
11520 const RefinementCase<dim> ref_case = cell->refine_flag_set();
11521 for (const unsigned int face_no :
11523 if (cell->face(face_no)->at_boundary())
11524 {
11525 // this is the critical face at the boundary.
11527 face_no) !=
11529 {
11530 // up to now, we do not want to refine this
11531 // cell along the face under consideration
11532 // here.
11533 const typename Triangulation<dim,
11534 spacedim>::face_iterator
11535 face = cell->face(face_no);
11536 // the new point on the boundary would be this
11537 // one.
11538 const Point<spacedim> new_bound = face->center(true);
11539 // to check it, transform to the unit cell
11540 // with a linear mapping
11541 const Point<dim> new_unit =
11542 cell->reference_cell()
11543 .template get_default_linear_mapping<dim,
11544 spacedim>()
11545 .transform_real_to_unit_cell(cell, new_bound);
11546
11547 // Now, we have to calculate the distance from
11548 // the face in the unit cell.
11549
11550 // take the correct coordinate direction (0
11551 // for faces 0 and 1, 1 for faces 2 and 3, 2
11552 // for faces 4 and 5) and subtract the correct
11553 // boundary value of the face (0 for faces 0,
11554 // 2, and 4; 1 for faces 1, 3 and 5)
11555 const double dist =
11556 std::fabs(new_unit[face_no / 2] - face_no % 2);
11557
11558 // compare this with the empirical value
11559 // allowed. if it is too big, flag the face
11560 // for isotropic refinement
11561 const double allowed = 0.25;
11562
11563 if (dist > allowed)
11564 cell->flag_for_face_refinement(face_no);
11565 } // if flagged for anistropic refinement
11566 } // if (cell->face(face)->at_boundary())
11567 } // for all cells
11568 }
11569
11570
11583 template <int dim, int spacedim>
11584 static void
11586 {
11587 Assert(dim < 3,
11588 ExcMessage("Wrong function called -- there should "
11589 "be a specialization."));
11590 }
11591
11592
11593 template <int spacedim>
11594 static void
11597 {
11598 const unsigned int dim = 3;
11599 using raw_line_iterator =
11601
11602 // variable to store whether the mesh was changed in the
11603 // present loop and in the whole process
11604 bool mesh_changed = false;
11605
11606 do
11607 {
11608 mesh_changed = false;
11609
11610 // for this following, we need to know which cells are
11611 // going to be coarsened, if we had to make a
11612 // decision. the following function sets these flags:
11613 triangulation.fix_coarsen_flags();
11614
11615 // first clear flags on lines, since we need them to determine
11616 // which lines will be refined
11617 triangulation.clear_user_flags_line();
11618
11619 // flag those lines that are refined and will not be
11620 // coarsened and those that will be refined
11621 for (const auto &cell : triangulation.cell_iterators())
11622 if (cell->refine_flag_set())
11623 {
11624 const std::array<unsigned int, 12> line_indices =
11625 TriaAccessorImplementation::Implementation::
11626 get_line_indices_of_cell(*cell);
11627 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11629 cell->refine_flag_set(), l) ==
11631 {
11632 raw_line_iterator line(&triangulation,
11633 0,
11634 line_indices[l]);
11635 // flag a line, that will be refined
11636 line->set_user_flag();
11637 }
11638 }
11639 else if (cell->has_children() &&
11640 !cell->child(0)->coarsen_flag_set())
11641 {
11642 const std::array<unsigned int, 12> line_indices =
11643 TriaAccessorImplementation::Implementation::
11644 get_line_indices_of_cell(*cell);
11645 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11647 cell->refinement_case(), l) ==
11649 {
11650 raw_line_iterator line(&triangulation,
11651 0,
11652 line_indices[l]);
11653 // flag a line, that is refined and will stay so
11654 line->set_user_flag();
11655 }
11656 }
11657 else if (cell->has_children() &&
11658 cell->child(0)->coarsen_flag_set())
11659 cell->set_user_flag();
11660
11661
11662 // now check whether there are cells with lines that are
11663 // more than once refined or that will be more than once
11664 // refined. The first thing should never be the case, in
11665 // the second case we flag the cell for refinement
11667 cell = triangulation.last_active();
11668 cell != triangulation.end();
11669 --cell)
11670 {
11671 const std::array<unsigned int, 12> line_indices =
11672 TriaAccessorImplementation::Implementation::
11673 get_line_indices_of_cell(*cell);
11674 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11675 {
11676 raw_line_iterator line(&triangulation, 0, line_indices[l]);
11677 if (line->has_children())
11678 {
11679 // if this line is refined, its children should
11680 // not have further children
11681 //
11682 // however, if any of the children is flagged
11683 // for further refinement, we need to refine
11684 // this cell also (at least, if the cell is not
11685 // already flagged)
11686 bool offending_line_found = false;
11687
11688 for (unsigned int c = 0; c < 2; ++c)
11689 {
11690 Assert(line->child(c)->has_children() == false,
11692
11693 if (line->child(c)->user_flag_set() &&
11695 cell->refine_flag_set(), l) ==
11697 {
11698 // tag this cell for refinement
11699 cell->clear_coarsen_flag();
11700 // if anisotropic coarsening is allowed:
11701 // extend the refine_flag in the needed
11702 // direction, else set refine_flag
11703 // (isotropic)
11704 if (triangulation.smooth_grid &
11706 allow_anisotropic_smoothing)
11707 cell->flag_for_line_refinement(l);
11708 else
11709 cell->set_refine_flag();
11710
11711 for (unsigned int k = 0; k < cell->n_lines();
11712 ++k)
11714 cell->refine_flag_set(), l) ==
11716 // flag a line, that will be refined
11717 raw_line_iterator(&triangulation,
11718 0,
11719 line_indices[k])
11720 ->set_user_flag();
11721
11722 // note that we have changed the grid
11723 offending_line_found = true;
11724
11725 // it may save us several loop
11726 // iterations if we flag all lines of
11727 // this cell now (and not at the outset
11728 // of the next iteration) for refinement
11729 for (unsigned int k = 0; k < cell->n_lines();
11730 ++k)
11731 {
11732 const auto line =
11733 raw_line_iterator(&triangulation,
11734 0,
11735 line_indices[k]);
11736 if (!line->has_children() &&
11738 line_refinement_case(
11739 cell->refine_flag_set(), k) !=
11741 line->set_user_flag();
11742 }
11743
11744 break;
11745 }
11746 }
11747
11748 if (offending_line_found)
11749 {
11750 mesh_changed = true;
11751 break;
11752 }
11753 }
11754 }
11755 }
11756
11757
11758 // there is another thing here: if any of the lines will
11759 // be refined, then we may not coarsen the present cell
11760 // similarly, if any of the lines *is* already refined, we
11761 // may not coarsen the current cell. however, there's a
11762 // catch: if the line is refined, but the cell behind it
11763 // is going to be coarsened, then the situation
11764 // changes. if we forget this second condition, the
11765 // refine_and_coarsen_3d test will start to fail. note
11766 // that to know which cells are going to be coarsened, the
11767 // call for fix_coarsen_flags above is necessary
11769 triangulation.last();
11770 cell != triangulation.end();
11771 --cell)
11772 if (cell->user_flag_set())
11773 {
11774 const std::array<unsigned int, 12> line_indices =
11775 TriaAccessorImplementation::Implementation::
11776 get_line_indices_of_cell(*cell);
11777 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11778 {
11779 raw_line_iterator line(&triangulation,
11780 0,
11781 line_indices[l]);
11782 if (line->has_children() &&
11783 (line->child(0)->user_flag_set() ||
11784 line->child(1)->user_flag_set()))
11785 {
11786 for (unsigned int c = 0; c < cell->n_children(); ++c)
11787 cell->child(c)->clear_coarsen_flag();
11788 cell->clear_user_flag();
11789 for (unsigned int k = 0; k < cell->n_lines(); ++k)
11791 cell->refinement_case(), k) ==
11793 // flag a line, that is refined and will
11794 // stay so
11795 raw_line_iterator(&triangulation,
11796 0,
11797 line_indices[k])
11798 ->set_user_flag();
11799 mesh_changed = true;
11800 break;
11801 }
11802 }
11803 }
11804 }
11805 while (mesh_changed == true);
11806 }
11807
11808
11809
11816 template <int dim, int spacedim>
11817 static bool
11820 {
11821 // in 1d, coarsening is always allowed since we don't enforce
11822 // the 2:1 constraint there
11823 if (dim == 1)
11824 return true;
11825
11826 const RefinementCase<dim> ref_case = cell->refinement_case();
11827 for (const unsigned int n : GeometryInfo<dim>::face_indices())
11828 {
11829 // if the cell is not refined along that face, coarsening
11830 // will not change anything, so do nothing. the same
11831 // applies, if the face is at the boundary
11832 const RefinementCase<dim - 1> face_ref_case =
11833 GeometryInfo<dim>::face_refinement_case(cell->refinement_case(),
11834 n);
11835
11836 const unsigned int n_subfaces =
11837 GeometryInfo<dim - 1>::n_children(face_ref_case);
11838
11839 if (n_subfaces == 0 || cell->at_boundary(n))
11840 continue;
11841 for (unsigned int c = 0; c < n_subfaces; ++c)
11842 {
11844 child = cell->child(
11846
11848 child_neighbor = child->neighbor(n);
11849 if (!child->neighbor_is_coarser(n))
11850 {
11851 // in 2d, if the child's neighbor is coarser, then it has
11852 // no children. however, in 3d it might be
11853 // otherwise. consider for example, that our face might be
11854 // refined with cut_x, but the neighbor is refined with
11855 // cut_xy at that face. then the neighbor pointers of the
11856 // children of our cell will point to the common neighbor
11857 // cell, not to its children. what we really want to know
11858 // in the following is, whether the neighbor cell is
11859 // refined twice with reference to our cell. that only
11860 // has to be asked, if the child's neighbor is not a
11861 // coarser one. we check whether some of the children on
11862 // the neighbor are not flagged for coarsening, in that
11863 // case we may not coarsen. it is enough to check the
11864 // first child because we have already fixed the coarsen
11865 // flags on finer levels
11866 if (child_neighbor->has_children() &&
11867 !(child_neighbor->child(0)->is_active() &&
11868 child_neighbor->child(0)->coarsen_flag_set()))
11869 return false;
11870
11871 // the same applies, if the neighbors children are not
11872 // refined but will be after refinement
11873 if (child_neighbor->refine_flag_set())
11874 return false;
11875 }
11876 }
11877 }
11878 return true;
11879 }
11880 };
11881
11882
11887 {
11888 template <int spacedim>
11889 static void
11892
11893 template <int dim, int spacedim>
11895 {
11896 std::vector<std::pair<unsigned int, unsigned int>> adjacent_cells(
11897 2 * triangulation.n_raw_faces(),
11898 {numbers::invalid_unsigned_int, numbers::invalid_unsigned_int});
11899
11900 const auto set_entry = [&](const auto &face_index, const auto &cell) {
11901 const std::pair<unsigned int, unsigned int> cell_pair = {
11902 cell->level(), cell->index()};
11903 unsigned int index;
11904
11905 if (adjacent_cells[2 * face_index].first ==
11907 adjacent_cells[2 * face_index].second ==
11909 {
11910 index = 2 * face_index + 0;
11911 }
11912 else
11913 {
11914 Assert(((adjacent_cells[2 * face_index + 1].first ==
11916 (adjacent_cells[2 * face_index + 1].second ==
11919 index = 2 * face_index + 1;
11920 }
11921
11922 adjacent_cells[index] = cell_pair;
11923 };
11924
11925 const auto get_entry =
11926 [&](const auto &face_index,
11927 const auto &cell) -> TriaIterator<CellAccessor<dim, spacedim>> {
11928 auto test = adjacent_cells[2 * face_index];
11929
11930 if (test == std::pair<unsigned int, unsigned int>(cell->level(),
11931 cell->index()))
11932 test = adjacent_cells[2 * face_index + 1];
11933
11934 if ((test.first != numbers::invalid_unsigned_int) &&
11935 (test.second != numbers::invalid_unsigned_int))
11937 test.first,
11938 test.second);
11939 else
11941 };
11942
11943 for (const auto &cell : triangulation.cell_iterators())
11944 for (const auto &face : cell->face_iterators())
11945 {
11946 set_entry(face->index(), cell);
11947
11948 if (cell->is_active() && face->has_children())
11949 for (unsigned int c = 0; c < face->n_children(); ++c)
11950 set_entry(face->child(c)->index(), cell);
11951 }
11952
11953 for (const auto &cell : triangulation.cell_iterators())
11954 for (auto f : cell->face_indices())
11955 cell->set_neighbor(f, get_entry(cell->face(f)->index(), cell));
11956 }
11957
11958 template <int dim, int spacedim>
11959 static void
11961 Triangulation<dim, spacedim> & /*triangulation*/,
11963 std::vector<unsigned int> & /*line_cell_count*/,
11964 std::vector<unsigned int> & /*quad_cell_count*/)
11965 {
11967 }
11968
11969 template <int dim, int spacedim>
11972 const bool check_for_distorted_cells)
11973 {
11974 return Implementation::execute_refinement_isotropic(
11975 triangulation, check_for_distorted_cells);
11976 }
11977
11978 template <int dim, int spacedim>
11979 static void
11981 Triangulation<dim, spacedim> & /*triangulation*/)
11982 {
11983 // nothing to do since anisotropy is not supported
11984 }
11985
11986 template <int dim, int spacedim>
11987 static void
11990 {
11991 Implementation::prepare_refinement_dim_dependent(triangulation);
11992 }
11993
11994 template <int dim, int spacedim>
11995 static bool
11998 {
12000
12001 return false;
12002 }
12003 };
12004
12005
12006 template <int dim, int spacedim>
12009 {
12010 static const FlatManifold<dim, spacedim> flat_manifold;
12011 return flat_manifold;
12012 }
12013 } // namespace TriangulationImplementation
12014} // namespace internal
12015
12016#ifndef DOXYGEN
12017
12018template <int dim, int spacedim>
12021
12022
12023
12024template <int dim, int spacedim>
12027 const MeshSmoothing smooth_grid,
12028 const bool check_for_distorted_cells)
12029 : cell_attached_data({0, 0, {}, {}})
12030 , smooth_grid(smooth_grid)
12031 , anisotropic_refinement(false)
12032 , check_for_distorted_cells(check_for_distorted_cells)
12033{
12034 if (dim == 1)
12035 {
12036 vertex_to_boundary_id_map_1d =
12037 std::make_unique<std::map<unsigned int, types::boundary_id>>();
12038 vertex_to_manifold_id_map_1d =
12039 std::make_unique<std::map<unsigned int, types::manifold_id>>();
12040 }
12041
12042 // connect the any_change signal to the other top level signals
12043 signals.create.connect(signals.any_change);
12044 signals.post_refinement.connect(signals.any_change);
12045 signals.clear.connect(signals.any_change);
12046 signals.mesh_movement.connect(signals.any_change);
12047}
12048
12049
12050
12051template <int dim, int spacedim>
12054 Triangulation<dim, spacedim> &&tria) noexcept
12055 : EnableObserverPointer(std::move(tria))
12056 , smooth_grid(tria.smooth_grid)
12057 , reference_cells(std::move(tria.reference_cells))
12058 , periodic_face_pairs_level_0(std::move(tria.periodic_face_pairs_level_0))
12059 , periodic_face_map(std::move(tria.periodic_face_map))
12060 , levels(std::move(tria.levels))
12061 , faces(std::move(tria.faces))
12062 , vertices(std::move(tria.vertices))
12063 , vertices_used(std::move(tria.vertices_used))
12064 , manifolds(std::move(tria.manifolds))
12065 , anisotropic_refinement(tria.anisotropic_refinement)
12066 , check_for_distorted_cells(tria.check_for_distorted_cells)
12067 , number_cache(std::move(tria.number_cache))
12068 , vertex_to_boundary_id_map_1d(std::move(tria.vertex_to_boundary_id_map_1d))
12069 , vertex_to_manifold_id_map_1d(std::move(tria.vertex_to_manifold_id_map_1d))
12070{
12072
12073 if (tria.policy)
12074 this->policy = tria.policy->clone();
12075}
12076
12077
12078template <int dim, int spacedim>
12081 Triangulation<dim, spacedim> &&tria) noexcept
12082{
12083 EnableObserverPointer::operator=(std::move(tria));
12084
12085 smooth_grid = tria.smooth_grid;
12086 reference_cells = std::move(tria.reference_cells);
12087 periodic_face_pairs_level_0 = std::move(tria.periodic_face_pairs_level_0);
12088 periodic_face_map = std::move(tria.periodic_face_map);
12089 levels = std::move(tria.levels);
12090 faces = std::move(tria.faces);
12091 vertices = std::move(tria.vertices);
12092 vertices_used = std::move(tria.vertices_used);
12093 manifolds = std::move(tria.manifolds);
12094 anisotropic_refinement = tria.anisotropic_refinement;
12095 number_cache = tria.number_cache;
12096 vertex_to_boundary_id_map_1d = std::move(tria.vertex_to_boundary_id_map_1d);
12097 vertex_to_manifold_id_map_1d = std::move(tria.vertex_to_manifold_id_map_1d);
12098
12100
12101 if (tria.policy)
12102 this->policy = tria.policy->clone();
12103
12104 return *this;
12105}
12106
12107
12108
12109template <int dim, int spacedim>
12112{
12113 // notify listeners that the triangulation is going down...
12114 try
12115 {
12116 signals.clear();
12117 }
12118 catch (...)
12119 {}
12120
12121 levels.clear();
12122
12123 // the vertex_to_boundary_id_map_1d field should be unused except in
12124 // 1d. double check this here, as destruction is a good place to
12125 // ensure that what we've done over the course of the lifetime of
12126 // this object makes sense
12127 AssertNothrow((dim == 1) || (vertex_to_boundary_id_map_1d == nullptr),
12129
12130 // the vertex_to_manifold_id_map_1d field should be also unused
12131 // except in 1d. check this as well
12132 AssertNothrow((dim == 1) || (vertex_to_manifold_id_map_1d == nullptr),
12134}
12135
12136
12137
12138template <int dim, int spacedim>
12141{
12142 // notify listeners that the triangulation is going down...
12143 signals.clear();
12144
12145 // ...and then actually clear all content of it
12146 clear_despite_subscriptions();
12147 periodic_face_pairs_level_0.clear();
12148 periodic_face_map.clear();
12149 reference_cells.clear();
12150
12151 cell_attached_data = {0, 0, {}, {}};
12152 data_serializer.clear();
12153}
12154
12155template <int dim, int spacedim>
12158{
12159 return MPI_COMM_SELF;
12160}
12161
12162
12163
12164template <int dim, int spacedim>
12167{
12168 return get_mpi_communicator();
12169}
12170
12171
12172
12173template <int dim, int spacedim>
12175std::weak_ptr<const Utilities::MPI::Partitioner> Triangulation<dim, spacedim>::
12177{
12178 return number_cache.active_cell_index_partitioner;
12179}
12180
12181
12182
12183template <int dim, int spacedim>
12185std::weak_ptr<const Utilities::MPI::Partitioner> Triangulation<dim, spacedim>::
12186 global_level_cell_index_partitioner(const unsigned int level) const
12187{
12188 AssertIndexRange(level, this->n_levels());
12189
12190 return number_cache.level_cell_index_partitioners[level];
12191}
12192
12193
12194
12195template <int dim, int spacedim>
12198 const MeshSmoothing mesh_smoothing)
12199{
12200 smooth_grid = mesh_smoothing;
12201}
12202
12203
12204
12205template <int dim, int spacedim>
12209{
12210 return smooth_grid;
12211}
12212
12213
12214
12215template <int dim, int spacedim>
12218 const types::manifold_id m_number,
12219 const Manifold<dim, spacedim> &manifold_object)
12220{
12222
12223 manifolds[m_number] = manifold_object.clone();
12224}
12225
12226
12227
12228template <int dim, int spacedim>
12231 const types::manifold_id m_number)
12232{
12234
12235 // delete the entry located at number.
12236 manifolds[m_number] =
12238 spacedim>()
12239 .clone();
12240}
12241
12242
12243template <int dim, int spacedim>
12246{
12247 for (auto &m : manifolds)
12248 m.second = internal::TriangulationImplementation::
12249 get_default_flat_manifold<dim, spacedim>()
12250 .clone();
12251}
12252
12253
12254template <int dim, int spacedim>
12257 const types::manifold_id m_number)
12258{
12259 Assert(
12260 n_cells() > 0,
12261 ExcMessage(
12262 "Error: set_all_manifold_ids() can not be called on an empty Triangulation."));
12263
12264 for (const auto &cell : this->active_cell_iterators())
12265 cell->set_all_manifold_ids(m_number);
12266}
12267
12268
12269template <int dim, int spacedim>
12272 const types::manifold_id m_number)
12273{
12274 Assert(
12275 n_cells() > 0,
12276 ExcMessage(
12277 "Error: set_all_manifold_ids_on_boundary() can not be called on an empty Triangulation."));
12278
12279 for (const auto &cell : this->active_cell_iterators())
12280 for (auto f : GeometryInfo<dim>::face_indices())
12281 if (cell->face(f)->at_boundary())
12282 cell->face(f)->set_all_manifold_ids(m_number);
12283}
12284
12285
12286template <int dim, int spacedim>
12289 const types::boundary_id b_id,
12290 const types::manifold_id m_number)
12291{
12292 Assert(
12293 n_cells() > 0,
12294 ExcMessage(
12295 "Error: set_all_manifold_ids_on_boundary() can not be called on an empty Triangulation."));
12296
12297 [[maybe_unused]] bool boundary_found = false;
12298
12299 for (const auto &cell : this->active_cell_iterators())
12300 {
12301 // loop on faces
12302 for (auto f : GeometryInfo<dim>::face_indices())
12303 if (cell->face(f)->at_boundary() &&
12304 cell->face(f)->boundary_id() == b_id)
12305 {
12306 boundary_found = true;
12307 cell->face(f)->set_manifold_id(m_number);
12308 }
12309
12310 // loop on edges if dim >= 3
12311 if (dim >= 3)
12312 for (unsigned int e = 0; e < GeometryInfo<dim>::lines_per_cell; ++e)
12313 if (cell->line(e)->at_boundary() &&
12314 cell->line(e)->boundary_id() == b_id)
12315 {
12316 boundary_found = true;
12317 cell->line(e)->set_manifold_id(m_number);
12318 }
12319 }
12320
12321 Assert(boundary_found, ExcBoundaryIdNotFound(b_id));
12322}
12323
12324
12325
12326template <int dim, int spacedim>
12329 const types::manifold_id m_number) const
12330{
12331 // check if flat manifold has been queried
12332 if (m_number == numbers::flat_manifold_id)
12333 return internal::TriangulationImplementation::
12334 get_default_flat_manifold<dim, spacedim>();
12335
12336 // look, if there is a manifold stored at
12337 // manifold_id number.
12338 const auto it = manifolds.find(m_number);
12339
12340 if (it != manifolds.end())
12341 {
12342 // if we have found an entry, return it
12343 return *(it->second);
12344 }
12345
12346 Assert(
12347 false,
12348 ExcMessage(
12349 "No manifold of the manifold id " + std::to_string(m_number) +
12350 " has been attached to the triangulation. "
12351 "Please attach the right manifold with Triangulation::set_manifold()."));
12352
12353 return internal::TriangulationImplementation::
12354 get_default_flat_manifold<dim, spacedim>(); // never reached
12355}
12356
12357
12358
12359template <int dim, int spacedim>
12361std::vector<types::boundary_id> Triangulation<dim, spacedim>::get_boundary_ids()
12362 const
12363{
12364 std::set<types::boundary_id> boundary_ids;
12365 for (const auto &cell : active_cell_iterators())
12366 if (cell->is_locally_owned())
12367 for (const auto &face : cell->face_indices())
12368 if (cell->at_boundary(face))
12369 boundary_ids.insert(cell->face(face)->boundary_id());
12370
12371 return {boundary_ids.begin(), boundary_ids.end()};
12372}
12373
12374
12375
12376template <int dim, int spacedim>
12378std::vector<types::manifold_id> Triangulation<dim, spacedim>::get_manifold_ids()
12379 const
12380{
12381 std::set<types::manifold_id> m_ids;
12382 for (const auto &cell : active_cell_iterators())
12383 if (cell->is_locally_owned())
12384 {
12385 m_ids.insert(cell->manifold_id());
12386 for (const auto &face : cell->face_iterators())
12387 m_ids.insert(face->manifold_id());
12388 if (dim == 3)
12389 {
12390 const auto line_indices = internal::TriaAccessorImplementation::
12391 Implementation::get_line_indices_of_cell(*cell);
12392 for (unsigned int l = 0; l < cell->n_lines(); ++l)
12393 {
12394 raw_line_iterator line(this, 0, line_indices[l]);
12395 m_ids.insert(line->manifold_id());
12396 }
12397 }
12398 }
12399 return {m_ids.begin(), m_ids.end()};
12400}
12401
12402#endif
12403/*-----------------------------------------------------------------*/
12404
12405#ifndef DOXYGEN
12406
12407template <int dim, int spacedim>
12410 const Triangulation<dim, spacedim> &other_tria)
12411{
12412 Assert((vertices.empty()) && (levels.empty()) && (faces == nullptr),
12413 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
12414 Assert((other_tria.levels.size() != 0) && (other_tria.vertices.size() != 0) &&
12415 (dim == 1 || other_tria.faces != nullptr),
12416 ExcMessage(
12417 "When calling Triangulation::copy_triangulation(), "
12418 "the target triangulation must be empty but the source "
12419 "triangulation (the argument to this function) must contain "
12420 "something. Here, it seems like the source does not "
12421 "contain anything at all."));
12422
12423
12424 // copy normal elements
12425 vertices = other_tria.vertices;
12426 vertices_used = other_tria.vertices_used;
12427 anisotropic_refinement = other_tria.anisotropic_refinement;
12428 smooth_grid = other_tria.smooth_grid;
12429 reference_cells = other_tria.reference_cells;
12430
12431 if (dim > 1)
12432 faces = std::make_unique<internal::TriangulationImplementation::TriaFaces>(
12433 *other_tria.faces);
12434
12435 for (const auto &p : other_tria.manifolds)
12436 set_manifold(p.first, *p.second);
12437
12438
12439 levels.reserve(other_tria.levels.size());
12440 for (const auto &level : other_tria.levels)
12441 levels.push_back(
12442 std::make_unique<internal::TriangulationImplementation::TriaLevel>(
12443 *level));
12444
12445 number_cache = other_tria.number_cache;
12446
12447 if (dim == 1)
12448 {
12449 vertex_to_boundary_id_map_1d =
12450 std::make_unique<std::map<unsigned int, types::boundary_id>>(
12451 *other_tria.vertex_to_boundary_id_map_1d);
12452
12453 vertex_to_manifold_id_map_1d =
12454 std::make_unique<std::map<unsigned int, types::manifold_id>>(
12455 *other_tria.vertex_to_manifold_id_map_1d);
12456 }
12457
12458 if (other_tria.policy)
12459 this->policy = other_tria.policy->clone();
12460
12461 // periodic faces
12462 this->periodic_face_pairs_level_0.reserve(
12463 other_tria.periodic_face_pairs_level_0.size());
12464
12465 for (const auto &other_entry : other_tria.periodic_face_pairs_level_0)
12466 {
12467 auto entry = other_entry;
12468 entry.cell[0] =
12469 cell_iterator(this, entry.cell[0]->level(), entry.cell[0]->index());
12470 entry.cell[1] =
12471 cell_iterator(this, entry.cell[1]->level(), entry.cell[1]->index());
12472 periodic_face_pairs_level_0.emplace_back(entry);
12473 }
12474
12475 for (auto [first_cell_, second_cell_and_orientation] :
12476 other_tria.periodic_face_map)
12477 {
12478 auto first_cell = first_cell_; // make copy since key is const
12479 first_cell.first = cell_iterator(this,
12480 first_cell.first->level(),
12481 first_cell.first->index());
12482 second_cell_and_orientation.first.first =
12483 cell_iterator(this,
12484 second_cell_and_orientation.first.first->level(),
12485 second_cell_and_orientation.first.first->index());
12486
12487 this->periodic_face_map[first_cell] = second_cell_and_orientation;
12488 }
12489
12490 // inform those who are listening on other_tria of the copy operation
12491 other_tria.signals.copy(*this);
12492 // also inform all listeners of the current triangulation that the
12493 // triangulation has been created
12494 signals.create();
12495
12496 // note that we need not copy the
12497 // subscriptor!
12498}
12499
12500
12501
12502template <int dim, int spacedim>
12505{
12506 this->update_reference_cells();
12507
12508 if (this->all_reference_cells_are_hyper_cube())
12509 {
12510 this->policy =
12512 dim,
12513 spacedim,
12515 }
12516 else
12517 {
12518 this->policy =
12520 dim,
12521 spacedim,
12523 }
12524}
12525
12526
12527
12528template <int dim, int spacedim>
12531 const std::vector<Point<spacedim>> &v,
12532 const std::vector<CellData<dim>> &cells,
12533 const SubCellData &subcelldata)
12534{
12535 Assert((vertices.empty()) && (levels.empty()) && (faces == nullptr),
12536 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
12537 // check that no forbidden arrays
12538 // are used
12539 Assert(subcelldata.check_consistency(dim), ExcInternalError());
12540
12541 // try to create a triangulation; if this fails, we still want to
12542 // throw an exception but if we just do so we'll get into trouble
12543 // because sometimes other objects are already attached to it:
12544 try
12545 {
12547 create_triangulation(v, cells, subcelldata, *this);
12548 }
12549 catch (...)
12550 {
12551 clear_despite_subscriptions();
12552 throw;
12553 }
12554
12555 reset_policy();
12556
12557 // update our counts of the various elements of a triangulation, and set
12558 // active_cell_indices of all cells
12559 reset_cell_vertex_indices_cache();
12561 *this, levels.size(), number_cache);
12562 reset_active_cell_indices();
12563 reset_global_cell_indices();
12564
12565 // now verify that there are indeed no distorted cells. as per the
12566 // documentation of this class, we first collect all distorted cells
12567 // and then throw an exception if there are any
12568 if (check_for_distorted_cells)
12569 {
12570 DistortedCellList distorted_cells = collect_distorted_coarse_cells(*this);
12571 // throw the array (and fill the various location fields) if
12572 // there are distorted cells. otherwise, just fall off the end
12573 // of the function
12574 AssertThrow(distorted_cells.distorted_cells.empty(), distorted_cells);
12575 }
12576
12577
12578 /*
12579 When the triangulation is a manifold (dim < spacedim) and made of
12580 quadrilaterals, the normal field provided from the map class depends on
12581 the order of the vertices. It may happen that this normal field is
12582 discontinuous. The following code takes care that this is not the case by
12583 setting the cell direction flag on those cell that produce the wrong
12584 orientation.
12585
12586 To determine if 2 neighbors have the same or opposite orientation we use
12587 a truth table. Its entries are indexed by the local indices of the
12588 common face. For example if two elements share a face, and this face is
12589 face 0 for element 0 and face 1 for element 1, then table(0,1) will tell
12590 whether the orientation are the same (true) or opposite (false).
12591
12592 Even though there may be a combinatorial/graph theory argument to get this
12593 table in any dimension, I tested by hand all the different possible cases
12594 in 1D and 2D to generate the table.
12595
12596 Assuming that a surface respects the standard orientation for 2d meshes,
12597 the truth tables are symmetric and their true values are the following
12598
12599 - 1D curves: (0,1)
12600 - 2D surface: (0,1),(0,2),(1,3),(2,3)
12601
12602 We store this data using an n_faces x n_faces full matrix, which is
12603 actually much bigger than the minimal data required, but it makes the code
12604 more readable.
12605
12606 */
12607 if ((dim == spacedim - 1) && all_reference_cells_are_hyper_cube())
12608 {
12611 switch (dim)
12612 {
12613 case 1:
12614 {
12615 const bool values[][2] = {{false, true}, {true, false}};
12616 for (const unsigned int i : GeometryInfo<dim>::face_indices())
12617 for (const unsigned int j : GeometryInfo<dim>::face_indices())
12618 correct(i, j) = values[i][j];
12619 break;
12620 }
12621 case 2:
12622 {
12623 const bool values[][4] = {{false, true, true, false},
12624 {true, false, false, true},
12625 {true, false, false, true},
12626 {false, true, true, false}};
12627 for (const unsigned int i : GeometryInfo<dim>::face_indices())
12628 for (const unsigned int j : GeometryInfo<dim>::face_indices())
12629 correct(i, j) = (values[i][j]);
12630 break;
12631 }
12632 default:
12634 }
12635
12636
12637 std::list<active_cell_iterator> this_round, next_round;
12638 active_cell_iterator neighbor;
12639
12640 // Start with the first cell and (arbitrarily) decide that its
12641 // direction flag should be 'true':
12642 this_round.push_back(begin_active());
12643 begin_active()->set_direction_flag(true);
12644 begin_active()->set_user_flag();
12645
12646 while (this_round.size() > 0)
12647 {
12648 for (const auto &cell : this_round)
12649 {
12650 for (const unsigned int i : cell->face_indices())
12651 {
12652 if (cell->face(i)->at_boundary() == false)
12653 {
12654 // Consider the i'th neighbor of a cell for
12655 // which we have already set the direction:
12656 neighbor = cell->neighbor(i);
12657
12658 const unsigned int nb_of_nb =
12659 cell->neighbor_of_neighbor(i);
12660
12661 // If we already saw this neighboring cell,
12662 // check that everything is fine:
12663 if (neighbor->user_flag_set())
12664 {
12665 Assert(
12666 !(correct(i, nb_of_nb) ^
12667 (neighbor->direction_flag() ==
12668 cell->direction_flag())),
12669 ExcMessage(
12670 "The triangulation you are trying to create is not orientable."));
12671 }
12672 else
12673 {
12674 // We had not seen this cell yet. Set its
12675 // orientation flag (if necessary), mark it
12676 // as treated via the user flag, and push it
12677 // onto the list of cells to start work from
12678 // the next time around:
12679 if (correct(i, nb_of_nb) ^
12680 (neighbor->direction_flag() ==
12681 cell->direction_flag()))
12682 neighbor->set_direction_flag(
12683 !neighbor->direction_flag());
12684 neighbor->set_user_flag();
12685 next_round.push_back(neighbor);
12686 }
12687 }
12688 }
12689 }
12690
12691 // Before we quit let's check that if the triangulation is
12692 // disconnected that we still get all cells by starting
12693 // again from the first cell we haven't treated yet -- that
12694 // is, the first cell of the next disconnected component we
12695 // had not yet touched.
12696 if (next_round.empty())
12697 for (const auto &cell : this->active_cell_iterators())
12698 if (cell->user_flag_set() == false)
12699 {
12700 next_round.push_back(cell);
12701 cell->set_direction_flag(true);
12702 cell->set_user_flag();
12703 break;
12704 }
12705
12706 // Go on to the next round:
12707 next_round.swap(this_round);
12708 next_round.clear();
12709 }
12710 clear_user_flags();
12711 }
12712
12713 this->update_cell_relations();
12714
12715 // inform all listeners that the triangulation has been created
12716 signals.create();
12717}
12718
12719
12720
12721template <int dim, int spacedim>
12725{
12726 // 1) create coarse grid
12728 construction_data.coarse_cells,
12729 SubCellData());
12730
12731 // create a copy of cell_infos such that we can sort them
12732 auto cell_infos = construction_data.cell_infos;
12733
12734 // sort cell_infos on each level separately
12735 for (auto &cell_info : cell_infos)
12736 std::sort(
12737 cell_info.begin(),
12738 cell_info.end(),
12741 const CellId a_id(a.id);
12742 const CellId b_id(b.id);
12743
12744 const auto a_coarse_cell_index =
12745 this->coarse_cell_id_to_coarse_cell_index(a_id.get_coarse_cell_id());
12746 const auto b_coarse_cell_index =
12747 this->coarse_cell_id_to_coarse_cell_index(b_id.get_coarse_cell_id());
12748
12749 // according to their coarse-cell index and if that is
12750 // same according to their cell id (the result is that
12751 // cells on each level are sorted according to their
12752 // index on that level - what we need in the following
12753 // operations)
12754 if (a_coarse_cell_index != b_coarse_cell_index)
12755 return a_coarse_cell_index < b_coarse_cell_index;
12756 else
12757 return a_id < b_id;
12758 });
12759
12760 // 2) create all levels via a sequence of refinements. note that
12761 // we must make sure that we actually have cells on this level,
12762 // which is not clear in a parallel context for some processes
12763 for (unsigned int level = 0;
12764 level < cell_infos.size() && !cell_infos[level].empty();
12765 ++level)
12766 {
12767 // a) set manifold ids here (because new vertices have to be
12768 // positioned correctly during each refinement step)
12769 {
12770 auto cell = this->begin(level);
12771 auto cell_info = cell_infos[level].begin();
12772 for (; cell_info != cell_infos[level].end(); ++cell_info)
12773 {
12774 while (cell_info->id != cell->id().template to_binary<dim>())
12775 ++cell;
12776 if (dim == 2)
12777 for (const auto face : cell->face_indices())
12778 cell->face(face)->set_manifold_id(
12779 cell_info->manifold_line_ids[face]);
12780 else if (dim == 3)
12781 {
12782 for (const auto face : cell->face_indices())
12783 cell->face(face)->set_manifold_id(
12784 cell_info->manifold_quad_ids[face]);
12785
12786 const auto line_indices = internal::TriaAccessorImplementation::
12787 Implementation::get_line_indices_of_cell(*cell);
12788 for (unsigned int l = 0; l < cell->n_lines(); ++l)
12789 {
12790 raw_line_iterator line(this, 0, line_indices[l]);
12791 line->set_manifold_id(cell_info->manifold_line_ids[l]);
12792 }
12793 }
12794
12795 cell->set_manifold_id(cell_info->manifold_id);
12796 }
12797 }
12798
12799 // b) perform refinement on all levels but on the finest
12800 if (level + 1 != cell_infos.size())
12801 {
12802 // find cells that should have children and mark them for
12803 // refinement
12804 auto coarse_cell = this->begin(level);
12805 auto fine_cell_info = cell_infos[level + 1].begin();
12806
12807 // loop over all cells on the next level
12808 for (; fine_cell_info != cell_infos[level + 1].end();
12809 ++fine_cell_info)
12810 {
12811 // find the parent of that cell
12812 while (
12813 !coarse_cell->id().is_parent_of(CellId(fine_cell_info->id)))
12814 ++coarse_cell;
12815
12816 // set parent for refinement
12817 coarse_cell->set_refine_flag();
12818 }
12819
12820 // execute refinement
12821 ::Triangulation<dim,
12822 spacedim>::execute_coarsening_and_refinement();
12823 }
12824 }
12825
12826 // 3) set boundary ids
12827 for (unsigned int level = 0;
12828 level < cell_infos.size() && !cell_infos[level].empty();
12829 ++level)
12830 {
12831 auto cell = this->begin(level);
12832 auto cell_info = cell_infos[level].begin();
12833 for (; cell_info != cell_infos[level].end(); ++cell_info)
12834 {
12835 // find cell that has the correct cell
12836 while (cell_info->id != cell->id().template to_binary<dim>())
12837 ++cell;
12838
12839 // boundary ids
12840 for (auto pair : cell_info->boundary_ids)
12841 if (cell->face(pair.first)->at_boundary())
12842 cell->face(pair.first)->set_boundary_id(pair.second);
12843 }
12844 }
12845
12846 // inform all listeners that the triangulation has been created
12847 signals.create();
12848}
12849
12850
12851template <int dim, int spacedim>
12854{
12855 AssertThrow(dim + 1 == spacedim,
12856 ExcMessage(
12857 "This function can only be called if dim == spacedim-1."));
12858 for (const auto &cell : this->active_cell_iterators())
12859 cell->set_direction_flag(!cell->direction_flag());
12860}
12861
12862
12863
12864template <int dim, int spacedim>
12867{
12868 Assert(n_cells() > 0,
12869 ExcMessage("Error: An empty Triangulation can not be refined."));
12870
12871 for (const auto &cell : this->active_cell_iterators())
12872 {
12873 cell->clear_coarsen_flag();
12874 cell->set_refine_flag();
12875 cell->set_refine_choice();
12876 }
12877}
12878
12879
12880
12881template <int dim, int spacedim>
12883void Triangulation<dim, spacedim>::refine_global(const unsigned int times)
12884{
12885 Assert(n_cells() > 0,
12886 ExcMessage("Error: An empty Triangulation can not be refined."));
12887
12888 for (unsigned int i = 0; i < times; ++i)
12889 {
12890 set_all_refine_flags();
12891 execute_coarsening_and_refinement();
12892 }
12893}
12894
12895
12896
12897template <int dim, int spacedim>
12899void Triangulation<dim, spacedim>::coarsen_global(const unsigned int times)
12900{
12901 for (unsigned int i = 0; i < times; ++i)
12902 {
12903 for (const auto &cell : this->active_cell_iterators())
12904 {
12905 cell->clear_refine_flag();
12906 cell->set_coarsen_flag();
12907 }
12908 execute_coarsening_and_refinement();
12909 }
12910}
12911
12912
12913#endif
12914/*-------------------- refine/coarsen flags -------------------------*/
12915
12916#ifndef DOXYGEN
12917
12918template <int dim, int spacedim>
12920void Triangulation<dim, spacedim>::save_refine_flags(std::vector<bool> &v) const
12921{
12922 v.resize(dim * n_active_cells(), false);
12923 std::vector<bool>::iterator i = v.begin();
12924
12925 for (const auto &cell : this->active_cell_iterators())
12926 for (unsigned int j = 0; j < dim; ++j, ++i)
12927 if (cell->refine_flag_set() & (1 << j))
12928 *i = true;
12929
12930 Assert(i == v.end(), ExcInternalError());
12931}
12932
12933
12934
12935template <int dim, int spacedim>
12937void Triangulation<dim, spacedim>::save_refine_flags(std::ostream &out) const
12938{
12939 std::vector<bool> v;
12940 save_refine_flags(v);
12941 write_bool_vector(mn_tria_refine_flags_begin,
12942 v,
12944 out);
12945}
12946
12947
12948
12949template <int dim, int spacedim>
12952{
12953 std::vector<bool> v;
12954 read_bool_vector(mn_tria_refine_flags_begin, v, mn_tria_refine_flags_end, in);
12955 load_refine_flags(v);
12956}
12957
12958
12959
12960template <int dim, int spacedim>
12962void Triangulation<dim, spacedim>::load_refine_flags(const std::vector<bool> &v)
12963{
12964 AssertThrow(v.size() == dim * n_active_cells(), ExcGridReadError());
12965
12966 std::vector<bool>::const_iterator i = v.begin();
12967 for (const auto &cell : this->active_cell_iterators())
12968 {
12969 unsigned int ref_case = 0;
12970
12971 for (unsigned int j = 0; j < dim; ++j, ++i)
12972 if (*i == true)
12973 ref_case += 1 << j;
12975 ExcGridReadError());
12976 if (ref_case > 0)
12977 cell->set_refine_flag(RefinementCase<dim>(ref_case));
12978 else
12979 cell->clear_refine_flag();
12980 }
12981
12982 Assert(i == v.end(), ExcInternalError());
12983}
12984
12985
12986
12987template <int dim, int spacedim>
12990 std::vector<bool> &v) const
12991{
12992 v.resize(n_active_cells(), false);
12993 std::vector<bool>::iterator i = v.begin();
12994 for (const auto &cell : this->active_cell_iterators())
12995 {
12996 *i = cell->coarsen_flag_set();
12997 ++i;
12998 }
12999
13000 Assert(i == v.end(), ExcInternalError());
13001}
13002
13003
13004
13005template <int dim, int spacedim>
13007void Triangulation<dim, spacedim>::save_coarsen_flags(std::ostream &out) const
13008{
13009 std::vector<bool> v;
13010 save_coarsen_flags(v);
13011 write_bool_vector(mn_tria_coarsen_flags_begin,
13012 v,
13014 out);
13015}
13016
13017
13018
13019template <int dim, int spacedim>
13022{
13023 std::vector<bool> v;
13024 read_bool_vector(mn_tria_coarsen_flags_begin,
13025 v,
13027 in);
13028 load_coarsen_flags(v);
13029}
13030
13031
13032
13033template <int dim, int spacedim>
13036 const std::vector<bool> &v)
13037{
13038 Assert(v.size() == n_active_cells(), ExcGridReadError());
13039
13040 std::vector<bool>::const_iterator i = v.begin();
13041 for (const auto &cell : this->active_cell_iterators())
13042 {
13043 if (*i == true)
13044 cell->set_coarsen_flag();
13045 else
13046 cell->clear_coarsen_flag();
13047 ++i;
13048 }
13049
13050 Assert(i == v.end(), ExcInternalError());
13051}
13052
13053
13054template <int dim, int spacedim>
13057{
13058 return anisotropic_refinement;
13059}
13060
13061
13062#endif
13063
13064namespace internal
13065{
13066 namespace
13067 {
13068 std::vector<std::vector<bool>>
13069 extract_raw_coarsen_flags(
13070 const std::vector<std::unique_ptr<
13072 {
13073 std::vector<std::vector<bool>> coarsen_flags(levels.size());
13074 for (unsigned int level = 0; level < levels.size(); ++level)
13075 coarsen_flags[level] = levels[level]->coarsen_flags;
13076 return coarsen_flags;
13077 }
13078
13079 std::vector<std::vector<std::uint8_t>>
13080 extract_raw_refine_flags(
13081 const std::vector<std::unique_ptr<
13083 {
13084 std::vector<std::vector<std::uint8_t>> refine_flags(levels.size());
13085 for (unsigned int level = 0; level < levels.size(); ++level)
13086 refine_flags[level] = levels[level]->refine_flags;
13087 return refine_flags;
13088 }
13089 } // namespace
13090} // namespace internal
13091
13092
13093/*-------------------- user data/flags -------------------------*/
13094
13095
13096namespace
13097{
13098 // clear user data of cells
13099 void
13100 clear_user_data(std::vector<std::unique_ptr<
13102 {
13103 for (auto &level : levels)
13104 level->cells.clear_user_data();
13105 }
13106
13107
13108 // clear user data of faces
13109 void
13111 {
13112 if (faces->dim == 2)
13113 {
13114 faces->lines.clear_user_data();
13115 }
13116
13117
13118 if (faces->dim == 3)
13119 {
13120 faces->lines.clear_user_data();
13121 faces->quads.clear_user_data();
13122 }
13123 }
13124} // namespace
13125
13126#ifndef DOXYGEN
13127
13128template <int dim, int spacedim>
13131{
13132 // let functions in anonymous namespace do their work
13133 ::clear_user_data(levels);
13134 if (dim > 1)
13135 ::clear_user_data(faces.get());
13136}
13137
13138
13139
13140namespace
13141{
13142 void
13143 clear_user_flags_line(
13144 unsigned int dim,
13145 std::vector<
13146 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
13147 &levels,
13149 {
13150 if (dim == 1)
13151 {
13152 for (const auto &level : levels)
13153 level->cells.clear_user_flags();
13154 }
13155 else if (dim == 2 || dim == 3)
13156 {
13157 faces->lines.clear_user_flags();
13158 }
13159 else
13160 {
13162 }
13163 }
13164} // namespace
13165
13166
13167template <int dim, int spacedim>
13170{
13171 ::clear_user_flags_line(dim, levels, faces.get());
13172}
13173
13174
13175
13176namespace
13177{
13178 void
13179 clear_user_flags_quad(
13180 unsigned int dim,
13181 std::vector<
13182 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
13183 &levels,
13185 {
13186 if (dim == 1)
13187 {
13188 // nothing to do in 1d
13189 }
13190 else if (dim == 2)
13191 {
13192 for (const auto &level : levels)
13193 level->cells.clear_user_flags();
13194 }
13195 else if (dim == 3)
13196 {
13197 faces->quads.clear_user_flags();
13198 }
13199 else
13200 {
13202 }
13203 }
13204} // namespace
13205
13206
13207template <int dim, int spacedim>
13210{
13211 ::clear_user_flags_quad(dim, levels, faces.get());
13212}
13213
13214
13215
13216namespace
13217{
13218 void
13219 clear_user_flags_hex(
13220 unsigned int dim,
13221 std::vector<
13222 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
13223 &levels,
13225 {
13226 if (dim == 1)
13227 {
13228 // nothing to do in 1d
13229 }
13230 else if (dim == 2)
13231 {
13232 // nothing to do in 2d
13233 }
13234 else if (dim == 3)
13235 {
13236 for (const auto &level : levels)
13237 level->cells.clear_user_flags();
13238 }
13239 else
13240 {
13242 }
13243 }
13244} // namespace
13245
13246
13247template <int dim, int spacedim>
13250{
13251 ::clear_user_flags_hex(dim, levels, faces.get());
13252}
13253
13254
13255
13256template <int dim, int spacedim>
13259{
13260 clear_user_flags_line();
13261 clear_user_flags_quad();
13262 clear_user_flags_hex();
13263}
13264
13265
13266
13267template <int dim, int spacedim>
13269void Triangulation<dim, spacedim>::save_user_flags(std::ostream &out) const
13270{
13271 save_user_flags_line(out);
13272
13273 if (dim >= 2)
13274 save_user_flags_quad(out);
13275
13276 if (dim >= 3)
13277 save_user_flags_hex(out);
13278
13279 if (dim >= 4)
13281}
13282
13283
13284
13285template <int dim, int spacedim>
13287void Triangulation<dim, spacedim>::save_user_flags(std::vector<bool> &v) const
13288{
13289 // clear vector and append
13290 // all the stuff later on
13291 v.clear();
13292
13293 std::vector<bool> tmp;
13294
13295 save_user_flags_line(tmp);
13296 v.insert(v.end(), tmp.begin(), tmp.end());
13297
13298 if (dim >= 2)
13299 {
13300 save_user_flags_quad(tmp);
13301 v.insert(v.end(), tmp.begin(), tmp.end());
13302 }
13303
13304 if (dim >= 3)
13305 {
13306 save_user_flags_hex(tmp);
13307 v.insert(v.end(), tmp.begin(), tmp.end());
13308 }
13309
13310 if (dim >= 4)
13312}
13313
13314
13315
13316template <int dim, int spacedim>
13319{
13320 load_user_flags_line(in);
13321
13322 if (dim >= 2)
13323 load_user_flags_quad(in);
13324
13325 if (dim >= 3)
13326 load_user_flags_hex(in);
13327
13328 if (dim >= 4)
13330}
13331
13332
13333
13334template <int dim, int spacedim>
13336void Triangulation<dim, spacedim>::load_user_flags(const std::vector<bool> &v)
13337{
13338 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
13339 std::vector<bool> tmp;
13340
13341 // first extract the flags
13342 // belonging to lines
13343 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
13344 // and set the lines
13345 load_user_flags_line(tmp);
13346
13347 if (dim >= 2)
13348 {
13349 tmp.clear();
13350 tmp.insert(tmp.end(),
13351 v.begin() + n_lines(),
13352 v.begin() + n_lines() + n_quads());
13353 load_user_flags_quad(tmp);
13354 }
13355
13356 if (dim >= 3)
13357 {
13358 tmp.clear();
13359 tmp.insert(tmp.end(),
13360 v.begin() + n_lines() + n_quads(),
13361 v.begin() + n_lines() + n_quads() + n_hexs());
13362 load_user_flags_hex(tmp);
13363 }
13364
13365 if (dim >= 4)
13367}
13368
13369
13370
13371template <int dim, int spacedim>
13374 std::vector<bool> &v) const
13375{
13376 v.resize(n_lines(), false);
13377 std::vector<bool>::iterator i = v.begin();
13378 line_iterator line = begin_line(), endl = end_line();
13379 for (; line != endl; ++line, ++i)
13380 *i = line->user_flag_set();
13381
13382 Assert(i == v.end(), ExcInternalError());
13383}
13384
13385
13386
13387template <int dim, int spacedim>
13389void Triangulation<dim, spacedim>::save_user_flags_line(std::ostream &out) const
13390{
13391 std::vector<bool> v;
13392 save_user_flags_line(v);
13393 write_bool_vector(mn_tria_line_user_flags_begin,
13394 v,
13396 out);
13397}
13398
13399
13400
13401template <int dim, int spacedim>
13404{
13405 std::vector<bool> v;
13406 read_bool_vector(mn_tria_line_user_flags_begin,
13407 v,
13409 in);
13410 load_user_flags_line(v);
13411}
13412
13413
13414
13415template <int dim, int spacedim>
13418 const std::vector<bool> &v)
13419{
13420 Assert(v.size() == n_lines(), ExcGridReadError());
13421
13422 line_iterator line = begin_line(), endl = end_line();
13423 std::vector<bool>::const_iterator i = v.begin();
13424 for (; line != endl; ++line, ++i)
13425 if (*i == true)
13426 line->set_user_flag();
13427 else
13428 line->clear_user_flag();
13429
13430 Assert(i == v.end(), ExcInternalError());
13431}
13432
13433#endif
13434
13435namespace
13436{
13437 template <typename Iterator>
13438 bool
13439 get_user_flag(const Iterator &i)
13440 {
13441 return i->user_flag_set();
13442 }
13443
13444
13445
13446 template <int structdim, int dim, int spacedim>
13447 bool
13449 {
13451 return false;
13452 }
13453
13454
13455
13456 template <typename Iterator>
13457 void
13458 set_user_flag(const Iterator &i)
13459 {
13460 i->set_user_flag();
13461 }
13462
13463
13464
13465 template <int structdim, int dim, int spacedim>
13466 void
13468 {
13470 }
13471
13472
13473
13474 template <typename Iterator>
13475 void
13476 clear_user_flag(const Iterator &i)
13477 {
13478 i->clear_user_flag();
13479 }
13480
13481
13482
13483 template <int structdim, int dim, int spacedim>
13484 void
13485 clear_user_flag(
13487 {
13489 }
13490} // namespace
13491
13492#ifndef DOXYGEN
13493
13494template <int dim, int spacedim>
13497 std::vector<bool> &v) const
13498{
13499 v.resize(n_quads(), false);
13500
13501 if (dim >= 2)
13502 {
13503 std::vector<bool>::iterator i = v.begin();
13504 quad_iterator quad = begin_quad(), endq = end_quad();
13505 for (; quad != endq; ++quad, ++i)
13506 *i = get_user_flag(quad);
13507
13508 Assert(i == v.end(), ExcInternalError());
13509 }
13510}
13511
13512
13513
13514template <int dim, int spacedim>
13516void Triangulation<dim, spacedim>::save_user_flags_quad(std::ostream &out) const
13517{
13518 std::vector<bool> v;
13519 save_user_flags_quad(v);
13520 write_bool_vector(mn_tria_quad_user_flags_begin,
13521 v,
13523 out);
13524}
13525
13526
13527
13528template <int dim, int spacedim>
13531{
13532 std::vector<bool> v;
13533 read_bool_vector(mn_tria_quad_user_flags_begin,
13534 v,
13536 in);
13537 load_user_flags_quad(v);
13538}
13539
13540
13541
13542template <int dim, int spacedim>
13545 const std::vector<bool> &v)
13546{
13547 Assert(v.size() == n_quads(), ExcGridReadError());
13548
13549 if (dim >= 2)
13550 {
13551 quad_iterator quad = begin_quad(), endq = end_quad();
13552 std::vector<bool>::const_iterator i = v.begin();
13553 for (; quad != endq; ++quad, ++i)
13554 if (*i == true)
13555 set_user_flag(quad);
13556 else
13557 clear_user_flag(quad);
13558
13559 Assert(i == v.end(), ExcInternalError());
13560 }
13561}
13562
13563
13564
13565template <int dim, int spacedim>
13568 std::vector<bool> &v) const
13569{
13570 v.resize(n_hexs(), false);
13571
13572 if (dim >= 3)
13573 {
13574 std::vector<bool>::iterator i = v.begin();
13575 hex_iterator hex = begin_hex(), endh = end_hex();
13576 for (; hex != endh; ++hex, ++i)
13577 *i = get_user_flag(hex);
13578
13579 Assert(i == v.end(), ExcInternalError());
13580 }
13581}
13582
13583
13584
13585template <int dim, int spacedim>
13587void Triangulation<dim, spacedim>::save_user_flags_hex(std::ostream &out) const
13588{
13589 std::vector<bool> v;
13590 save_user_flags_hex(v);
13591 write_bool_vector(mn_tria_hex_user_flags_begin,
13592 v,
13594 out);
13595}
13596
13597
13598
13599template <int dim, int spacedim>
13602{
13603 std::vector<bool> v;
13604 read_bool_vector(mn_tria_hex_user_flags_begin,
13605 v,
13607 in);
13608 load_user_flags_hex(v);
13609}
13610
13611
13612
13613template <int dim, int spacedim>
13616 const std::vector<bool> &v)
13617{
13618 Assert(v.size() == n_hexs(), ExcGridReadError());
13619
13620 if (dim >= 3)
13621 {
13622 hex_iterator hex = begin_hex(), endh = end_hex();
13623 std::vector<bool>::const_iterator i = v.begin();
13624 for (; hex != endh; ++hex, ++i)
13625 if (*i == true)
13626 set_user_flag(hex);
13627 else
13628 clear_user_flag(hex);
13629
13630 Assert(i == v.end(), ExcInternalError());
13631 }
13632}
13633
13634
13635
13636template <int dim, int spacedim>
13639 std::vector<unsigned int> &v) const
13640{
13641 // clear vector and append all the
13642 // stuff later on
13643 v.clear();
13644
13645 std::vector<unsigned int> tmp;
13646
13647 save_user_indices_line(tmp);
13648 v.insert(v.end(), tmp.begin(), tmp.end());
13649
13650 if (dim >= 2)
13651 {
13652 save_user_indices_quad(tmp);
13653 v.insert(v.end(), tmp.begin(), tmp.end());
13654 }
13655
13656 if (dim >= 3)
13657 {
13658 save_user_indices_hex(tmp);
13659 v.insert(v.end(), tmp.begin(), tmp.end());
13660 }
13661
13662 if (dim >= 4)
13664}
13665
13666
13667
13668template <int dim, int spacedim>
13671 const std::vector<unsigned int> &v)
13672{
13673 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
13674 std::vector<unsigned int> tmp;
13675
13676 // first extract the indices
13677 // belonging to lines
13678 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
13679 // and set the lines
13680 load_user_indices_line(tmp);
13681
13682 if (dim >= 2)
13683 {
13684 tmp.clear();
13685 tmp.insert(tmp.end(),
13686 v.begin() + n_lines(),
13687 v.begin() + n_lines() + n_quads());
13688 load_user_indices_quad(tmp);
13689 }
13690
13691 if (dim >= 3)
13692 {
13693 tmp.clear();
13694 tmp.insert(tmp.end(),
13695 v.begin() + n_lines() + n_quads(),
13696 v.begin() + n_lines() + n_quads() + n_hexs());
13697 load_user_indices_hex(tmp);
13698 }
13699
13700 if (dim >= 4)
13702}
13703
13704
13705
13706template <int dim, int spacedim>
13708void Triangulation<dim, spacedim>::save(const std::string &file_basename) const
13709{
13710 // Save triangulation information.
13711 {
13712 std::ofstream ofs_tria(file_basename + "_triangulation.data");
13713 AssertThrow(ofs_tria.fail() == false, ExcIO());
13714
13715 boost::archive::text_oarchive oa(ofs_tria, boost::archive::no_header);
13716 save(oa,
13718 }
13719
13720 // Save attached data.
13721 {
13722 std::ofstream ofs_info(file_basename + ".info");
13723 ofs_info
13724 << "version nproc n_attached_fixed_size_objs n_attached_variable_size_objs n_active_cells"
13725 << std::endl
13727 << " " << 1 << " " << this->cell_attached_data.pack_callbacks_fixed.size()
13728 << " " << this->cell_attached_data.pack_callbacks_variable.size() << " "
13729 << this->n_global_active_cells() << std::endl;
13730 }
13731
13732 this->save_attached_data(0, this->n_global_active_cells(), file_basename);
13733}
13734
13735
13736
13737template <int dim, int spacedim>
13739void Triangulation<dim, spacedim>::load(const std::string &file_basename)
13740{
13741 // It's probably prudent to first get rid of any all content of the
13742 // triangulation, rather than hope that the deserialization below
13743 // overwrites everything:
13744 clear();
13745
13746 // Load triangulation information.
13747 {
13748 std::ifstream ifs_tria(file_basename + "_triangulation.data");
13749 AssertThrow(ifs_tria.fail() == false, ExcIO());
13750
13751 boost::archive::text_iarchive ia(ifs_tria, boost::archive::no_header);
13752 load(ia,
13754 }
13755
13756 // Load attached data.
13757 unsigned int version, numcpus, attached_count_fixed, attached_count_variable,
13758 n_global_active_cells;
13759 {
13760 std::ifstream ifs_info(std::string(file_basename) + ".info");
13761 AssertThrow(ifs_info.fail() == false, ExcIO());
13762 std::string firstline;
13763 std::getline(ifs_info, firstline);
13764 ifs_info >> version >> numcpus >> attached_count_fixed >>
13765 attached_count_variable >> n_global_active_cells;
13766 }
13767
13768 AssertThrow(numcpus == 1,
13769 ExcMessage("Incompatible number of CPUs found in .info file."));
13770
13771 const auto expected_version =
13773 spacedim>::version_number;
13774 AssertThrow(version == expected_version,
13775 ExcMessage(
13776 "The information saved in the file you are trying "
13777 "to read the triangulation from was written with an "
13778 "incompatible file format version and cannot be read."));
13779 Assert(this->n_global_active_cells() == n_global_active_cells,
13780 ExcMessage("The number of cells of the triangulation differs "
13781 "from the number of cells written into the .info file."));
13782
13783 // Clear all of the callback data, as explained in the documentation of
13784 // register_data_attach().
13785 this->cell_attached_data.n_attached_data_sets = 0;
13786 this->cell_attached_data.n_attached_deserialize =
13787 attached_count_fixed + attached_count_variable;
13788
13789 this->load_attached_data(0,
13790 this->n_global_active_cells(),
13791 this->n_active_cells(),
13792 file_basename,
13793 attached_count_fixed,
13794 attached_count_variable);
13795
13796 this->update_cell_relations();
13797}
13798
13799#endif
13800namespace
13801{
13802 template <typename Iterator>
13803 unsigned int
13804 get_user_index(const Iterator &i)
13805 {
13806 return i->user_index();
13807 }
13808
13809
13810
13811 template <int structdim, int dim, int spacedim>
13812 unsigned int
13813 get_user_index(
13815 {
13818 }
13819
13820
13821
13822 template <typename Iterator>
13823 void
13824 set_user_index(const Iterator &i, const unsigned int x)
13825 {
13826 i->set_user_index(x);
13827 }
13828
13829
13830
13831 template <int structdim, int dim, int spacedim>
13832 void
13833 set_user_index(
13835 const unsigned int)
13836 {
13838 }
13839} // namespace
13840
13841#ifndef DOXYGEN
13842
13843template <int dim, int spacedim>
13846 std::vector<unsigned int> &v) const
13847{
13848 v.resize(n_lines(), 0);
13849 std::vector<unsigned int>::iterator i = v.begin();
13850 line_iterator line = begin_line(), endl = end_line();
13851 for (; line != endl; ++line, ++i)
13852 *i = line->user_index();
13853}
13854
13855
13856
13857template <int dim, int spacedim>
13860 const std::vector<unsigned int> &v)
13861{
13862 Assert(v.size() == n_lines(), ExcGridReadError());
13863
13864 line_iterator line = begin_line(), endl = end_line();
13865 std::vector<unsigned int>::const_iterator i = v.begin();
13866 for (; line != endl; ++line, ++i)
13867 line->set_user_index(*i);
13868}
13869
13870
13871template <int dim, int spacedim>
13874 std::vector<unsigned int> &v) const
13875{
13876 v.resize(n_quads(), 0);
13877
13878 if (dim >= 2)
13879 {
13880 std::vector<unsigned int>::iterator i = v.begin();
13881 quad_iterator quad = begin_quad(), endq = end_quad();
13882 for (; quad != endq; ++quad, ++i)
13883 *i = get_user_index(quad);
13884 }
13885}
13886
13887
13888
13889template <int dim, int spacedim>
13892 const std::vector<unsigned int> &v)
13893{
13894 Assert(v.size() == n_quads(), ExcGridReadError());
13895
13896 if (dim >= 2)
13897 {
13898 quad_iterator quad = begin_quad(), endq = end_quad();
13899 std::vector<unsigned int>::const_iterator i = v.begin();
13900 for (; quad != endq; ++quad, ++i)
13901 set_user_index(quad, *i);
13902 }
13903}
13904
13905
13906template <int dim, int spacedim>
13909 std::vector<unsigned int> &v) const
13910{
13911 v.resize(n_hexs(), 0);
13912
13913 if (dim >= 3)
13914 {
13915 std::vector<unsigned int>::iterator i = v.begin();
13916 hex_iterator hex = begin_hex(), endh = end_hex();
13917 for (; hex != endh; ++hex, ++i)
13918 *i = get_user_index(hex);
13919 }
13920}
13921
13922
13923
13924template <int dim, int spacedim>
13927 const std::vector<unsigned int> &v)
13928{
13929 Assert(v.size() == n_hexs(), ExcGridReadError());
13930
13931 if (dim >= 3)
13932 {
13933 hex_iterator hex = begin_hex(), endh = end_hex();
13934 std::vector<unsigned int>::const_iterator i = v.begin();
13935 for (; hex != endh; ++hex, ++i)
13936 set_user_index(hex, *i);
13937 }
13938}
13939
13940#endif
13941
13942
13943//---------------- user pointers ----------------------------------------//
13944
13945
13946namespace
13947{
13948 template <typename Iterator>
13949 void *
13950 get_user_pointer(const Iterator &i)
13951 {
13952 return i->user_pointer();
13953 }
13954
13955
13956
13957 template <int structdim, int dim, int spacedim>
13958 void *
13959 get_user_pointer(
13961 {
13963 return nullptr;
13964 }
13965
13966
13967
13968 template <typename Iterator>
13969 void
13970 set_user_pointer(const Iterator &i, void *x)
13971 {
13972 i->set_user_pointer(x);
13973 }
13974
13975
13976
13977 template <int structdim, int dim, int spacedim>
13978 void
13979 set_user_pointer(
13981 void *)
13982 {
13984 }
13985} // namespace
13986
13987#ifndef DOXYGEN
13988
13989template <int dim, int spacedim>
13992 std::vector<void *> &v) const
13993{
13994 // clear vector and append all the
13995 // stuff later on
13996 v.clear();
13997
13998 std::vector<void *> tmp;
13999
14000 save_user_pointers_line(tmp);
14001 v.insert(v.end(), tmp.begin(), tmp.end());
14002
14003 if (dim >= 2)
14004 {
14005 save_user_pointers_quad(tmp);
14006 v.insert(v.end(), tmp.begin(), tmp.end());
14007 }
14008
14009 if (dim >= 3)
14010 {
14011 save_user_pointers_hex(tmp);
14012 v.insert(v.end(), tmp.begin(), tmp.end());
14013 }
14014
14015 if (dim >= 4)
14017}
14018
14019
14020
14021template <int dim, int spacedim>
14024 const std::vector<void *> &v)
14025{
14026 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
14027 std::vector<void *> tmp;
14028
14029 // first extract the pointers
14030 // belonging to lines
14031 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
14032 // and set the lines
14033 load_user_pointers_line(tmp);
14034
14035 if (dim >= 2)
14036 {
14037 tmp.clear();
14038 tmp.insert(tmp.end(),
14039 v.begin() + n_lines(),
14040 v.begin() + n_lines() + n_quads());
14041 load_user_pointers_quad(tmp);
14042 }
14043
14044 if (dim >= 3)
14045 {
14046 tmp.clear();
14047 tmp.insert(tmp.end(),
14048 v.begin() + n_lines() + n_quads(),
14049 v.begin() + n_lines() + n_quads() + n_hexs());
14050 load_user_pointers_hex(tmp);
14051 }
14052
14053 if (dim >= 4)
14055}
14056
14057
14058
14059template <int dim, int spacedim>
14062 std::vector<void *> &v) const
14063{
14064 v.resize(n_lines(), nullptr);
14065 std::vector<void *>::iterator i = v.begin();
14066 line_iterator line = begin_line(), endl = end_line();
14067 for (; line != endl; ++line, ++i)
14068 *i = line->user_pointer();
14069}
14070
14071
14072
14073template <int dim, int spacedim>
14076 const std::vector<void *> &v)
14077{
14078 Assert(v.size() == n_lines(), ExcGridReadError());
14079
14080 line_iterator line = begin_line(), endl = end_line();
14081 std::vector<void *>::const_iterator i = v.begin();
14082 for (; line != endl; ++line, ++i)
14083 line->set_user_pointer(*i);
14084}
14085
14086
14087
14088template <int dim, int spacedim>
14091 std::vector<void *> &v) const
14092{
14093 v.resize(n_quads(), nullptr);
14094
14095 if (dim >= 2)
14096 {
14097 std::vector<void *>::iterator i = v.begin();
14098 quad_iterator quad = begin_quad(), endq = end_quad();
14099 for (; quad != endq; ++quad, ++i)
14100 *i = get_user_pointer(quad);
14101 }
14102}
14103
14104
14105
14106template <int dim, int spacedim>
14109 const std::vector<void *> &v)
14110{
14111 Assert(v.size() == n_quads(), ExcGridReadError());
14112
14113 if (dim >= 2)
14114 {
14115 quad_iterator quad = begin_quad(), endq = end_quad();
14116 std::vector<void *>::const_iterator i = v.begin();
14117 for (; quad != endq; ++quad, ++i)
14118 set_user_pointer(quad, *i);
14119 }
14120}
14121
14122
14123template <int dim, int spacedim>
14126 std::vector<void *> &v) const
14127{
14128 v.resize(n_hexs(), nullptr);
14129
14130 if (dim >= 3)
14131 {
14132 std::vector<void *>::iterator i = v.begin();
14133 hex_iterator hex = begin_hex(), endh = end_hex();
14134 for (; hex != endh; ++hex, ++i)
14135 *i = get_user_pointer(hex);
14136 }
14137}
14138
14139
14140
14141template <int dim, int spacedim>
14144 const std::vector<void *> &v)
14145{
14146 Assert(v.size() == n_hexs(), ExcGridReadError());
14147
14148 if (dim >= 3)
14149 {
14150 hex_iterator hex = begin_hex(), endh = end_hex();
14151 std::vector<void *>::const_iterator i = v.begin();
14152 for (; hex != endh; ++hex, ++i)
14153 set_user_pointer(hex, *i);
14154 }
14155}
14156
14157#endif
14158
14159/*------------------------ Cell iterator functions ------------------------*/
14160
14161#ifndef DOXYGEN
14162
14163template <int dim, int spacedim>
14166 Triangulation<dim, spacedim>::begin_raw(const unsigned int level) const
14167{
14168 switch (dim)
14169 {
14170 case 1:
14171 return begin_raw_line(level);
14172 case 2:
14173 return begin_raw_quad(level);
14174 case 3:
14175 return begin_raw_hex(level);
14176 default:
14178 return raw_cell_iterator();
14179 }
14180}
14181
14182
14183
14184template <int dim, int spacedim>
14187 Triangulation<dim, spacedim>::begin(const unsigned int level) const
14188{
14189 switch (dim)
14190 {
14191 case 1:
14192 return begin_line(level);
14193 case 2:
14194 return begin_quad(level);
14195 case 3:
14196 return begin_hex(level);
14197 default:
14198 Assert(false, ExcImpossibleInDim(dim));
14199 return cell_iterator();
14200 }
14201}
14202
14203
14204
14205template <int dim, int spacedim>
14208 Triangulation<dim, spacedim>::begin_active(const unsigned int level) const
14209{
14210 switch (dim)
14211 {
14212 case 1:
14213 return begin_active_line(level);
14214 case 2:
14215 return begin_active_quad(level);
14216 case 3:
14217 return begin_active_hex(level);
14218 default:
14220 return active_cell_iterator();
14221 }
14222}
14223
14224
14225
14226template <int dim, int spacedim>
14230{
14231 const unsigned int level = levels.size() - 1;
14232 if (levels[level]->cells.n_objects() == 0)
14233 return end(level);
14234
14235 // find the last raw iterator on
14236 // this level
14237 raw_cell_iterator ri(const_cast<Triangulation<dim, spacedim> *>(this),
14238 level,
14239 levels[level]->cells.n_objects() - 1);
14240
14241 // then move to the last used one
14242 if (ri->used() == true)
14243 return ri;
14244 while ((--ri).state() == IteratorState::valid)
14245 if (ri->used() == true)
14246 return ri;
14247 return ri;
14248}
14249
14250
14251
14252template <int dim, int spacedim>
14256{
14257 // get the last used cell
14258 cell_iterator cell = last();
14259
14260 if (cell != end())
14261 {
14262 // then move to the last active one
14263 if (cell->is_active() == true)
14264 return cell;
14265 while ((--cell).state() == IteratorState::valid)
14266 if (cell->is_active() == true)
14267 return cell;
14268 }
14269 return cell;
14270}
14271
14272
14273
14274template <int dim, int spacedim>
14278 const CellId &cell_id) const
14279{
14280 Assert(
14281 this->contains_cell(cell_id),
14282 ExcMessage(
14283 "CellId is invalid for this triangulation.\n"
14284 "Either the provided CellId does not correspond to a cell in this "
14285 "triangulation object, or, in case you are using a parallel "
14286 "triangulation, may correspond to an artificial cell that is less "
14287 "refined on this processor. In the case of "
14288 "parallel::fullydistributed::Triangulation, the corresponding coarse "
14289 "cell might not be accessible by the current process."));
14290
14291 cell_iterator cell(
14292 this, 0, coarse_cell_id_to_coarse_cell_index(cell_id.get_coarse_cell_id()));
14293
14294 for (const auto &child_index : cell_id.get_child_indices())
14295 cell = cell->child(static_cast<unsigned int>(child_index));
14296
14297 return cell;
14298}
14299
14300
14301
14302template <int dim, int spacedim>
14304bool Triangulation<dim, spacedim>::contains_cell(const CellId &cell_id) const
14305{
14306 const auto coarse_cell_index =
14307 coarse_cell_id_to_coarse_cell_index(cell_id.get_coarse_cell_id());
14308
14309 if (coarse_cell_index == numbers::invalid_unsigned_int)
14310 return false;
14311
14312 cell_iterator cell(this, 0, coarse_cell_index);
14313
14314 for (const auto &child_index : cell_id.get_child_indices())
14315 {
14316 if (cell->has_children() == false)
14317 return false;
14318 cell = cell->child(static_cast<unsigned int>(child_index));
14319 }
14320
14321 return true;
14322}
14323
14324
14325
14326template <int dim, int spacedim>
14330{
14331 return cell_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14332 -1,
14333 -1);
14334}
14335
14336
14337
14338template <int dim, int spacedim>
14341 Triangulation<dim, spacedim>::end_raw(const unsigned int level) const
14342{
14343 // This function may be called on parallel triangulations on levels
14344 // that exist globally, but not on the local portion of the
14345 // triangulation. In that case, just return the end iterator.
14346 //
14347 // We need to use levels.size() instead of n_levels() because the
14348 // latter function uses the cache, but we need to be able to call
14349 // this function at a time when the cache is not currently up to
14350 // date.
14351 if (level >= levels.size())
14352 {
14353 Assert(level < n_global_levels(),
14354 ExcInvalidLevel(level, n_global_levels()));
14355 return end();
14356 }
14357
14358 // Query whether the given level is valid for the local portion of the
14359 // triangulation.
14360 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14361 if (level < levels.size() - 1)
14362 return begin_raw(level + 1);
14363 else
14364 return end();
14365}
14366
14367
14368template <int dim, int spacedim>
14371 Triangulation<dim, spacedim>::end(const unsigned int level) const
14372{
14373 // This function may be called on parallel triangulations on levels
14374 // that exist globally, but not on the local portion of the
14375 // triangulation. In that case, just return the end iterator.
14376 //
14377 // We need to use levels.size() instead of n_levels() because the
14378 // latter function uses the cache, but we need to be able to call
14379 // this function at a time when the cache is not currently up to
14380 // date.
14381 if (level >= levels.size())
14382 {
14383 Assert(level < n_global_levels(),
14384 ExcInvalidLevel(level, n_global_levels()));
14385 return end();
14386 }
14387
14388 // Query whether the given level is valid for the local portion of the
14389 // triangulation.
14390 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14391 if (level < levels.size() - 1)
14392 return begin(level + 1);
14393 else
14394 return end();
14395}
14396
14397
14398template <int dim, int spacedim>
14401 Triangulation<dim, spacedim>::end_active(const unsigned int level) const
14402{
14403 // This function may be called on parallel triangulations on levels
14404 // that exist globally, but not on the local portion of the
14405 // triangulation. In that case, just return the end iterator.
14406 //
14407 // We need to use levels.size() instead of n_levels() because the
14408 // latter function uses the cache, but we need to be able to call
14409 // this function at a time when the cache is not currently up to
14410 // date.
14411 if (level >= levels.size())
14412 {
14413 Assert(level < n_global_levels(),
14414 ExcInvalidLevel(level, n_global_levels()));
14415 return end();
14416 }
14417
14418 // Query whether the given level is valid for the local portion of the
14419 // triangulation.
14420 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14421 return (level >= levels.size() - 1 ? active_cell_iterator(end()) :
14422 begin_active(level + 1));
14423}
14424
14425
14426
14427template <int dim, int spacedim>
14431 const
14432{
14434 begin(), end());
14435}
14436
14437
14438template <int dim, int spacedim>
14441 active_cell_iterator> Triangulation<dim, spacedim>::
14443{
14444 return IteratorRange<
14446 end());
14447}
14448
14449
14450
14451template <int dim, int spacedim>
14454 cell_iterator> Triangulation<dim, spacedim>::
14455 cell_iterators_on_level(const unsigned int level) const
14456{
14458 begin(level), end(level));
14459}
14460
14461
14462
14463template <int dim, int spacedim>
14466 active_cell_iterator> Triangulation<dim, spacedim>::
14467 active_cell_iterators_on_level(const unsigned int level) const
14468{
14469 return IteratorRange<
14471 begin_active(level), end_active(level));
14472}
14473#endif
14474
14475/*------------------------ Face iterator functions ------------------------*/
14476
14477#ifndef DOXYGEN
14478
14479template <int dim, int spacedim>
14483{
14484 switch (dim)
14485 {
14486 case 1:
14487 Assert(false, ExcImpossibleInDim(1));
14488 return raw_face_iterator();
14489 case 2:
14490 return begin_line();
14491 case 3:
14492 return begin_quad();
14493 default:
14495 return face_iterator();
14496 }
14497}
14498
14499
14500
14501template <int dim, int spacedim>
14505{
14506 switch (dim)
14507 {
14508 case 1:
14509 Assert(false, ExcImpossibleInDim(1));
14510 return raw_face_iterator();
14511 case 2:
14512 return begin_active_line();
14513 case 3:
14514 return begin_active_quad();
14515 default:
14517 return active_face_iterator();
14518 }
14519}
14520
14521
14522
14523template <int dim, int spacedim>
14527{
14528 switch (dim)
14529 {
14530 case 1:
14531 Assert(false, ExcImpossibleInDim(1));
14532 return raw_face_iterator();
14533 case 2:
14534 return end_line();
14535 case 3:
14536 return end_quad();
14537 default:
14539 return raw_face_iterator();
14540 }
14541}
14542
14543
14544
14545template <int dim, int spacedim>
14548 active_face_iterator> Triangulation<dim, spacedim>::
14550{
14551 return IteratorRange<
14553 begin_active_face(), end_face());
14554}
14555
14556/*------------------------ Vertex iterator functions ------------------------*/
14557
14558
14559template <int dim, int spacedim>
14563{
14564 vertex_iterator i =
14565 raw_vertex_iterator(const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
14566 if (i.state() != IteratorState::valid)
14567 return i;
14568 // This loop will end because every triangulation has used vertices.
14569 while (i->used() == false)
14570 if ((++i).state() != IteratorState::valid)
14571 return i;
14572 return i;
14573}
14574
14575
14576
14577template <int dim, int spacedim>
14581{
14582 // every vertex is active
14583 return begin_vertex();
14584}
14585
14586
14587
14588template <int dim, int spacedim>
14592{
14593 return raw_vertex_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14594 -1,
14596}
14597
14598#endif
14599
14600
14601/*------------------------ Line iterator functions ------------------------*/
14602
14603#ifndef DOXYGEN
14604
14605template <int dim, int spacedim>
14608 Triangulation<dim, spacedim>::begin_raw_line(const unsigned int level) const
14609{
14610 // This function may be called on parallel triangulations on levels
14611 // that exist globally, but not on the local portion of the
14612 // triangulation. In that case, just return the end iterator.
14613 //
14614 // We need to use levels.size() instead of n_levels() because the
14615 // latter function uses the cache, but we need to be able to call
14616 // this function at a time when the cache is not currently up to
14617 // date.
14618 if (level >= levels.size())
14619 {
14620 Assert(level < n_global_levels(),
14621 ExcInvalidLevel(level, n_global_levels()));
14622 return end_line();
14623 }
14624
14625 switch (dim)
14626 {
14627 case 1:
14628 // Query whether the given level is valid for the local portion of the
14629 // triangulation.
14630 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14631
14632 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
14633 return end_line();
14634
14635 return raw_line_iterator(
14636 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
14637
14638 default:
14639 Assert(level == 0, ExcFacesHaveNoLevel());
14640 return raw_line_iterator(
14641 const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
14642 }
14643}
14644
14645
14646template <int dim, int spacedim>
14649 Triangulation<dim, spacedim>::begin_line(const unsigned int level) const
14650{
14651 // level is checked in begin_raw
14652 raw_line_iterator ri = begin_raw_line(level);
14653 if (ri.state() != IteratorState::valid)
14654 return ri;
14655 while (ri->used() == false)
14656 if ((++ri).state() != IteratorState::valid)
14657 return ri;
14658 return ri;
14659}
14660
14661
14662
14663template <int dim, int spacedim>
14667 const unsigned int level) const
14668{
14669 // level is checked in begin_raw
14670 line_iterator i = begin_line(level);
14671 if (i.state() != IteratorState::valid)
14672 return i;
14673 while (i->has_children())
14674 if ((++i).state() != IteratorState::valid)
14675 return i;
14676 return i;
14677}
14678
14679
14680
14681template <int dim, int spacedim>
14685{
14686 return raw_line_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14687 -1,
14688 -1);
14689}
14690
14691#endif
14692
14693/*------------------------ Quad iterator functions ------------------------*/
14694
14695#ifndef DOXYGEN
14696
14697template <int dim, int spacedim>
14700 Triangulation<dim, spacedim>::begin_raw_quad(const unsigned int level) const
14701{
14702 // This function may be called on parallel triangulations on levels
14703 // that exist globally, but not on the local portion of the
14704 // triangulation. In that case, just return the end iterator.
14705 //
14706 // We need to use levels.size() instead of n_levels() because the
14707 // latter function uses the cache, but we need to be able to call
14708 // this function at a time when the cache is not currently up to
14709 // date.
14710 if (level >= levels.size())
14711 {
14712 Assert(level < n_global_levels(),
14713 ExcInvalidLevel(level, n_global_levels()));
14714 return end_quad();
14715 }
14716
14717 switch (dim)
14718 {
14719 case 1:
14720 Assert(false, ExcImpossibleInDim(1));
14721 return raw_hex_iterator();
14722 case 2:
14723 {
14724 // Query whether the given level is valid for the local portion of the
14725 // triangulation.
14726 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14727
14728 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
14729 return end_quad();
14730
14731 return raw_quad_iterator(
14732 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
14733 }
14734
14735 case 3:
14736 {
14737 Assert(level == 0, ExcFacesHaveNoLevel());
14738
14739 return raw_quad_iterator(
14740 const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
14741 }
14742
14743
14744 default:
14746 return raw_hex_iterator();
14747 }
14748}
14749
14750
14751
14752template <int dim, int spacedim>
14755 Triangulation<dim, spacedim>::begin_quad(const unsigned int level) const
14756{
14757 // level is checked in begin_raw
14758 raw_quad_iterator ri = begin_raw_quad(level);
14759 if (ri.state() != IteratorState::valid)
14760 return ri;
14761 while (ri->used() == false)
14762 if ((++ri).state() != IteratorState::valid)
14763 return ri;
14764 return ri;
14765}
14766
14767
14768
14769template <int dim, int spacedim>
14773 const unsigned int level) const
14774{
14775 // level is checked in begin_raw
14776 quad_iterator i = begin_quad(level);
14777 if (i.state() != IteratorState::valid)
14778 return i;
14779 while (i->has_children())
14780 if ((++i).state() != IteratorState::valid)
14781 return i;
14782 return i;
14783}
14784
14785
14786
14787template <int dim, int spacedim>
14791{
14792 return raw_quad_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14793 -1,
14794 -1);
14795}
14796
14797#endif
14798
14799/*------------------------ Hex iterator functions ------------------------*/
14800
14801#ifndef DOXYGEN
14802
14803template <int dim, int spacedim>
14806 Triangulation<dim, spacedim>::begin_raw_hex(const unsigned int level) const
14807{
14808 // This function may be called on parallel triangulations on levels
14809 // that exist globally, but not on the local portion of the
14810 // triangulation. In that case, just return the end iterator.
14811 //
14812 // We need to use levels.size() instead of n_levels() because the
14813 // latter function uses the cache, but we need to be able to call
14814 // this function at a time when the cache is not currently up to
14815 // date.
14816 if (level >= levels.size())
14817 {
14818 Assert(level < n_global_levels(),
14819 ExcInvalidLevel(level, n_global_levels()));
14820 return end_hex();
14821 }
14822
14823 switch (dim)
14824 {
14825 case 1:
14826 case 2:
14827 Assert(false, ExcImpossibleInDim(1));
14828 return raw_hex_iterator();
14829 case 3:
14830 {
14831 // Query whether the given level is valid for the local portion of the
14832 // triangulation.
14833 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14834
14835 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
14836 return end_hex();
14837
14838 return raw_hex_iterator(
14839 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
14840 }
14841
14842 default:
14844 return raw_hex_iterator();
14845 }
14846}
14847
14848
14849
14850template <int dim, int spacedim>
14853 Triangulation<dim, spacedim>::begin_hex(const unsigned int level) const
14854{
14855 // level is checked in begin_raw
14856 raw_hex_iterator ri = begin_raw_hex(level);
14857 if (ri.state() != IteratorState::valid)
14858 return ri;
14859 while (ri->used() == false)
14860 if ((++ri).state() != IteratorState::valid)
14861 return ri;
14862 return ri;
14863}
14864
14865
14866
14867template <int dim, int spacedim>
14871{
14872 // level is checked in begin_raw
14873 hex_iterator i = begin_hex(level);
14874 if (i.state() != IteratorState::valid)
14875 return i;
14876 while (i->has_children())
14877 if ((++i).state() != IteratorState::valid)
14878 return i;
14879 return i;
14880}
14881
14882
14883
14884template <int dim, int spacedim>
14888{
14889 return raw_hex_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14890 -1,
14891 -1);
14892}
14893
14894#endif
14895
14896// -------------------------------- number of cells etc ---------------
14897
14898
14899namespace internal
14900{
14901 namespace TriangulationImplementation
14902 {
14903 inline unsigned int
14905 {
14906 return c.n_lines;
14907 }
14908
14909
14910 inline unsigned int
14913 {
14914 return c.n_active_lines;
14915 }
14916
14917
14918 inline unsigned int
14920 {
14921 return c.n_quads;
14922 }
14923
14924
14925 inline unsigned int
14928 {
14929 return c.n_active_quads;
14930 }
14931
14932
14933 inline unsigned int
14935 {
14936 return c.n_hexes;
14937 }
14938
14939
14940 inline unsigned int
14943 {
14944 return c.n_active_hexes;
14945 }
14946 } // namespace TriangulationImplementation
14947} // namespace internal
14948
14949#ifndef DOXYGEN
14950
14951template <int dim, int spacedim>
14953unsigned int Triangulation<dim, spacedim>::n_cells() const
14954{
14956}
14957
14958
14959template <int dim, int spacedim>
14962{
14964}
14965
14966template <int dim, int spacedim>
14970{
14971 return n_active_cells();
14972}
14973
14974template <int dim, int spacedim>
14978{
14979 return n_cells(0);
14980}
14981
14982template <int dim, int spacedim>
14984unsigned int Triangulation<dim, spacedim>::n_faces() const
14985{
14986 switch (dim)
14987 {
14988 case 1:
14989 return n_used_vertices();
14990 case 2:
14991 return n_lines();
14992 case 3:
14993 return n_quads();
14994 default:
14996 }
14997 return 0;
14998}
14999
15000
15001template <int dim, int spacedim>
15004{
15005 switch (dim)
15006 {
15007 case 1:
15008 return n_vertices();
15009 case 2:
15010 return n_raw_lines();
15011 case 3:
15012 return n_raw_quads();
15013 default:
15015 }
15016 return 0;
15017}
15018
15019
15020template <int dim, int spacedim>
15023{
15024 switch (dim)
15025 {
15026 case 1:
15027 return n_used_vertices();
15028 case 2:
15029 return n_active_lines();
15030 case 3:
15031 return n_active_quads();
15032 default:
15034 }
15035 return 0;
15036}
15037
15038
15039template <int dim, int spacedim>
15042 const unsigned int level) const
15043{
15044 switch (dim)
15045 {
15046 case 1:
15047 return n_raw_lines(level);
15048 case 2:
15049 return n_raw_quads(level);
15050 case 3:
15051 return n_raw_hexs(level);
15052 default:
15054 }
15055 return 0;
15056}
15057
15058
15059
15060template <int dim, int spacedim>
15063 const unsigned int level) const
15064{
15065 switch (dim)
15066 {
15067 case 1:
15068 return n_lines(level);
15069 case 2:
15070 return n_quads(level);
15071 case 3:
15072 return n_hexs(level);
15073 default:
15075 }
15076 return 0;
15077}
15078
15079
15080
15081template <int dim, int spacedim>
15084 const unsigned int level) const
15085{
15086 switch (dim)
15087 {
15088 case 1:
15089 return n_active_lines(level);
15090 case 2:
15091 return n_active_quads(level);
15092 case 3:
15093 return n_active_hexs(level);
15094 default:
15096 }
15097 return 0;
15098}
15099
15100
15101template <int dim, int spacedim>
15104{
15105 if (anisotropic_refinement == false)
15106 {
15107 for (unsigned int lvl = 0; lvl < n_global_levels() - 1; ++lvl)
15108 if (n_active_cells(lvl) != 0)
15109 return true;
15110 }
15111 else
15112 {
15113 for (const auto &cell : active_cell_iterators())
15114 for (const auto &i : cell->face_indices())
15115 if (cell->face(i)->has_children())
15116 return true;
15117 }
15118 return false;
15119}
15120
15121
15122template <int dim, int spacedim>
15124unsigned int Triangulation<dim, spacedim>::n_lines() const
15125{
15126 return number_cache.n_lines;
15127}
15128
15129
15130
15131template <int dim, int spacedim>
15134 const unsigned int level) const
15135{
15136 if (dim == 1)
15137 {
15138 AssertIndexRange(level, n_levels());
15139 return levels[level]->cells.n_objects();
15140 }
15141
15142 Assert(false, ExcFacesHaveNoLevel());
15143 return 0;
15144}
15145
15146
15147template <int dim, int spacedim>
15150{
15151 if (dim == 1)
15152 {
15154 return 0;
15155 }
15156
15157 return faces->lines.n_objects();
15158}
15159
15160
15161template <int dim, int spacedim>
15164 const unsigned int level) const
15165{
15166 AssertIndexRange(level, number_cache.n_lines_level.size());
15167 Assert(dim == 1, ExcFacesHaveNoLevel());
15168 return number_cache.n_lines_level[level];
15169}
15170
15171
15172template <int dim, int spacedim>
15175{
15176 return number_cache.n_active_lines;
15177}
15178
15179
15180template <int dim, int spacedim>
15183 const unsigned int level) const
15184{
15185 AssertIndexRange(level, number_cache.n_lines_level.size());
15186 Assert(dim == 1, ExcFacesHaveNoLevel());
15187
15188 return number_cache.n_active_lines_level[level];
15189}
15190#endif
15191
15192template <>
15193unsigned int
15195{
15196 return 0;
15197}
15198
15199
15200template <>
15201unsigned int
15202Triangulation<1, 1>::n_quads(const unsigned int) const
15203{
15204 return 0;
15205}
15206
15207
15208template <>
15209unsigned int
15210Triangulation<1, 1>::n_raw_quads(const unsigned int) const
15211{
15212 return 0;
15213}
15214
15215
15216template <>
15217unsigned int
15218Triangulation<1, 1>::n_raw_hexs(const unsigned int) const
15219{
15220 return 0;
15221}
15222
15223
15224template <>
15225unsigned int
15227{
15228 return 0;
15229}
15230
15231
15232template <>
15233unsigned int
15235{
15236 return 0;
15237}
15238
15239
15240
15241template <>
15242unsigned int
15244{
15245 return 0;
15246}
15247
15248
15249template <>
15250unsigned int
15251Triangulation<1, 2>::n_quads(const unsigned int) const
15252{
15253 return 0;
15254}
15255
15256
15257template <>
15258unsigned int
15259Triangulation<1, 2>::n_raw_quads(const unsigned int) const
15260{
15261 return 0;
15262}
15263
15264
15265template <>
15266unsigned int
15267Triangulation<1, 2>::n_raw_hexs(const unsigned int) const
15268{
15269 return 0;
15270}
15271
15272
15273template <>
15274unsigned int
15276{
15277 return 0;
15278}
15279
15280
15281template <>
15282unsigned int
15284{
15285 return 0;
15286}
15287
15288
15289template <>
15290unsigned int
15292{
15293 return 0;
15294}
15295
15296
15297template <>
15298unsigned int
15299Triangulation<1, 3>::n_quads(const unsigned int) const
15300{
15301 return 0;
15302}
15303
15304
15305template <>
15306unsigned int
15307Triangulation<1, 3>::n_raw_quads(const unsigned int) const
15308{
15309 return 0;
15310}
15311
15312
15313template <>
15314unsigned int
15315Triangulation<1, 3>::n_raw_hexs(const unsigned int) const
15316{
15317 return 0;
15318}
15319
15320
15321template <>
15322unsigned int
15324{
15325 return 0;
15326}
15327
15328
15329template <>
15330unsigned int
15332{
15333 return 0;
15334}
15335
15336#ifndef DOXYGEN
15337
15338template <int dim, int spacedim>
15340unsigned int Triangulation<dim, spacedim>::n_quads() const
15341{
15342 return number_cache.n_quads;
15343}
15344
15345
15346template <int dim, int spacedim>
15349 const unsigned int level) const
15350{
15351 Assert(dim == 2, ExcFacesHaveNoLevel());
15352 AssertIndexRange(level, number_cache.n_quads_level.size());
15353 return number_cache.n_quads_level[level];
15354}
15355
15356#endif
15357
15358template <>
15359unsigned int
15361{
15362 AssertIndexRange(level, n_levels());
15363 return levels[level]->cells.n_objects();
15364}
15365
15366
15367
15368template <>
15369unsigned int
15371{
15372 AssertIndexRange(level, n_levels());
15373 return levels[level]->cells.n_objects();
15374}
15375
15376
15377template <>
15378unsigned int
15379Triangulation<3, 3>::n_raw_quads(const unsigned int) const
15380{
15381 Assert(false, ExcFacesHaveNoLevel());
15382 return 0;
15383}
15384
15385#ifndef DOXYGEN
15386
15387template <int dim, int spacedim>
15390{
15392 return 0;
15393}
15394
15395#endif
15396
15397template <>
15398unsigned int
15400{
15401 return faces->quads.n_objects();
15402}
15403
15404#ifndef DOXYGEN
15405
15406template <int dim, int spacedim>
15409{
15410 return number_cache.n_active_quads;
15411}
15412
15413
15414template <int dim, int spacedim>
15417 const unsigned int level) const
15418{
15419 AssertIndexRange(level, number_cache.n_quads_level.size());
15420 Assert(dim == 2, ExcFacesHaveNoLevel());
15421
15422 return number_cache.n_active_quads_level[level];
15423}
15424
15425
15426template <int dim, int spacedim>
15428unsigned int Triangulation<dim, spacedim>::n_hexs() const
15429{
15430 return 0;
15431}
15432
15433
15434
15435template <int dim, int spacedim>
15437unsigned int Triangulation<dim, spacedim>::n_hexs(const unsigned int) const
15438{
15439 return 0;
15440}
15441
15442
15443
15444template <int dim, int spacedim>
15446unsigned int Triangulation<dim, spacedim>::n_raw_hexs(const unsigned int) const
15447{
15448 return 0;
15449}
15450
15451
15452template <int dim, int spacedim>
15455{
15456 return 0;
15457}
15458
15459
15460
15461template <int dim, int spacedim>
15464 const unsigned int) const
15465{
15466 return 0;
15467}
15468
15469#endif
15470
15471template <>
15472unsigned int
15474{
15475 return number_cache.n_hexes;
15476}
15477
15478
15479
15480template <>
15481unsigned int
15482Triangulation<3, 3>::n_hexs(const unsigned int level) const
15483{
15484 AssertIndexRange(level, number_cache.n_hexes_level.size());
15485
15486 return number_cache.n_hexes_level[level];
15487}
15488
15489
15490
15491template <>
15492unsigned int
15494{
15495 AssertIndexRange(level, n_levels());
15496 return levels[level]->cells.n_objects();
15497}
15498
15499
15500template <>
15501unsigned int
15503{
15504 return number_cache.n_active_hexes;
15505}
15506
15507
15508
15509template <>
15510unsigned int
15512{
15513 AssertIndexRange(level, number_cache.n_hexes_level.size());
15514
15515 return number_cache.n_active_hexes_level[level];
15516}
15517
15518#ifndef DOXYGEN
15519
15520template <int dim, int spacedim>
15523{
15524 return std::count(vertices_used.begin(), vertices_used.end(), true);
15525}
15526
15527
15528
15529template <int dim, int spacedim>
15531const std::vector<bool> &Triangulation<dim, spacedim>::get_used_vertices() const
15532{
15533 return vertices_used;
15534}
15535
15536#endif
15537
15538template <>
15539unsigned int
15541{
15542 return 2;
15543}
15544
15545
15546
15547template <>
15548unsigned int
15550{
15551 return 2;
15552}
15553
15554
15555template <>
15556unsigned int
15558{
15559 return 2;
15560}
15561
15562#ifndef DOXYGEN
15563
15564template <int dim, int spacedim>
15567{
15568 cell_iterator cell = begin(0),
15569 endc = (n_levels() > 1 ? begin(1) : cell_iterator(end()));
15570 // store the largest index of the
15571 // vertices used on level 0
15572 unsigned int max_vertex_index = 0;
15573 for (; cell != endc; ++cell)
15574 for (const unsigned int vertex : GeometryInfo<dim>::vertex_indices())
15575 if (cell->vertex_index(vertex) > max_vertex_index)
15576 max_vertex_index = cell->vertex_index(vertex);
15577
15578 // store the number of times a cell
15579 // touches a vertex. An unsigned
15580 // int should suffice, even for
15581 // larger dimensions
15582 std::vector<unsigned short int> usage_count(max_vertex_index + 1, 0);
15583 // touch a vertex's usage count
15584 // every time we find an adjacent
15585 // element
15586 for (cell = begin(); cell != endc; ++cell)
15587 for (const unsigned int vertex : GeometryInfo<dim>::vertex_indices())
15588 ++usage_count[cell->vertex_index(vertex)];
15589
15591 static_cast<unsigned int>(
15592 *std::max_element(usage_count.begin(), usage_count.end())));
15593}
15594
15595
15596
15597template <int dim, int spacedim>
15601{
15603}
15604
15605
15606
15607template <int dim, int spacedim>
15610{
15611 return *this;
15612}
15613
15614
15615
15616template <int dim, int spacedim>
15620{
15621 return *this;
15622}
15623
15624
15625
15626template <int dim, int spacedim>
15630 &periodicity_vector)
15631{
15632 periodic_face_pairs_level_0.insert(periodic_face_pairs_level_0.end(),
15633 periodicity_vector.begin(),
15634 periodicity_vector.end());
15635
15636 // Now initialize periodic_face_map
15637 update_periodic_face_map();
15638}
15639
15640
15641
15642template <int dim, int spacedim>
15644const typename std::map<
15645 std::pair<typename Triangulation<dim, spacedim>::cell_iterator, unsigned int>,
15646 std::pair<std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
15647 unsigned int>,
15650{
15651 return periodic_face_map;
15652}
15653
15654
15655template <int dim, int spacedim>
15658{
15659 // We only update the cell relations here for serial triangulations.
15660 // For other triangulations, this is done at other stages of
15661 // mesh creation and mesh refinement.
15663 this))
15664 return;
15665
15666 this->local_cell_relations.clear();
15667 this->local_cell_relations.reserve(this->n_active_cells());
15668
15669 for (const auto &cell : this->active_cell_iterators())
15670 this->local_cell_relations.emplace_back(
15671 cell, ::CellStatus::cell_will_persist);
15672}
15673
15674
15675
15676template <int dim, int spacedim>
15679{
15681 this))
15682 return;
15683
15684 std::vector<CellId> active_cell_old;
15685
15686 // pack data before triangulation gets updated
15687 if (this->cell_attached_data.n_attached_data_sets > 0)
15688 {
15689 // store old active cells to determine cell status after
15690 // coarsening/refinement
15691 active_cell_old.reserve(this->n_active_cells());
15692
15693 for (const auto &cell : this->active_cell_iterators())
15694 {
15695 const bool children_will_be_coarsened =
15696 (cell->level() > 0) && (cell->coarsen_flag_set());
15697
15698 if (children_will_be_coarsened == false)
15699 active_cell_old.emplace_back(cell->id());
15700 else
15701 {
15702 if (cell->parent()->child(0) == cell)
15703 active_cell_old.emplace_back(cell->parent()->id());
15704 }
15705 }
15706
15707 // update cell relations
15708 this->local_cell_relations.clear();
15709 this->local_cell_relations.reserve(this->n_global_active_cells());
15710
15711 std::vector<
15712 std::pair<unsigned int,
15714 cell_relation_t>>
15715 local_cell_relations_tmp;
15716
15717 for (const auto &cell : this->active_cell_iterators())
15718 {
15719 if (std::find(active_cell_old.begin(),
15720 active_cell_old.end(),
15721 cell->id()) != active_cell_old.end())
15722 {
15723 const unsigned int index =
15724 std::distance(active_cell_old.begin(),
15725 std::find(active_cell_old.begin(),
15726 active_cell_old.end(),
15727 cell->id()));
15728
15729 ::CellStatus status =
15730 cell->refine_flag_set() ?
15733
15734 local_cell_relations_tmp.emplace_back(
15735 index,
15737 cell_relation_t{cell, status});
15738 }
15739 else if (cell->level() > 0 &&
15740 std::find(active_cell_old.begin(),
15741 active_cell_old.end(),
15742 cell->parent()->id()) != active_cell_old.end())
15743 {
15744 const unsigned int index =
15745 std::distance(active_cell_old.begin(),
15746 std::find(active_cell_old.begin(),
15747 active_cell_old.end(),
15748 cell->parent()->id()));
15749
15750 ::CellStatus status;
15751
15752 if (cell->parent()->child_iterator_to_index(cell) == 0)
15754 else
15756
15757 local_cell_relations_tmp.emplace_back(
15758 index,
15760 cell_relation_t{cell->parent(), status});
15761 }
15762 else
15763 {
15765 }
15766 }
15767
15768 std::stable_sort(local_cell_relations_tmp.begin(),
15769 local_cell_relations_tmp.end(),
15770 [](const auto &a, const auto &b) {
15771 return a.first < b.first;
15772 });
15773
15774 for (const auto &tmp : local_cell_relations_tmp)
15775 this->local_cell_relations.emplace_back(tmp.second);
15776
15777 // pack data
15778 this->data_serializer.pack_data(
15779 this->local_cell_relations,
15780 this->cell_attached_data.pack_callbacks_fixed,
15781 this->cell_attached_data.pack_callbacks_variable,
15782 this->get_mpi_communicator());
15783
15784 // dummy copy of data
15785 this->data_serializer.dest_data_fixed =
15786 this->data_serializer.src_data_fixed;
15787 this->data_serializer.dest_data_variable =
15788 this->data_serializer.src_data_variable;
15789 this->data_serializer.dest_sizes_variable =
15790 this->data_serializer.src_sizes_variable;
15791 }
15792}
15793
15794
15795
15796template <int dim, int spacedim>
15799{
15801 this))
15802 return;
15803
15804 // transfer data after triangulation got updated
15805 if (this->cell_attached_data.n_attached_data_sets > 0)
15806 {
15807 std::vector<typename internal::CellAttachedDataSerializer<dim, spacedim>::
15808 cell_relation_t>
15809 temp;
15810
15811 for (const auto &cell : local_cell_relations)
15812 {
15813 if (cell.first->has_children())
15814 {
15817
15818 temp.emplace_back(cell.first->child(0),
15820 }
15821 else
15822 temp.push_back(cell);
15823 }
15824
15825 this->local_cell_relations = temp;
15826 }
15827}
15828
15829
15830
15831template <int dim, int spacedim>
15834{
15835 // Call our version of prepare_coarsening_and_refinement() even if a derived
15836 // class like parallel::distributed::Triangulation overrides it. Their
15837 // function will be called in their execute_coarsening_and_refinement()
15838 // function. Even in a distributed computation our job here is to reconstruct
15839 // the local part of the mesh and as such checking our flags is enough.
15841
15842 // verify a case with which we have had
15843 // some difficulty in the past (see the
15844 // deal.II/coarsening_* tests)
15845 if (smooth_grid & limit_level_difference_at_vertices)
15846 Assert(satisfies_level1_at_vertex_rule(*this) == true, ExcInternalError());
15847
15848 // Inform all listeners about beginning of refinement.
15849 signals.pre_refinement();
15850
15851 this->pack_data_serial();
15852
15853 execute_coarsening();
15854
15855 const DistortedCellList cells_with_distorted_children = execute_refinement();
15856
15857 // We need to update the cell relations in order to be able to
15858 // deserialize data. Later on, update_cell_relations is called to mark all
15859 // active cells with the cell_will_persist status.
15860 this->unpack_data_serial();
15861
15862 reset_cell_vertex_indices_cache();
15863
15864 // verify a case with which we have had
15865 // some difficulty in the past (see the
15866 // deal.II/coarsening_* tests)
15867 if (smooth_grid & limit_level_difference_at_vertices)
15868 Assert(satisfies_level1_at_vertex_rule(*this) == true, ExcInternalError());
15869
15870 // finally build up neighbor connectivity information, and set
15871 // active cell indices
15872 this->policy->update_neighbors(*this);
15873 reset_active_cell_indices();
15874
15875 reset_global_cell_indices(); // TODO: better place?
15876
15877 // Inform all listeners about end of refinement.
15878 signals.post_refinement();
15879
15880 AssertThrow(cells_with_distorted_children.distorted_cells.empty(),
15881 cells_with_distorted_children);
15882
15883 update_periodic_face_map();
15884
15885 if (this->cell_attached_data.n_attached_data_sets == 0)
15886 this->update_cell_relations();
15887
15888 if constexpr (running_in_debug_mode())
15889 {
15890 // In debug mode, we want to check for some consistency of the
15891 // result of this function. Because there are multiple exit
15892 // paths, put this check into a ScopeExit object that is
15893 // executed on each of the exit paths.
15894 //
15895 // Specifically, check on exit of this function that if a quad
15896 // cell has been refined, all of its children have neighbors
15897 // in all directions in which the parent cell has neighbors as
15898 // well. The children's neighbors are either the parent
15899 // neighbor or the parent neighbor's children, or simply one of
15900 // the other children of the current cell. This check is
15901 // useful because if one creates a triangulation with an
15902 // inconsistently ordered set of cells (e.g., because one has
15903 // forgotten to call GridTools::consistently_order_cells()),
15904 // then this relatively simple invariant is violated -- so the
15905 // check here can be used to catch that case, at least
15906 // sometimes.
15907 //
15908 // In 1d, this situation cannot happen. In 3d, we have explicit
15909 // orientation flags to ensure that it is not necessary to re-orient
15910 // cells at the beginning. But in both cases, the invariant should
15911 // still hold as long as the cell is a hypercube.
15912 for (const auto &cell : cell_iterators())
15913 {
15914 if (cell->has_children() && cell->reference_cell().is_hyper_cube())
15915 for (const unsigned int f : cell->face_indices())
15916 if (cell->at_boundary(f) == false)
15917 {
15918 for (const auto &child : cell->child_iterators())
15919 {
15920 Assert(
15921 child->at_boundary(f) == false,
15922 ExcMessage(
15923 "We ended up with a triangulation whose child cells "
15924 "are not connected to their neighbors as expected. "
15925 "When you created the triangulation, did you forget "
15926 "to call GridTools::consistently_order_cells() "
15927 "before calling Triangulation::create_triangulation()?"));
15928 }
15929 }
15930 }
15931 }
15932}
15933
15934
15935
15936template <int dim, int spacedim>
15939{
15940 unsigned int active_cell_index = 0;
15941 for (raw_cell_iterator cell = begin_raw(); cell != end(); ++cell)
15942 if ((cell->used() == false) || cell->has_children())
15943 cell->set_active_cell_index(numbers::invalid_unsigned_int);
15944 else
15945 {
15946 cell->set_active_cell_index(active_cell_index);
15947 ++active_cell_index;
15948 }
15949
15950 Assert(active_cell_index == n_active_cells(), ExcInternalError());
15951}
15952
15953
15954
15955template <int dim, int spacedim>
15958{
15959 {
15961 for (const auto &cell : active_cell_iterators())
15962 cell->set_global_active_cell_index(cell_index++);
15963 }
15964
15965 for (unsigned int l = 0; l < levels.size(); ++l)
15966 {
15968 for (const auto &cell : cell_iterators_on_level(l))
15969 cell->set_global_level_cell_index(cell_index++);
15970 }
15971}
15972
15973
15974
15975template <int dim, int spacedim>
15978{
15979 for (unsigned int l = 0; l < levels.size(); ++l)
15980 {
15981 std::vector<unsigned int> &cache = levels[l]->cell_vertex_indices_cache;
15982 cache.clear();
15983 cache.resize(levels[l]->refine_flags.size() *
15984 ReferenceCells::max_n_vertices<dim>(),
15986 for (const auto &cell : cell_iterators_on_level(l))
15987 {
15988 const unsigned int my_index =
15989 cell->index() * ReferenceCells::max_n_vertices<dim>();
15990
15991 // to reduce the cost of this function when passing down into quads,
15992 // then lines, then vertices, we use a more low-level access method
15993 // for hexahedral cells, where we can streamline most of the logic
15994 const ReferenceCell ref_cell = cell->reference_cell();
15995 if (ref_cell == ReferenceCells::Hexahedron)
15996 for (unsigned int face = 4; face < 6; ++face)
15997 {
15998 const auto face_iter = cell->face(face);
15999 const std::array<types::geometric_orientation, 2>
16000 line_orientations{{face_iter->line_orientation(0),
16001 face_iter->line_orientation(1)}};
16002 const std::array<unsigned int, 2> line_vertex_indices{
16003 {line_orientations[0] ==
16005 line_orientations[1] ==
16007 const std::array<unsigned int, 4> raw_vertex_indices{
16008 {face_iter->line(0)->vertex_index(1 - line_vertex_indices[0]),
16009 face_iter->line(1)->vertex_index(1 - line_vertex_indices[1]),
16010 face_iter->line(0)->vertex_index(line_vertex_indices[0]),
16011 face_iter->line(1)->vertex_index(line_vertex_indices[1])}};
16012
16013 const auto combined_orientation =
16014 levels[l]->face_orientations.get_combined_orientation(
16015 cell->index() * ReferenceCells::max_n_faces<dim>() + face);
16016 const std::array<unsigned int, 4> vertex_order{
16017 {ref_cell.standard_to_real_face_vertex(0,
16018 face,
16019 combined_orientation),
16021 face,
16022 combined_orientation),
16024 face,
16025 combined_orientation),
16027 3, face, combined_orientation)}};
16028
16029 const unsigned int index = my_index + 4 * (face - 4);
16030 for (unsigned int i = 0; i < 4; ++i)
16031 cache[index + i] = raw_vertex_indices[vertex_order[i]];
16032 }
16033 else if (ref_cell == ReferenceCells::Quadrilateral)
16034 {
16035 const std::array<types::geometric_orientation, 2>
16036 line_orientations{
16037 {cell->line_orientation(0), cell->line_orientation(1)}};
16038 const std::array<unsigned int, 2> line_vertex_indices{
16039 {line_orientations[0] == numbers::default_geometric_orientation,
16040 line_orientations[1] ==
16042 const std::array<unsigned int, 4> raw_vertex_indices{
16043 {cell->line(0)->vertex_index(1 - line_vertex_indices[0]),
16044 cell->line(1)->vertex_index(1 - line_vertex_indices[1]),
16045 cell->line(0)->vertex_index(line_vertex_indices[0]),
16046 cell->line(1)->vertex_index(line_vertex_indices[1])}};
16047 for (unsigned int i = 0; i < 4; ++i)
16048 cache[my_index + i] = raw_vertex_indices[i];
16049 }
16050 else if (ref_cell == ReferenceCells::Line)
16051 {
16052 cache[my_index + 0] = cell->vertex_index(0);
16053 cache[my_index + 1] = cell->vertex_index(1);
16054 }
16055 else
16056 {
16057 Assert(dim == 2 || dim == 3, ExcInternalError());
16058 for (const unsigned int i : cell->vertex_indices())
16059 {
16060 const auto [face_index, vertex_index] =
16062 const auto vertex_within_face_index =
16064 vertex_index,
16065 face_index,
16066 cell->combined_face_orientation(face_index));
16067 cache[my_index + i] =
16068 cell->face(face_index)
16069 ->vertex_index(vertex_within_face_index);
16070 }
16071 }
16072 }
16073 }
16074}
16075
16076
16077
16078template <int dim, int spacedim>
16081{
16082 // first empty the currently stored objects
16083 periodic_face_map.clear();
16084
16085 typename std::vector<
16087 for (it = periodic_face_pairs_level_0.begin();
16088 it != periodic_face_pairs_level_0.end();
16089 ++it)
16090 {
16091 update_periodic_face_map_recursively<dim, spacedim>(it->cell[0],
16092 it->cell[1],
16093 it->face_idx[0],
16094 it->face_idx[1],
16095 it->orientation,
16096 periodic_face_map);
16097
16098 const auto face_reference_cell =
16099 it->cell[0]->reference_cell().face_reference_cell(it->face_idx[0]);
16100 // for the other way, we need to invert the orientation
16101 update_periodic_face_map_recursively<dim, spacedim>(
16102 it->cell[1],
16103 it->cell[0],
16104 it->face_idx[1],
16105 it->face_idx[0],
16106 face_reference_cell.get_inverse_combined_orientation(it->orientation),
16107 periodic_face_map);
16108 }
16109
16110 // check consistency
16111 typename std::map<std::pair<cell_iterator, unsigned int>,
16112 std::pair<std::pair<cell_iterator, unsigned int>,
16113 types::geometric_orientation>>::const_iterator
16114 it_test;
16115 for (it_test = periodic_face_map.begin(); it_test != periodic_face_map.end();
16116 ++it_test)
16117 {
16119 it_test->first.first;
16121 it_test->second.first.first;
16122 if (cell_1->level() == cell_2->level())
16123 {
16124 // if both cells have the same neighbor, then the same pair
16125 // order swapped has to be in the map
16126 Assert(periodic_face_map[it_test->second.first].first ==
16127 it_test->first,
16129 }
16130 }
16131}
16132
16133
16134
16135template <int dim, int spacedim>
16138{
16139 std::set<ReferenceCell> reference_cells_set;
16140 for (auto cell : active_cell_iterators())
16141 if (cell->is_locally_owned())
16142 reference_cells_set.insert(cell->reference_cell());
16143
16144 this->reference_cells =
16145 std::vector<ReferenceCell>(reference_cells_set.begin(),
16146 reference_cells_set.end());
16147}
16148
16149
16150
16151template <int dim, int spacedim>
16153const std::vector<ReferenceCell>
16155{
16156 return this->reference_cells;
16157}
16158
16159
16160
16161template <int dim, int spacedim>
16164{
16165 Assert(this->reference_cells.size() > 0,
16166 ExcMessage("You can't ask about the kinds of reference "
16167 "cells used by this triangulation if the "
16168 "triangulation doesn't yet have any cells in it."));
16169 return (this->reference_cells.size() == 1 &&
16170 this->reference_cells[0].is_hyper_cube());
16171}
16172
16173
16174
16175template <int dim, int spacedim>
16178{
16179 Assert(this->reference_cells.size() > 0,
16180 ExcMessage("You can't ask about the kinds of reference "
16181 "cells used by this triangulation if the "
16182 "triangulation doesn't yet have any cells in it."));
16183 return (this->reference_cells.size() == 1 &&
16184 this->reference_cells[0].is_simplex());
16185}
16186
16187
16188
16189template <int dim, int spacedim>
16192{
16193 Assert(this->reference_cells.size() > 0,
16194 ExcMessage("You can't ask about the kinds of reference "
16195 "cells used by this triangulation if the "
16196 "triangulation doesn't yet have any cells in it."));
16197 return reference_cells.size() > 1 ||
16198 ((reference_cells[0].is_hyper_cube() == false) &&
16199 (reference_cells[0].is_simplex() == false));
16200}
16201
16202
16203
16204template <int dim, int spacedim>
16207 const std::function<std::vector<char>(const cell_iterator &,
16208 const ::CellStatus)>
16209 &pack_callback,
16210 const bool returns_variable_size_data)
16211{
16212 unsigned int handle = numbers::invalid_unsigned_int;
16213
16214 // Add new callback function to the corresponding register.
16215 // Encode handles according to returns_variable_size_data.
16216 if (returns_variable_size_data)
16217 {
16218 handle = 2 * this->cell_attached_data.pack_callbacks_variable.size();
16219 this->cell_attached_data.pack_callbacks_variable.push_back(pack_callback);
16220 }
16221 else
16222 {
16223 handle = 2 * this->cell_attached_data.pack_callbacks_fixed.size() + 1;
16224 this->cell_attached_data.pack_callbacks_fixed.push_back(pack_callback);
16225 }
16226
16227 // Increase overall counter.
16228 ++this->cell_attached_data.n_attached_data_sets;
16229
16230 return handle;
16231}
16232
16233
16234
16235template <int dim, int spacedim>
16238 const unsigned int handle,
16239 const std::function<
16240 void(const cell_iterator &,
16241 const ::CellStatus,
16242 const boost::iterator_range<std::vector<char>::const_iterator> &)>
16243 &unpack_callback)
16244{
16245 // perform unpacking
16246 this->data_serializer.unpack_data(this->local_cell_relations,
16247 handle,
16248 unpack_callback);
16249
16250 // decrease counters
16251 --this->cell_attached_data.n_attached_data_sets;
16252 if (this->cell_attached_data.n_attached_deserialize > 0)
16253 --this->cell_attached_data.n_attached_deserialize;
16254
16255 // important: only remove data if we are not in the deserialization
16256 // process. There, each SolutionTransfer registers and unpacks before
16257 // the next one does this, so n_attached_data_sets is only 1 here. This
16258 // would destroy the saved data before the second SolutionTransfer can
16259 // get it. This created a bug that is documented in
16260 // tests/mpi/p4est_save_03 with more than one SolutionTransfer.
16261
16262 if (this->cell_attached_data.n_attached_data_sets == 0 &&
16263 this->cell_attached_data.n_attached_deserialize == 0)
16264 {
16265 // everybody got their data, time for cleanup!
16266 this->cell_attached_data.pack_callbacks_fixed.clear();
16267 this->cell_attached_data.pack_callbacks_variable.clear();
16268 this->data_serializer.clear();
16269
16270 // reset all cell_status entries after coarsening/refinement
16271 for (auto &cell_rel : this->local_cell_relations)
16272 cell_rel.second = ::CellStatus::cell_will_persist;
16273 }
16274}
16275
16276
16277
16278template <int dim, int spacedim>
16281 const unsigned int global_first_cell,
16282 const unsigned int global_num_cells,
16283 const std::string &file_basename) const
16284{
16285 // cast away constness
16286 auto tria = const_cast<Triangulation<dim, spacedim> *>(this);
16287
16288 // each cell should have been flagged `CellStatus::cell_will_persist`
16289 for (const auto &cell_rel : this->local_cell_relations)
16290 {
16291 (void)cell_rel;
16292 Assert((cell_rel.second == // cell_status
16295 }
16296
16297 if (this->cell_attached_data.n_attached_data_sets > 0)
16298 {
16299 // pack attached data first
16300 tria->data_serializer.pack_data(
16301 tria->local_cell_relations,
16302 tria->cell_attached_data.pack_callbacks_fixed,
16303 tria->cell_attached_data.pack_callbacks_variable,
16304 this->get_mpi_communicator());
16305
16306 // then store buffers in file
16307 tria->data_serializer.save(global_first_cell,
16308 global_num_cells,
16309 file_basename,
16310 this->get_mpi_communicator());
16311
16312 // and release the memory afterwards
16313 tria->data_serializer.clear();
16314 }
16315
16316 // clear all of the callback data, as explained in the documentation of
16317 // register_data_attach()
16318 {
16319 tria->cell_attached_data.n_attached_data_sets = 0;
16320 tria->cell_attached_data.pack_callbacks_fixed.clear();
16321 tria->cell_attached_data.pack_callbacks_variable.clear();
16322 }
16323}
16324
16325
16326template <int dim, int spacedim>
16329 const unsigned int global_first_cell,
16330 const unsigned int global_num_cells,
16331 const unsigned int local_num_cells,
16332 const std::string &file_basename,
16333 const unsigned int n_attached_deserialize_fixed,
16334 const unsigned int n_attached_deserialize_variable)
16335{
16336 // load saved data, if any was stored
16337 if (this->cell_attached_data.n_attached_deserialize > 0)
16338 {
16339 this->data_serializer.load(global_first_cell,
16340 global_num_cells,
16341 local_num_cells,
16342 file_basename,
16343 n_attached_deserialize_fixed,
16344 n_attached_deserialize_variable,
16345 this->get_mpi_communicator());
16346
16347 this->data_serializer.unpack_cell_status(this->local_cell_relations);
16348
16349 if constexpr (running_in_debug_mode())
16350 {
16351 // the CellStatus of all stored cells should always be
16352 // CellStatus::cell_will_persist.
16353 for (const auto &cell_rel : this->local_cell_relations)
16354 {
16355 Assert((cell_rel.second == // cell_status
16358 }
16359 }
16360 }
16361}
16362
16363
16364template <int dim, int spacedim>
16367{
16368 levels.clear();
16369 faces.reset();
16370
16371 vertices.clear();
16372 vertices_used.clear();
16373
16374 manifolds.clear();
16375
16376 // In 1d, also reset vertex-to-(boundary|manifold) maps to empty maps
16377 if (dim == 1)
16378 {
16379 Assert(vertex_to_boundary_id_map_1d != nullptr, ExcInternalError());
16380 vertex_to_boundary_id_map_1d->clear();
16381
16382 Assert(vertex_to_manifold_id_map_1d != nullptr, ExcInternalError());
16383 vertex_to_manifold_id_map_1d->clear();
16384 }
16385 else
16386 {
16387 // For dim>1, these maps should simply not exist.
16388 Assert(vertex_to_boundary_id_map_1d == nullptr, ExcInternalError());
16389 Assert(vertex_to_manifold_id_map_1d == nullptr, ExcInternalError());
16390 }
16391
16392
16394}
16395
16396
16397
16398template <int dim, int spacedim>
16402{
16403 const DistortedCellList cells_with_distorted_children =
16404 this->policy->execute_refinement(*this, check_for_distorted_cells);
16405
16406
16407
16408 // re-compute number of lines
16410 *this, levels.size(), number_cache);
16411
16412 if constexpr (running_in_debug_mode())
16413 {
16414 for (const auto &level : levels)
16415 monitor_memory(level->cells, dim);
16416
16417 // check whether really all refinement flags are reset (also of
16418 // previously non-active cells which we may not have touched. If the
16419 // refinement flag of a non-active cell is set, something went wrong
16420 // since the cell-accessors should have caught this)
16421 for (const auto &cell : this->cell_iterators())
16422 Assert(!cell->refine_flag_set(), ExcInternalError());
16423 }
16424
16425 return cells_with_distorted_children;
16426}
16427
16428
16429
16430template <int dim, int spacedim>
16433{
16434 // first find out if there are any cells at all to be coarsened in the
16435 // loop below
16436 const cell_iterator endc = end();
16437 bool do_coarsen = false;
16438 if (levels.size() >= 2)
16439 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
16440 if (!cell->is_active() && cell->child(0)->coarsen_flag_set())
16441 {
16442 do_coarsen = true;
16443 break;
16444 }
16445
16446 if (!do_coarsen)
16447 return;
16448
16449 // create a vector counting for each line and quads how many cells contain
16450 // the respective object. this is used later to decide which lines can be
16451 // deleted after coarsening a cell.
16452 std::vector<unsigned int> line_cell_count(dim > 1 ? this->n_raw_lines() : 0);
16453 std::vector<unsigned int> quad_cell_count(dim > 2 ? this->n_raw_quads() : 0);
16454 if (dim > 1)
16455 for (const auto &cell : this->cell_iterators())
16456 {
16457 if (dim > 2)
16458 {
16459 const auto line_indices = internal::TriaAccessorImplementation::
16460 Implementation::get_line_indices_of_cell(*cell);
16461 // avoid a compiler warning by fixing the max number of
16462 // loop iterations to 12
16463 const unsigned int n_lines = std::min(cell->n_lines(), 12u);
16464 for (unsigned int l = 0; l < n_lines; ++l)
16465 ++line_cell_count[line_indices[l]];
16466 for (const unsigned int q : cell->face_indices())
16467 ++quad_cell_count[cell->face_index(q)];
16468 }
16469 else
16470 for (unsigned int l = 0; l < cell->n_lines(); ++l)
16471 ++line_cell_count[cell->line(l)->index()];
16472 }
16473
16474 // Since the loop goes over used cells we only need not worry about
16475 // deleting some cells since the ++operator will then just hop over them
16476 // if we should hit one. Do the loop in the reverse way since we may
16477 // only delete some cells if their neighbors have already been deleted
16478 // (if the latter are on a higher level for example). In effect, only
16479 // those cells are deleted of which originally all children were flagged
16480 // and for which all children are on the same refinement level. Note
16481 // that because of the effects of
16482 // @p{fix_coarsen_flags}, of a cell either all or no children must be
16483 // flagged for coarsening, so it is ok to only check the first child
16484 //
16485 // since we delete the *children* of cells, we can ignore cells on the
16486 // highest level, i.e., level must be less than or equal to
16487 // n_levels()-2.
16488 if (levels.size() >= 2)
16489 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
16490 if (!cell->is_active() && cell->child(0)->coarsen_flag_set())
16491 {
16492 for (unsigned int child = 0; child < cell->n_children(); ++child)
16493 {
16494 Assert(cell->child(child)->coarsen_flag_set(),
16496 cell->child(child)->clear_coarsen_flag();
16497 }
16498 // inform all listeners that cell coarsening is going to happen
16499 signals.pre_coarsening_on_cell(cell);
16500 // use a separate function, since this is dimension specific
16501 this->policy->delete_children(*this,
16502 cell,
16503 line_cell_count,
16504 quad_cell_count);
16505 }
16506
16507 // re-compute number of lines and quads
16509 *this, levels.size(), number_cache);
16510}
16511
16512
16513
16514template <int dim, int spacedim>
16517{
16518 // copy a piece of code from prepare_coarsening_and_refinement that
16519 // ensures that the level difference at vertices is limited if so
16520 // desired. we need this code here since at least in 1d we don't
16521 // call the dimension-independent version of
16522 // prepare_coarsening_and_refinement function. in 2d and 3d, having
16523 // this hunk here makes our lives a bit easier as well as it takes
16524 // care of these cases earlier than it would otherwise happen.
16525 //
16526 // the main difference to the code in p_c_and_r is that here we
16527 // absolutely have to make sure that we get things right, i.e. that
16528 // in particular we set flags right if
16529 // limit_level_difference_at_vertices is set. to do so we iterate
16530 // until the flags don't change any more
16531 auto previous_coarsen_flags = internal::extract_raw_coarsen_flags(levels);
16532
16533 bool continue_iterating = true;
16534
16535 do
16536 {
16537 if (smooth_grid & limit_level_difference_at_vertices)
16538 {
16539 Assert(!anisotropic_refinement,
16540 ExcMessage("In case of anisotropic refinement the "
16541 "limit_level_difference_at_vertices flag for "
16542 "mesh smoothing must not be set!"));
16543
16544 // store highest level one of the cells adjacent to a vertex
16545 // belongs to
16546 std::vector<int> vertex_level(vertices.size(), 0);
16547 for (const auto &cell : this->active_cell_iterators())
16548 {
16549 if (cell->refine_flag_set())
16550 for (const unsigned int vertex : cell->vertex_indices())
16551 vertex_level[cell->vertex_index(vertex)] =
16552 std::max(vertex_level[cell->vertex_index(vertex)],
16553 cell->level() + 1);
16554 else if (!cell->coarsen_flag_set())
16555 for (const unsigned int vertex : cell->vertex_indices())
16556 vertex_level[cell->vertex_index(vertex)] =
16557 std::max(vertex_level[cell->vertex_index(vertex)],
16558 cell->level());
16559 else
16560 {
16561 // if coarsen flag is set then tentatively assume
16562 // that the cell will be coarsened. this isn't
16563 // always true (the coarsen flag could be removed
16564 // again) and so we may make an error here. we try
16565 // to correct this by iterating over the entire
16566 // process until we are converged
16567 Assert(cell->coarsen_flag_set(), ExcInternalError());
16568 for (const unsigned int vertex : cell->vertex_indices())
16569 vertex_level[cell->vertex_index(vertex)] =
16570 std::max(vertex_level[cell->vertex_index(vertex)],
16571 cell->level() - 1);
16572 }
16573 }
16574
16575
16576 // loop over all cells in reverse order. do so because we
16577 // can then update the vertex levels on the adjacent
16578 // vertices and maybe already flag additional cells in this
16579 // loop
16580 //
16581 // note that not only may we have to add additional
16582 // refinement flags, but we will also have to remove
16583 // coarsening flags on cells adjacent to vertices that will
16584 // see refinement
16585 active_cell_iterator endc = end();
16586 for (active_cell_iterator cell = last_active(); cell != endc; --cell)
16587 if (cell->refine_flag_set() == false)
16588 {
16589 for (const unsigned int vertex : cell->vertex_indices())
16590 if (vertex_level[cell->vertex_index(vertex)] >=
16591 cell->level() + 1)
16592 {
16593 // remove coarsen flag...
16594 cell->clear_coarsen_flag();
16595
16596 // ...and if necessary also refine the current
16597 // cell, at the same time updating the level
16598 // information about vertices
16599 if (vertex_level[cell->vertex_index(vertex)] >
16600 cell->level() + 1)
16601 {
16602 cell->set_refine_flag();
16603
16604 for (const unsigned int v : cell->vertex_indices())
16605 vertex_level[cell->vertex_index(v)] =
16606 std::max(vertex_level[cell->vertex_index(v)],
16607 cell->level() + 1);
16608 }
16609
16610 // continue and see whether we may, for example,
16611 // go into the inner 'if' above based on a
16612 // different vertex
16613 }
16614 }
16615 }
16616
16617 // loop over all cells and remove the coarsen flags for those cells that
16618 // have sister cells not marked for coarsening, or where some neighbors
16619 // are more refined.
16620
16621 // Coarsen flags of cells with no mother cell, i.e. on the
16622 // coarsest level, are deleted explicitly.
16623 for (const auto &acell : this->active_cell_iterators_on_level(0))
16624 acell->clear_coarsen_flag();
16625
16626 const cell_iterator endc = end();
16627 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
16628 {
16629 // nothing to do if we are already on the finest level
16630 if (cell->is_active())
16631 continue;
16632
16633 const unsigned int n_children = cell->n_children();
16634 unsigned int flagged_children = 0;
16635 for (unsigned int child = 0; child < n_children; ++child)
16636 {
16637 const auto child_cell = cell->child(child);
16638 if (child_cell->is_active() && child_cell->coarsen_flag_set())
16639 {
16640 ++flagged_children;
16641 // clear flag since we don't need it anymore
16642 child_cell->clear_coarsen_flag();
16643 }
16644 }
16645
16646 // flag the children for coarsening again if all children were
16647 // flagged and if the policy allows it
16648 if (flagged_children == n_children &&
16649 this->policy->coarsening_allowed(cell))
16650 for (unsigned int c = 0; c < n_children; ++c)
16651 {
16652 Assert(cell->child(c)->refine_flag_set() == false,
16654
16655 cell->child(c)->set_coarsen_flag();
16656 }
16657 }
16658
16659 // now see if anything has changed in the last iteration of this
16660 // function
16661 auto current_coarsen_flags = internal::extract_raw_coarsen_flags(levels);
16662
16663 continue_iterating = (current_coarsen_flags != previous_coarsen_flags);
16664 previous_coarsen_flags.swap(current_coarsen_flags);
16665 }
16666 while (continue_iterating == true);
16667}
16668
16669#endif
16670
16671// TODO: merge the following 3 functions since they are the same
16672template <>
16673bool
16675{
16676 // save the flags to determine whether something was changed in the
16677 // course of this function
16678 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
16679
16680 // do nothing in 1d, except setting the coarsening flags correctly
16681 fix_coarsen_flags();
16682
16683 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
16684
16685 return (flags_before != flags_after);
16686}
16687
16688
16689
16690template <>
16691bool
16693{
16694 // save the flags to determine whether something was changed in the
16695 // course of this function
16696 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
16697
16698 // do nothing in 1d, except setting the coarsening flags correctly
16699 fix_coarsen_flags();
16700
16701 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
16702
16703 return (flags_before != flags_after);
16704}
16705
16706
16707
16708template <>
16709bool
16711{
16712 // save the flags to determine whether something was changed in the
16713 // course of this function
16714 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
16715
16716 // do nothing in 1d, except setting the coarsening flags correctly
16717 fix_coarsen_flags();
16718
16719 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
16720
16721 return (flags_before != flags_after);
16722}
16723
16724
16725
16726namespace
16727{
16728 // check if the given @param cell marked for coarsening would
16729 // produce an unrefined island. To break up long chains of these
16730 // cells we recursively check our neighbors in case we change this
16731 // cell. This reduces the number of outer iterations dramatically.
16732 template <int dim, int spacedim>
16733 void
16734 possibly_do_not_produce_unrefined_islands(
16736 {
16737 Assert(cell->has_children(), ExcInternalError());
16738
16739 unsigned int n_neighbors = 0;
16740 // count all neighbors that will be refined along the face of our
16741 // cell after the next step
16742 unsigned int count = 0;
16743 for (const unsigned int n : GeometryInfo<dim>::face_indices())
16744 {
16745 const typename Triangulation<dim, spacedim>::cell_iterator neighbor =
16746 cell->neighbor(n);
16747 if (neighbor.state() == IteratorState::valid)
16748 {
16749 ++n_neighbors;
16750 if (face_will_be_refined_by_neighbor(cell, n))
16751 ++count;
16752 }
16753 }
16754 // clear coarsen flags if either all existing neighbors will be
16755 // refined or all but one will be and the cell is in the interior
16756 // of the domain
16757 if (count == n_neighbors ||
16758 (count >= n_neighbors - 1 &&
16759 n_neighbors == GeometryInfo<dim>::faces_per_cell))
16760 {
16761 for (unsigned int c = 0; c < cell->n_children(); ++c)
16762 cell->child(c)->clear_coarsen_flag();
16763
16764 for (const unsigned int face : GeometryInfo<dim>::face_indices())
16765 if (!cell->at_boundary(face) &&
16766 (!cell->neighbor(face)->is_active()) &&
16767 (cell_will_be_coarsened(cell->neighbor(face))))
16768 possibly_do_not_produce_unrefined_islands<dim, spacedim>(
16769 cell->neighbor(face));
16770 }
16771 }
16772
16773
16774 // see if the current cell needs to be refined to avoid unrefined
16775 // islands.
16776 //
16777 // there are sometimes chains of cells that induce refinement of
16778 // each other. to avoid running the loop in
16779 // prepare_coarsening_and_refinement over and over again for each
16780 // one of them, at least for the isotropic refinement case we seek
16781 // to flag neighboring elements as well as necessary. this takes
16782 // care of (slightly pathological) cases like
16783 // deal.II/mesh_smoothing_03
16784 template <int dim, int spacedim>
16785 void
16786 possibly_refine_unrefined_island(
16788 const bool allow_anisotropic_smoothing)
16789 {
16790 Assert(cell->is_active(), ExcInternalError());
16791
16792 if constexpr (running_in_debug_mode())
16793 {
16794 // If this is not a parallel::distributed::Triangulation, then we really
16795 // should only get here if the cell is marked for refinement:
16796 if (dynamic_cast<
16798 &cell->get_triangulation()) == nullptr)
16799 Assert(cell->refine_flag_set() == false, ExcInternalError());
16800 else
16801 // But if this is a p::d::Triangulation, then we don't have that
16802 // much control and we can get here because mesh smoothing is
16803 // requested but can not be honored because p4est controls
16804 // what gets refined. In that case, we can at least provide
16805 // a better error message.
16806 Assert(
16807 cell->refine_flag_set() == false,
16808 ExcMessage(
16809 "The triangulation is trying to avoid unrefined islands "
16810 "during mesh refinement/coarsening, as you had requested "
16811 " by passing the appropriate 'smoothing flags' to the "
16812 "constructor of the triangulation. However, for objects "
16813 "of type parallel::distributed::Triangulation, control "
16814 "over which cells get refined rests with p4est, not the "
16815 "deal.II triangulation, and consequently it is not "
16816 "always possible to avoid unrefined islands in the mesh. "
16817 "Please remove the constructor argument to the triangulation "
16818 "object that requests mesh smoothing."));
16819 }
16820
16821 // now we provide two algorithms. the first one is the standard
16822 // one, coming from the time, where only isotropic refinement was
16823 // possible. it simply counts the neighbors that are or will be
16824 // refined and compares to the number of other ones. the second
16825 // one does this check independently for each direction: if all
16826 // neighbors in one direction (normally two, at the boundary only
16827 // one) are refined, the current cell is flagged to be refined in
16828 // an according direction.
16829
16830 if (allow_anisotropic_smoothing == false)
16831 {
16832 // use first algorithm
16833 unsigned int refined_neighbors = 0, unrefined_neighbors = 0;
16834 for (const unsigned int face : GeometryInfo<dim>::face_indices())
16835 if (!cell->at_boundary(face))
16836 {
16837 if (face_will_be_refined_by_neighbor(cell, face))
16838 ++refined_neighbors;
16839 else
16840 ++unrefined_neighbors;
16841 }
16842
16843 if (unrefined_neighbors < refined_neighbors)
16844 {
16845 cell->clear_coarsen_flag();
16846 cell->set_refine_flag();
16847
16848 // ok, so now we have flagged this cell. if we know that
16849 // there were any unrefined neighbors at all, see if any
16850 // of those will have to be refined as well
16851 if (unrefined_neighbors > 0)
16852 for (const unsigned int face : GeometryInfo<dim>::face_indices())
16853 if (!cell->at_boundary(face) &&
16854 (face_will_be_refined_by_neighbor(cell, face) == false) &&
16855 (cell->neighbor(face)->has_children() == false) &&
16856 (cell->neighbor(face)->refine_flag_set() == false))
16857 possibly_refine_unrefined_island<dim, spacedim>(
16858 cell->neighbor(face), allow_anisotropic_smoothing);
16859 }
16860 }
16861 else
16862 {
16863 // variable to store the cell refine case needed to fulfill
16864 // all smoothing requirements
16865 RefinementCase<dim> smoothing_cell_refinement_case =
16867
16868 // use second algorithm, do the check individually for each
16869 // direction
16870 for (unsigned int face_pair = 0;
16871 face_pair < GeometryInfo<dim>::faces_per_cell / 2;
16872 ++face_pair)
16873 {
16874 // variable to store the cell refine case needed to refine
16875 // at the current face pair in the same way as the
16876 // neighbors do...
16877 RefinementCase<dim> directional_cell_refinement_case =
16879
16880 for (unsigned int face_index = 0; face_index < 2; ++face_index)
16881 {
16882 unsigned int face = 2 * face_pair + face_index;
16883 // variable to store the refine case (to come) of the
16884 // face under consideration
16885 RefinementCase<dim - 1> expected_face_ref_case =
16886 RefinementCase<dim - 1>::no_refinement;
16887
16888 if (cell->neighbor(face).state() == IteratorState::valid)
16889 face_will_be_refined_by_neighbor<dim, spacedim>(
16890 cell, face, expected_face_ref_case);
16891 // now extract which refine case would be necessary to
16892 // achieve the same face refinement. set the
16893 // intersection with other requirements for the same
16894 // direction.
16895
16896 // note: using the intersection is not an obvious
16897 // decision, we could also argue that it is more
16898 // natural to use the union. however, intersection is
16899 // the less aggressive tactic and favours a smaller
16900 // number of refined cells over an intensive
16901 // smoothing. this way we try not to lose too much of
16902 // the effort we put in anisotropic refinement
16903 // indicators due to overly aggressive smoothing...
16904 directional_cell_refinement_case =
16905 (directional_cell_refinement_case &
16908 expected_face_ref_case,
16909 face,
16910 cell->face_orientation(face),
16911 cell->face_flip(face),
16912 cell->face_rotation(face)));
16913 } // for both face indices
16914 // if both requirements sum up to something useful, add
16915 // this to the refine case for smoothing. note: if
16916 // directional_cell_refinement_case is isotropic still,
16917 // then something went wrong...
16918 Assert(directional_cell_refinement_case <
16921 smoothing_cell_refinement_case =
16922 smoothing_cell_refinement_case | directional_cell_refinement_case;
16923 } // for all face_pairs
16924 // no we collected contributions from all directions. combine
16925 // the new flags with the existing refine case, but only if
16926 // smoothing is required
16927 if (smoothing_cell_refinement_case)
16928 {
16929 cell->clear_coarsen_flag();
16930 cell->set_refine_flag(cell->refine_flag_set() |
16931 smoothing_cell_refinement_case);
16932 }
16933 }
16934 }
16935} // namespace
16936
16937#ifndef DOXYGEN
16938template <int dim, int spacedim>
16941{
16942 // save the flags to determine whether something was changed in the
16943 // course of this function
16944 const auto coarsen_flags_before = internal::extract_raw_coarsen_flags(levels);
16945 const auto refine_flags_before = internal::extract_raw_refine_flags(levels);
16946
16947 // save the flags at the outset of each loop. we do so in order to
16948 // find out whether something was changed in the present loop, in
16949 // which case we would have to re-run the loop. the other
16950 // possibility to find this out would be to set a flag
16951 // @p{something_changed} to true each time we change something.
16952 // however, sometimes one change in one of the parts of the loop is
16953 // undone by another one, so we might end up in an endless loop. we
16954 // could be tempted to break this loop at an arbitrary number of
16955 // runs, but that would not be a clean solution, since we would
16956 // either have to 1/ break the loop too early, in which case the
16957 // promise that a second call to this function immediately after the
16958 // first one does not change anything, would be broken, or 2/ we do
16959 // as many loops as there are levels. we know that information is
16960 // transported over one level in each run of the loop, so this is
16961 // enough. Unfortunately, each loop is rather expensive, so we chose
16962 // the way presented here
16963 auto coarsen_flags_before_loop = coarsen_flags_before;
16964 auto refine_flags_before_loop = refine_flags_before;
16965
16966 // now for what is done in each loop: we have to fulfill several
16967 // tasks at the same time, namely several mesh smoothing algorithms
16968 // and mesh regularization, by which we mean that the next mesh
16969 // fulfills several requirements such as no double refinement at
16970 // each face or line, etc.
16971 //
16972 // since doing these things at once seems almost impossible (in the
16973 // first year of this library, they were done in two functions, one
16974 // for refinement and one for coarsening, and most things within
16975 // these were done at once, so the code was rather impossible to
16976 // join into this, only, function), we do them one after each
16977 // other. the order in which we do them is such that the important
16978 // tasks, namely regularization, are done last and the least
16979 // important things are done the first. the following order is
16980 // chosen:
16981 //
16982 // 0/ Only if coarsest_level_1 or patch_level_1 is set: clear all
16983 // coarsen flags on level 1 to avoid level 0 cells being created
16984 // by coarsening. As coarsen flags will never be added, this can
16985 // be done once and for all before the actual loop starts.
16986 //
16987 // 1/ do not coarsen a cell if 'most of the neighbors' will be
16988 // refined after the step. This is to prevent occurrence of
16989 // unrefined islands.
16990 //
16991 // 2/ eliminate refined islands in the interior and at the
16992 // boundary. since they don't do much harm besides increasing the
16993 // number of degrees of freedom, doing this has a rather low
16994 // priority.
16995 //
16996 // 3/ limit the level difference of neighboring cells at each
16997 // vertex.
16998 //
16999 // 4/ eliminate unrefined islands. this has higher priority since
17000 // this diminishes the approximation properties not only of the
17001 // unrefined island, but also of the surrounding patch.
17002 //
17003 // 5/ ensure patch level 1. Then the triangulation consists of
17004 // patches, i.e. of cells that are refined once. It follows that
17005 // if at least one of the children of a cell is or will be
17006 // refined than all children need to be refined. This step only
17007 // sets refinement flags and does not set coarsening flags. If
17008 // the patch_level_1 flag is set, then
17009 // eliminate_unrefined_islands, eliminate_refined_inner_islands
17010 // and eliminate_refined_boundary_islands will be fulfilled
17011 // automatically and do not need to be enforced separately.
17012 //
17013 // 6/ take care of the requirement that no double refinement is done
17014 // at each face
17015 //
17016 // 7/ take care that no double refinement is done at each line in 3d
17017 // or higher dimensions.
17018 //
17019 // 8/ make sure that all children of each cell are either flagged
17020 // for coarsening or none of the children is
17021 //
17022 // For some of these steps, it is known that they interact. Namely,
17023 // it is not possible to guarantee that after step 6 another step 5
17024 // would have no effect; the same holds for the opposite order and
17025 // also when taking into account step 7. however, it is important to
17026 // guarantee that step five or six do not undo something that step 5
17027 // did, and step 7 not something of step 6, otherwise the
17028 // requirements will not be satisfied even if the loop
17029 // terminates. this is accomplished by the fact that steps 5 and 6
17030 // only *add* refinement flags and delete coarsening flags
17031 // (therefore, step 6 can't undo something that step 4 already did),
17032 // and step 7 only deletes coarsening flags, never adds some. step 7
17033 // needs also take care that it won't tag cells for refinement for
17034 // which some neighbors are more refined or will be refined.
17035
17036 //------------------------------------
17037 // STEP 0:
17038 // Only if coarsest_level_1 or patch_level_1 is set: clear all
17039 // coarsen flags on level 1 to avoid level 0 cells being created
17040 // by coarsening.
17041 if (((smooth_grid & coarsest_level_1) || (smooth_grid & patch_level_1)) &&
17042 n_levels() >= 2)
17043 {
17044 for (const auto &cell : active_cell_iterators_on_level(1))
17045 cell->clear_coarsen_flag();
17046 }
17047
17048 bool mesh_changed_in_this_loop = false;
17049 do
17050 {
17051 //------------------------------------
17052 // STEP 1:
17053 // do not coarsen a cell if 'most of the neighbors' will be
17054 // refined after the step. This is to prevent the occurrence
17055 // of unrefined islands. If patch_level_1 is set, this will
17056 // be automatically fulfilled.
17057 if (smooth_grid & do_not_produce_unrefined_islands &&
17058 !(smooth_grid & patch_level_1))
17059 {
17060 for (const auto &cell : cell_iterators())
17061 {
17062 // only do something if this
17063 // cell will be coarsened
17064 if (!cell->is_active() && cell_will_be_coarsened(cell))
17065 possibly_do_not_produce_unrefined_islands<dim, spacedim>(cell);
17066 }
17067 }
17068
17069
17070 //------------------------------------
17071 // STEP 2:
17072 // eliminate refined islands in the interior and at the
17073 // boundary. since they don't do much harm besides increasing
17074 // the number of degrees of freedom, doing this has a rather
17075 // low priority. If patch_level_1 is set, this will be
17076 // automatically fulfilled.
17077 //
17078 // there is one corner case to consider: if this is a
17079 // distributed triangulation, there may be refined islands on
17080 // the boundary of which we own only part (e.g. a single cell
17081 // in the corner of a domain). the rest of the island is
17082 // ghost cells and it *looks* like the area around it
17083 // (artificial cells) are coarser but this is only because
17084 // they may actually be equally fine on other
17085 // processors. it's hard to detect this case but we can do
17086 // the following: only set coarsen flags to remove this
17087 // refined island if all cells we want to set flags on are
17088 // locally owned
17089 if (smooth_grid & (eliminate_refined_inner_islands |
17090 eliminate_refined_boundary_islands) &&
17091 !(smooth_grid & patch_level_1))
17092 {
17093 for (const auto &cell : cell_iterators())
17094 if (!cell->is_active() ||
17095 (cell->is_active() && cell->refine_flag_set() &&
17096 cell->is_locally_owned()))
17097 {
17098 // check whether all children are active, i.e. not
17099 // refined themselves. This is a precondition that the
17100 // children may be coarsened away. If the cell is only
17101 // flagged for refinement, then all future children
17102 // will be active
17103 bool all_children_active = true;
17104 if (!cell->is_active())
17105 for (unsigned int c = 0; c < cell->n_children(); ++c)
17106 if (!cell->child(c)->is_active() ||
17107 cell->child(c)->is_ghost() ||
17108 cell->child(c)->is_artificial())
17109 {
17110 all_children_active = false;
17111 break;
17112 }
17113
17114 if (all_children_active)
17115 {
17116 // count number of refined and unrefined neighbors
17117 // of cell. neighbors on lower levels are counted
17118 // as unrefined since they can only get to the
17119 // same level as this cell by the next refinement
17120 // cycle
17121 unsigned int unrefined_neighbors = 0, total_neighbors = 0;
17122
17123 // Keep track if this cell is at a periodic
17124 // boundary or not. TODO: We do not currently run
17125 // the algorithm for inner islands at a periodic
17126 // boundary (remains to be implemented), but we
17127 // also don't want to consider them
17128 // boundary_island cells as this can interfere
17129 // with 2:1 refinement across periodic faces.
17130 // Instead: just ignore those cells for this
17131 // smoothing operation below.
17132 bool at_periodic_boundary = false;
17133
17134 for (const unsigned int n : cell->face_indices())
17135 {
17136 const cell_iterator neighbor = cell->neighbor(n);
17137 if (neighbor.state() == IteratorState::valid)
17138 {
17139 ++total_neighbors;
17140
17141 if (!face_will_be_refined_by_neighbor(cell, n))
17142 ++unrefined_neighbors;
17143 }
17144 else if (cell->has_periodic_neighbor(n))
17145 {
17146 ++total_neighbors;
17147 at_periodic_boundary = true;
17148 }
17149 }
17150
17151 // if all neighbors unrefined: mark this cell for
17152 // coarsening or don't refine if marked for that
17153 //
17154 // also do the distinction between the two
17155 // versions of the eliminate_refined_*_islands
17156 // flag
17157 //
17158 // the last check is whether there are any
17159 // neighbors at all. if not so, then we are (e.g.)
17160 // on the coarsest grid with one cell, for which,
17161 // of course, we do not remove the refine flag.
17162 if ((unrefined_neighbors == total_neighbors) &&
17163 ((!cell->at_boundary() &&
17164 (smooth_grid & eliminate_refined_inner_islands)) ||
17165 (cell->at_boundary() && !at_periodic_boundary &&
17166 (smooth_grid &
17167 eliminate_refined_boundary_islands))) &&
17168 (total_neighbors != 0))
17169 {
17170 if (!cell->is_active())
17171 for (unsigned int c = 0; c < cell->n_children(); ++c)
17172 {
17173 cell->child(c)->clear_refine_flag();
17174 cell->child(c)->set_coarsen_flag();
17175 }
17176 else
17177 cell->clear_refine_flag();
17178 }
17179 }
17180 }
17181 }
17182
17183 //------------------------------------
17184 // STEP 3:
17185 // limit the level difference of neighboring cells at each
17186 // vertex.
17187 //
17188 // in case of anisotropic refinement this does not make
17189 // sense. as soon as one cell is anisotropically refined, an
17190 // Assertion is thrown. therefore we can ignore this problem
17191 // later on
17192 if (smooth_grid & limit_level_difference_at_vertices)
17193 {
17194 Assert(!anisotropic_refinement,
17195 ExcMessage("In case of anisotropic refinement the "
17196 "limit_level_difference_at_vertices flag for "
17197 "mesh smoothing must not be set!"));
17198
17199 // store highest level one of the cells adjacent to a vertex
17200 // belongs to
17201 std::vector<int> vertex_level(vertices.size(), 0);
17202 for (const auto &cell : active_cell_iterators())
17203 {
17204 if (cell->refine_flag_set())
17205 for (const unsigned int vertex : cell->vertex_indices())
17206 vertex_level[cell->vertex_index(vertex)] =
17207 std::max(vertex_level[cell->vertex_index(vertex)],
17208 cell->level() + 1);
17209 else if (!cell->coarsen_flag_set())
17210 for (const unsigned int vertex : cell->vertex_indices())
17211 vertex_level[cell->vertex_index(vertex)] =
17212 std::max(vertex_level[cell->vertex_index(vertex)],
17213 cell->level());
17214 else
17215 {
17216 // if coarsen flag is set then tentatively assume
17217 // that the cell will be coarsened. this isn't
17218 // always true (the coarsen flag could be removed
17219 // again) and so we may make an error here
17220 Assert(cell->coarsen_flag_set(), ExcInternalError());
17221 for (const unsigned int vertex : cell->vertex_indices())
17222 vertex_level[cell->vertex_index(vertex)] =
17223 std::max(vertex_level[cell->vertex_index(vertex)],
17224 cell->level() - 1);
17225 }
17226 }
17227
17228
17229 // loop over all cells in reverse order. do so because we
17230 // can then update the vertex levels on the adjacent
17231 // vertices and maybe already flag additional cells in this
17232 // loop
17233 //
17234 // note that not only may we have to add additional
17235 // refinement flags, but we will also have to remove
17236 // coarsening flags on cells adjacent to vertices that will
17237 // see refinement
17238 for (active_cell_iterator cell = last_active(); cell != end(); --cell)
17239 if (cell->refine_flag_set() == false)
17240 {
17241 for (const unsigned int vertex : cell->vertex_indices())
17242 if (vertex_level[cell->vertex_index(vertex)] >=
17243 cell->level() + 1)
17244 {
17245 // remove coarsen flag...
17246 cell->clear_coarsen_flag();
17247
17248 // ...and if necessary also refine the current
17249 // cell, at the same time updating the level
17250 // information about vertices
17251 if (vertex_level[cell->vertex_index(vertex)] >
17252 cell->level() + 1)
17253 {
17254 cell->set_refine_flag();
17255
17256 for (const unsigned int v : cell->vertex_indices())
17257 vertex_level[cell->vertex_index(v)] =
17258 std::max(vertex_level[cell->vertex_index(v)],
17259 cell->level() + 1);
17260 }
17261
17262 // continue and see whether we may, for example,
17263 // go into the inner'if'
17264 // above based on a
17265 // different vertex
17266 }
17267 }
17268 }
17269
17270 //-----------------------------------
17271 // STEP 4:
17272 // eliminate unrefined islands. this has higher priority
17273 // since this diminishes the approximation properties not
17274 // only of the unrefined island, but also of the surrounding
17275 // patch.
17276 //
17277 // do the loop from finest to coarsest cells since we may
17278 // trigger a cascade by marking cells for refinement which
17279 // may trigger more cells further down below
17280 if (smooth_grid & eliminate_unrefined_islands)
17281 {
17282 for (active_cell_iterator cell = last_active(); cell != end(); --cell)
17283 // only do something if cell is not already flagged for
17284 // (isotropic) refinement
17285 if (cell->refine_flag_set() !=
17287 possibly_refine_unrefined_island<dim, spacedim>(
17288 cell, (smooth_grid & allow_anisotropic_smoothing) != 0);
17289 }
17290
17291 //-------------------------------
17292 // STEP 5:
17293 // ensure patch level 1.
17294 //
17295 // Introduce some terminology:
17296 // - a cell that is refined
17297 // once is a patch of
17298 // level 1 simply called patch.
17299 // - a cell that is globally
17300 // refined twice is called
17301 // a patch of level 2.
17302 // - patch level n says that
17303 // the triangulation consists
17304 // of patches of level n.
17305 // This makes sense only
17306 // if the grid is already at
17307 // least n times globally
17308 // refined.
17309 //
17310 // E.g. from patch level 1 follows: if at least one of the
17311 // children of a cell is or will be refined than enforce all
17312 // children to be refined.
17313
17314 // This step 4 only sets refinement flags and does not set
17315 // coarsening flags.
17316 if (smooth_grid & patch_level_1)
17317 {
17318 // An important assumption (A) is that before calling this
17319 // function the grid was already of patch level 1.
17320
17321 // loop over all cells whose children are all active. (By
17322 // assumption (A) either all or none of the children are
17323 // active). If the refine flag of at least one of the
17324 // children is set then set_refine_flag and
17325 // clear_coarsen_flag of all children.
17326 for (const auto &cell : cell_iterators())
17327 if (!cell->is_active())
17328 {
17329 // ensure the invariant. we can then check whether all
17330 // of its children are further refined or not by
17331 // simply looking at the first child
17332 Assert(cell_is_patch_level_1(cell), ExcInternalError());
17333 if (cell->child(0)->has_children() == true)
17334 continue;
17335
17336 // cell is found to be a patch. combine the refine
17337 // cases of all children
17338 RefinementCase<dim> combined_ref_case =
17340 for (unsigned int i = 0; i < cell->n_children(); ++i)
17341 combined_ref_case =
17342 combined_ref_case | cell->child(i)->refine_flag_set();
17343 if (combined_ref_case != RefinementCase<dim>::no_refinement)
17344 for (unsigned int i = 0; i < cell->n_children(); ++i)
17345 {
17346 cell_iterator child = cell->child(i);
17347
17348 child->clear_coarsen_flag();
17349 child->set_refine_flag(combined_ref_case);
17350 }
17351 }
17352
17353 // The code above dealt with the case where we may get a
17354 // non-patch_level_1 mesh from refinement. Now also deal
17355 // with the case where we could get such a mesh by
17356 // coarsening. Coarsen the children (and remove the
17357 // grandchildren) only if all cell->grandchild(i)
17358 // ->coarsen_flag_set() are set.
17359 //
17360 // for a case where this is a bit tricky, take a look at the
17361 // mesh_smoothing_0[12] testcases
17362 for (const auto &cell : cell_iterators())
17363 {
17364 // check if this cell has active grandchildren. note
17365 // that we know that it is patch_level_1, i.e. if one of
17366 // its children is active then so are all, and it isn't
17367 // going to have any grandchildren at all:
17368 if (cell->is_active() || cell->child(0)->is_active())
17369 continue;
17370
17371 // cell is not active, and so are none of its
17372 // children. check the grandchildren. note that the
17373 // children are also patch_level_1, and so we only ever
17374 // need to check their first child
17375 const unsigned int n_children = cell->n_children();
17376 bool has_active_grandchildren = false;
17377
17378 for (unsigned int i = 0; i < n_children; ++i)
17379 if (cell->child(i)->child(0)->is_active())
17380 {
17381 has_active_grandchildren = true;
17382 break;
17383 }
17384
17385 if (has_active_grandchildren == false)
17386 continue;
17387
17388
17389 // ok, there are active grandchildren. see if either all
17390 // or none of them are flagged for coarsening
17391 unsigned int n_grandchildren = 0;
17392
17393 // count all coarsen flags of the grandchildren.
17394 unsigned int n_coarsen_flags = 0;
17395
17396 // cell is not a patch (of level 1) as it has a
17397 // grandchild. Is cell a patch of level 2?? Therefore:
17398 // find out whether all cell->child(i) are patches
17399 for (unsigned int c = 0; c < n_children; ++c)
17400 {
17401 // get at the child. by assumption (A), and the
17402 // check by which we got here, the child is not
17403 // active
17404 cell_iterator child = cell->child(c);
17405
17406 const unsigned int nn_children = child->n_children();
17407 n_grandchildren += nn_children;
17408
17409 // if child is found to be a patch of active cells
17410 // itself, then add up how many of its children are
17411 // supposed to be coarsened
17412 if (child->child(0)->is_active())
17413 for (unsigned int cc = 0; cc < nn_children; ++cc)
17414 if (child->child(cc)->coarsen_flag_set())
17415 ++n_coarsen_flags;
17416 }
17417
17418 // if not all grandchildren are supposed to be coarsened
17419 // (e.g. because some simply don't have the flag set, or
17420 // because they are not active and therefore cannot
17421 // carry the flag), then remove the coarsen flag from
17422 // all of the active grandchildren. note that there may
17423 // be coarsen flags on the grandgrandchildren -- we
17424 // don't clear them here, but we'll get to them in later
17425 // iterations if necessary
17426 //
17427 // there is nothing we have to do if no coarsen flags
17428 // have been set at all
17429 if ((n_coarsen_flags != n_grandchildren) && (n_coarsen_flags > 0))
17430 for (unsigned int c = 0; c < n_children; ++c)
17431 {
17432 const cell_iterator child = cell->child(c);
17433 if (child->child(0)->is_active())
17434 for (unsigned int cc = 0; cc < child->n_children(); ++cc)
17435 child->child(cc)->clear_coarsen_flag();
17436 }
17437 }
17438 }
17439
17440 //--------------------------------
17441 //
17442 // at the boundary we could end up with cells with negative
17443 // volume or at least with a part, that is negative, if the
17444 // cell is refined anisotropically. we have to check, whether
17445 // that can happen
17446 this->policy->prevent_distorted_boundary_cells(*this);
17447
17448 //-------------------------------
17449 // STEP 6:
17450 // take care of the requirement that no
17451 // double refinement is done at each face
17452 //
17453 // in case of anisotropic refinement it is only likely, but
17454 // not sure, that the cells, which are more refined along a
17455 // certain face common to two cells are on a higher
17456 // level. therefore we cannot be sure, that the requirement
17457 // of no double refinement is fulfilled after a single pass
17458 // of the following actions. We could just wait for the next
17459 // global loop. when this function terminates, the
17460 // requirement will be fulfilled. However, it might be faster
17461 // to insert an inner loop here.
17462 bool changed = true;
17463 while (changed)
17464 {
17465 changed = false;
17466 active_cell_iterator cell = last_active(), endc = end();
17467
17468 for (; cell != endc; --cell)
17469 if (cell->refine_flag_set())
17470 {
17471 // loop over neighbors of cell
17472 for (const auto i : cell->face_indices())
17473 {
17474 // only do something if the face is not at the
17475 // boundary and if the face will be refined with
17476 // the RefineCase currently flagged for
17477 const bool has_periodic_neighbor =
17478 cell->has_periodic_neighbor(i);
17479 const bool has_neighbor_or_periodic_neighbor =
17480 !cell->at_boundary(i) || has_periodic_neighbor;
17481 if (has_neighbor_or_periodic_neighbor &&
17483 cell->refine_flag_set(), i) !=
17485 {
17486 // 1) if the neighbor has children: nothing to
17487 // worry about. 2) if the neighbor is active
17488 // and a coarser one, ensure, that its
17489 // refine_flag is set 3) if the neighbor is
17490 // active and as refined along the face as our
17491 // current cell, make sure, that no
17492 // coarsen_flag is set. if we remove the
17493 // coarsen flag of our neighbor,
17494 // fix_coarsen_flags() makes sure, that the
17495 // mother cell will not be coarsened
17496 if (cell->neighbor_or_periodic_neighbor(i)->is_active())
17497 {
17498 if ((!has_periodic_neighbor &&
17499 cell->neighbor_is_coarser(i)) ||
17500 (has_periodic_neighbor &&
17501 cell->periodic_neighbor_is_coarser(i)))
17502 {
17503 if (cell->neighbor_or_periodic_neighbor(i)
17504 ->coarsen_flag_set())
17505 cell->neighbor_or_periodic_neighbor(i)
17506 ->clear_coarsen_flag();
17507 // we'll set the refine flag for this
17508 // neighbor below. we note, that we
17509 // have changed something by setting
17510 // the changed flag to true. We do not
17511 // need to do so, if we just removed
17512 // the coarsen flag, as the changed
17513 // flag only indicates the need to
17514 // re-run the inner loop. however, we
17515 // only loop over cells flagged for
17516 // refinement here, so nothing to
17517 // worry about if we remove coarsen
17518 // flags
17519
17520 if (dim == 2)
17521 {
17522 if (smooth_grid &
17523 allow_anisotropic_smoothing)
17524 changed =
17525 has_periodic_neighbor ?
17526 cell->periodic_neighbor(i)
17527 ->flag_for_face_refinement(
17528 cell
17529 ->periodic_neighbor_of_coarser_periodic_neighbor(
17530 i)
17531 .first,
17533 cell->neighbor(i)
17534 ->flag_for_face_refinement(
17535 cell
17536 ->neighbor_of_coarser_neighbor(
17537 i)
17538 .first,
17540 else
17541 {
17542 if (!cell
17543 ->neighbor_or_periodic_neighbor(
17544 i)
17545 ->refine_flag_set())
17546 changed = true;
17547 cell->neighbor_or_periodic_neighbor(i)
17548 ->set_refine_flag();
17549 }
17550 }
17551 else // i.e. if (dim==3)
17552 {
17553 // ugly situations might arise here,
17554 // consider the following situation, which
17555 // shows neighboring cells at the common
17556 // face, where the upper right element is
17557 // coarser at the given face. Now the upper
17558 // child element of the lower left wants to
17559 // refine according to cut_z, such that
17560 // there is a 'horizontal' refinement of the
17561 // face marked with #####
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 // / /
17587 //
17588 // this introduces too many hanging nodes
17589 // and the neighboring (coarser) cell (upper
17590 // right) has to be refined. If it is only
17591 // refined according to cut_z, then
17592 // everything is ok:
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 // / /
17618 //
17619 // if however the cell wants to refine
17620 // itself in an other way, or if we disallow
17621 // anisotropic smoothing, then simply
17622 // refining the neighbor isotropically is
17623 // not going to work, since this introduces
17624 // a refinement of face ##### with both
17625 // cut_x and cut_y, which is not possible:
17626 //
17627 // / / /
17628 // / / /
17629 // *-------*-------*
17630 // | | |
17631 // | | | /
17632 // | | |/
17633 // *-------*-------*
17634 // | | |
17635 // | | | /
17636 // | | |/
17637 // *-------*-------*
17638 //
17639 //
17640 // *---------------*
17641 // /| /|
17642 // / *---------------*
17643 // /| /|
17644 // *---------------*
17645 // /| /|
17646 // / | / |
17647 // | |
17648 // *---------------*
17649 // / /
17650 // / /
17651 //
17652 // thus, in this case we also need to refine
17653 // our current cell in the new direction:
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 // / /
17679
17680 std::pair<unsigned int, unsigned int>
17681 nb_indices =
17682 has_periodic_neighbor ?
17683 cell
17684 ->periodic_neighbor_of_coarser_periodic_neighbor(
17685 i) :
17686 cell->neighbor_of_coarser_neighbor(i);
17687 unsigned int refined_along_x = 0,
17688 refined_along_y = 0,
17689 to_be_refined_along_x = 0,
17690 to_be_refined_along_y = 0;
17691
17692 const int this_face_index =
17693 cell->face_index(i);
17694
17695 // step 1: detect, along which axis the face
17696 // is currently refined
17697
17698 // first, we need an iterator pointing to
17699 // the parent face. This requires a slight
17700 // detour in case the neighbor is behind a
17701 // periodic face.
17702 const auto parent_face = [&]() {
17703 if (has_periodic_neighbor)
17704 {
17705 const auto neighbor =
17706 cell->periodic_neighbor(i);
17707 const auto parent_face_no =
17708 neighbor
17709 ->periodic_neighbor_of_periodic_neighbor(
17710 nb_indices.first);
17711 auto parent =
17712 neighbor->periodic_neighbor(
17713 nb_indices.first);
17714 return parent->face(parent_face_no);
17715 }
17716 else
17717 return cell->neighbor(i)->face(
17718 nb_indices.first);
17719 }();
17720
17721 if ((this_face_index ==
17722 parent_face->child_index(0)) ||
17723 (this_face_index ==
17724 parent_face->child_index(1)))
17725 {
17726 // this might be an
17727 // anisotropic child. get the
17728 // face refine case of the
17729 // neighbors face and count
17730 // refinements in x and y
17731 // direction.
17732 RefinementCase<dim - 1> frc =
17733 parent_face->refinement_case();
17735 ++refined_along_x;
17737 ++refined_along_y;
17738 }
17739 else
17740 // this has to be an isotropic
17741 // child
17742 {
17743 ++refined_along_x;
17744 ++refined_along_y;
17745 }
17746 // step 2: detect, along which axis the face
17747 // has to be refined given the current
17748 // refine flag
17749 RefinementCase<dim - 1> flagged_frc =
17751 cell->refine_flag_set(),
17752 i,
17753 cell->face_orientation(i),
17754 cell->face_flip(i),
17755 cell->face_rotation(i));
17756 if (flagged_frc &
17758 ++to_be_refined_along_x;
17759 if (flagged_frc &
17761 ++to_be_refined_along_y;
17762
17763 // step 3: set the refine flag of the
17764 // (coarser and active) neighbor.
17765 if ((smooth_grid &
17766 allow_anisotropic_smoothing) ||
17767 cell->neighbor_or_periodic_neighbor(i)
17768 ->refine_flag_set())
17769 {
17770 if (refined_along_x +
17771 to_be_refined_along_x >
17772 1)
17773 changed |=
17774 cell
17775 ->neighbor_or_periodic_neighbor(i)
17776 ->flag_for_face_refinement(
17777 nb_indices.first,
17778 RefinementCase<dim -
17779 1>::cut_axis(0));
17780 if (refined_along_y +
17781 to_be_refined_along_y >
17782 1)
17783 changed |=
17784 cell
17785 ->neighbor_or_periodic_neighbor(i)
17786 ->flag_for_face_refinement(
17787 nb_indices.first,
17788 RefinementCase<dim -
17789 1>::cut_axis(1));
17790 }
17791 else
17792 {
17793 if (cell
17794 ->neighbor_or_periodic_neighbor(i)
17795 ->refine_flag_set() !=
17798 changed = true;
17799 cell->neighbor_or_periodic_neighbor(i)
17800 ->set_refine_flag();
17801 }
17802
17803 // step 4: if necessary (see above) add to
17804 // the refine flag of the current cell
17805 cell_iterator nb =
17806 cell->neighbor_or_periodic_neighbor(i);
17807 RefinementCase<dim - 1> nb_frc =
17809 nb->refine_flag_set(),
17810 nb_indices.first,
17811 nb->face_orientation(nb_indices.first),
17812 nb->face_flip(nb_indices.first),
17813 nb->face_rotation(nb_indices.first));
17814 if ((nb_frc & RefinementCase<dim>::cut_x) &&
17815 !((refined_along_x != 0u) ||
17816 (to_be_refined_along_x != 0u)))
17817 changed |= cell->flag_for_face_refinement(
17818 i,
17820 if ((nb_frc & RefinementCase<dim>::cut_y) &&
17821 !((refined_along_y != 0u) ||
17822 (to_be_refined_along_y != 0u)))
17823 changed |= cell->flag_for_face_refinement(
17824 i,
17826 }
17827 } // if neighbor is coarser
17828 else // -> now the neighbor is not coarser
17829 {
17830 cell->neighbor_or_periodic_neighbor(i)
17831 ->clear_coarsen_flag();
17832 const unsigned int nb_nb =
17833 has_periodic_neighbor ?
17834 cell
17835 ->periodic_neighbor_of_periodic_neighbor(
17836 i) :
17837 cell->neighbor_of_neighbor(i);
17838 const cell_iterator neighbor =
17839 cell->neighbor_or_periodic_neighbor(i);
17840 RefinementCase<dim - 1> face_ref_case =
17842 neighbor->refine_flag_set(),
17843 nb_nb,
17844 neighbor->face_orientation(nb_nb),
17845 neighbor->face_flip(nb_nb),
17846 neighbor->face_rotation(nb_nb));
17847 RefinementCase<dim - 1> needed_face_ref_case =
17849 cell->refine_flag_set(),
17850 i,
17851 cell->face_orientation(i),
17852 cell->face_flip(i),
17853 cell->face_rotation(i));
17854 // if the neighbor wants to refine the
17855 // face with cut_x and we want cut_y
17856 // or vice versa, we have to refine
17857 // isotropically at the given face
17858 if ((face_ref_case ==
17860 needed_face_ref_case ==
17862 (face_ref_case ==
17864 needed_face_ref_case ==
17866 {
17867 changed = cell->flag_for_face_refinement(
17868 i, face_ref_case);
17869 neighbor->flag_for_face_refinement(
17870 nb_nb, needed_face_ref_case);
17871 }
17872 }
17873 }
17874 else //-> the neighbor is not active
17875 {
17876 RefinementCase<dim - 1>
17877 face_ref_case = cell->face(i)->refinement_case(),
17878 needed_face_ref_case =
17880 cell->refine_flag_set(),
17881 i,
17882 cell->face_orientation(i),
17883 cell->face_flip(i),
17884 cell->face_rotation(i));
17885 // if the face is refined with cut_x and
17886 // we want cut_y or vice versa, we have to
17887 // refine isotropically at the given face
17888 if ((face_ref_case == RefinementCase<dim>::cut_x &&
17889 needed_face_ref_case ==
17891 (face_ref_case == RefinementCase<dim>::cut_y &&
17892 needed_face_ref_case ==
17894 changed =
17895 cell->flag_for_face_refinement(i,
17896 face_ref_case);
17897 }
17898 }
17899 }
17900 }
17901 }
17902
17903 //------------------------------------
17904 // STEP 7:
17905 // take care that no double refinement is done at each line in 3d or
17906 // higher dimensions.
17907 this->policy->prepare_refinement_dim_dependent(*this);
17908
17909 //------------------------------------
17910 // STEP 8:
17911 // make sure that all children of each cell are either flagged for
17912 // coarsening or none of the children is
17913 fix_coarsen_flags();
17914
17915 // get the refinement and coarsening flags
17916 auto coarsen_flags_after_loop =
17917 internal::extract_raw_coarsen_flags(levels);
17918 auto refine_flags_after_loop = internal::extract_raw_refine_flags(levels);
17919
17920 // find out whether something was changed in this loop
17921 mesh_changed_in_this_loop =
17922 ((coarsen_flags_before_loop != coarsen_flags_after_loop) ||
17923 (refine_flags_before_loop != refine_flags_after_loop));
17924
17925 // set the flags for the next loop already
17926 coarsen_flags_before_loop.swap(coarsen_flags_after_loop);
17927 refine_flags_before_loop.swap(refine_flags_after_loop);
17928 }
17929 while (mesh_changed_in_this_loop);
17930
17931
17932 // find out whether something was really changed in this
17933 // function. Note that @p{..._flags_before_loop} represents the state
17934 // after the last loop, i.e., the present state
17935 return ((coarsen_flags_before != coarsen_flags_before_loop) ||
17936 (refine_flags_before != refine_flags_before_loop));
17937}
17938
17939
17940
17941template <int dim, int spacedim>
17944 const unsigned int magic_number1,
17945 const std::vector<bool> &v,
17946 const unsigned int magic_number2,
17947 std::ostream &out)
17948{
17949 const unsigned int N = v.size();
17950 unsigned char *flags = new unsigned char[N / 8 + 1];
17951 for (unsigned int i = 0; i < N / 8 + 1; ++i)
17952 flags[i] = 0;
17953
17954 for (unsigned int position = 0; position < N; ++position)
17955 flags[position / 8] |= (v[position] ? (1 << (position % 8)) : 0);
17956
17957 AssertThrow(out.fail() == false, ExcIO());
17958
17959 // format:
17960 // 0. magic number
17961 // 1. number of flags
17962 // 2. the flags
17963 // 3. magic number
17964 out << magic_number1 << ' ' << N << std::endl;
17965 for (unsigned int i = 0; i < N / 8 + 1; ++i)
17966 out << static_cast<unsigned int>(flags[i]) << ' ';
17967
17968 out << std::endl << magic_number2 << std::endl;
17969
17970 delete[] flags;
17971
17972 AssertThrow(out.fail() == false, ExcIO());
17973}
17974
17975
17976template <int dim, int spacedim>
17979 const unsigned int magic_number1,
17980 std::vector<bool> &v,
17981 const unsigned int magic_number2,
17982 std::istream &in)
17983{
17984 AssertThrow(in.fail() == false, ExcIO());
17985
17986 unsigned int magic_number;
17987 in >> magic_number;
17988 AssertThrow(magic_number == magic_number1, ExcGridReadError());
17989
17990 unsigned int N;
17991 in >> N;
17992 v.resize(N);
17993
17994 unsigned char *flags = new unsigned char[N / 8 + 1];
17995 unsigned short int tmp;
17996 for (unsigned int i = 0; i < N / 8 + 1; ++i)
17997 {
17998 in >> tmp;
17999 flags[i] = tmp;
18000 }
18001
18002 for (unsigned int position = 0; position != N; ++position)
18003 v[position] = ((flags[position / 8] & (1 << (position % 8))) != 0);
18004
18005 in >> magic_number;
18006 AssertThrow(magic_number == magic_number2, ExcGridReadError());
18007
18008 delete[] flags;
18009
18010 AssertThrow(in.fail() == false, ExcIO());
18011}
18012
18013
18014
18015template <int dim, int spacedim>
18018{
18019 std::size_t mem = 0;
18020 mem += sizeof(MeshSmoothing);
18021 mem += MemoryConsumption::memory_consumption(reference_cells);
18022 mem += MemoryConsumption::memory_consumption(periodic_face_pairs_level_0);
18024 for (const auto &level : levels)
18027 mem += MemoryConsumption::memory_consumption(vertices_used);
18028 mem += sizeof(manifolds);
18029 mem += sizeof(smooth_grid);
18030 mem += MemoryConsumption::memory_consumption(number_cache);
18031 mem += sizeof(faces);
18032 if (faces)
18034
18035 return mem;
18036}
18037
18038
18039
18040template <int dim, int spacedim>
18043 default;
18044
18045#endif
18046
18047// explicit instantiations
18048#include "grid/tria.inst"
18049
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:63
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:35
constexpr bool running_in_debug_mode()
Definition config.h:73
#define DEAL_II_CXX20_REQUIRES(condition)
Definition config.h:242
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:36
#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 ReferenceCell Triangle
constexpr ReferenceCell Hexahedron
constexpr ReferenceCell Invalid
constexpr unsigned int max_n_faces()
constexpr ReferenceCell Quadrilateral
constexpr ReferenceCell Tetrahedron
constexpr 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:14911
const Manifold< dim, spacedim > & get_default_flat_manifold()
Definition tria.cc:12008
unsigned int n_cells(const internal::TriangulationImplementation::NumberCache< 1 > &c)
Definition tria.cc:14904
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:269
constexpr unsigned int invalid_unsigned_int
Definition types.h:238
constexpr types::boundary_id internal_face_boundary_id
Definition types.h:329
constexpr types::manifold_id flat_manifold_id
Definition types.h:342
constexpr types::geometric_orientation reverse_line_orientation
Definition types.h:365
constexpr types::subdomain_id invalid_subdomain_id
Definition types.h:381
constexpr types::geometric_orientation default_geometric_orientation
Definition types.h:352
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:173
unsigned char geometric_orientation
Definition types.h:40
unsigned int boundary_id
Definition types.h:161
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:11890
static void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &)
Definition tria.cc:11980
static Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:11971
static bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &)
Definition tria.cc:11996
static void update_neighbors(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:11894
static void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:11988
static void delete_children(Triangulation< dim, spacedim > &, typename Triangulation< dim, spacedim >::cell_iterator &, std::vector< unsigned int > &, std::vector< unsigned int > &)
Definition tria.cc:11960
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:11497
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:11585
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:7124
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:11504
static bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell)
Definition tria.cc:11818
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:11595
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