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