deal.II version GIT relicensing-2289-g1e5549a87a 2024-12-21 21:30: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>
36
37#include <boost/archive/text_iarchive.hpp>
38#include <boost/archive/text_oarchive.hpp>
39
40#include <algorithm>
41#include <array>
42#include <cmath>
43#include <cstdint>
44#include <fstream>
45#include <functional>
46#include <limits>
47#include <list>
48#include <map>
49#include <memory>
50#include <numeric>
51
52
54
55
56namespace internal
57{
58 namespace TriangulationImplementation
59 {
61 : n_levels(0)
62 , n_lines(0)
63 , n_active_lines(0)
64 // all other fields are
65 // default constructed
66 {}
67
68
69
70 std::size_t
72 {
73 std::size_t mem =
78 MemoryConsumption::memory_consumption(n_active_lines_level);
79
80 if (active_cell_index_partitioner)
81 mem += active_cell_index_partitioner->memory_consumption();
82
83 for (const auto &partitioner : level_cell_index_partitioners)
84 if (partitioner)
85 mem += partitioner->memory_consumption();
86
87 return mem;
88 }
89
90
92 : n_quads(0)
93 , n_active_quads(0)
94 // all other fields are
95 // default constructed
96 {}
97
98
99
100 std::size_t
109
110
111
113 : n_hexes(0)
114 , n_active_hexes(0)
115 // all other fields are
116 // default constructed
117 {}
118
119
120
121 std::size_t
130 } // namespace TriangulationImplementation
131
132
133 template <int dim, int spacedim>
136 : variable_size_data_stored(false)
137 {}
138
139
140 template <int dim, int spacedim>
142 void CellAttachedDataSerializer<dim, spacedim>::pack_data(
143 const std::vector<cell_relation_t> &cell_relations,
144 const std::vector<
145 typename internal::CellAttachedData<dim, spacedim>::pack_callback_t>
146 &pack_callbacks_fixed,
147 const std::vector<
148 typename internal::CellAttachedData<dim, spacedim>::pack_callback_t>
149 &pack_callbacks_variable,
150 const MPI_Comm &mpi_communicator)
151 {
152 Assert(src_data_fixed.empty(),
153 ExcMessage("Previously packed data has not been released yet!"));
154 Assert(src_sizes_variable.empty(), ExcInternalError());
155
156 const unsigned int n_callbacks_fixed = pack_callbacks_fixed.size();
157 const unsigned int n_callbacks_variable = pack_callbacks_variable.size();
158
159 // Store information that we packed variable size data in
160 // a member variable for later.
161 variable_size_data_stored = (n_callbacks_variable > 0);
162
163 // If variable transfer is scheduled, we will store the data size that
164 // each variable size callback function writes in this auxiliary
165 // container. The information will be stored by each cell in this vector
166 // temporarily.
167 std::vector<unsigned int> cell_sizes_variable_cumulative(
168 n_callbacks_variable);
169
170 // Prepare the buffer structure, in which each callback function will
171 // store its data for each active cell.
172 // The outmost shell in this container construct corresponds to the
173 // data packed per cell. The next layer resembles the data that
174 // each callback function packs on the corresponding cell. These
175 // buffers are chains of chars stored in an std::vector<char>.
176 // A visualisation of the data structure:
177 /* clang-format off */
178 // | cell_1 | | cell_2 | ...
179 // || callback_1 || callback_2 |...| || callback_1 || callback_2 |...| ...
180 // |||char|char|...|||char|char|...|...| |||char|char|...|||char|char|...|...| ...
181 /* clang-format on */
182 std::vector<std::vector<std::vector<char>>> packed_fixed_size_data(
183 cell_relations.size());
184 std::vector<std::vector<std::vector<char>>> packed_variable_size_data(
185 variable_size_data_stored ? cell_relations.size() : 0);
186
187 //
188 // --------- Pack data for fixed and variable size transfer ---------
189 //
190 // Iterate over all cells, call all callback functions on each cell,
191 // and store their data in the corresponding buffer scope.
192 {
193 auto cell_rel_it = cell_relations.cbegin();
194 auto data_cell_fixed_it = packed_fixed_size_data.begin();
195 auto data_cell_variable_it = packed_variable_size_data.begin();
196 for (; cell_rel_it != cell_relations.cend(); ++cell_rel_it)
197 {
198 const auto &dealii_cell = cell_rel_it->first;
199 const auto &cell_status = cell_rel_it->second;
200
201 // Assertions about the tree structure.
202 switch (cell_status)
203 {
206 // double check the condition that we will only ever attach
207 // data to active cells when we get here
208 Assert(dealii_cell->is_active(), ExcInternalError());
209 break;
210
212 // double check the condition that we will only ever attach
213 // data to cells with children when we get here. however, we
214 // can only tolerate one level of coarsening at a time, so
215 // check that the children are all active
216 Assert(dealii_cell->is_active() == false, ExcInternalError());
217 for (unsigned int c = 0; c < dealii_cell->n_children(); ++c)
218 Assert(dealii_cell->child(c)->is_active(),
220 break;
221
223 // do nothing on invalid cells
224 break;
225
226 default:
228 break;
229 }
230
231 // Reserve memory corresponding to the number of callback
232 // functions that will be called.
233 // If variable size transfer is scheduled, we need to leave
234 // room for an array that holds information about how many
235 // bytes each of the variable size callback functions will
236 // write.
237 // On cells flagged with CellStatus::cell_invalid, only its CellStatus
238 // will be stored.
239 const unsigned int n_fixed_size_data_sets_on_cell =
240 1 + ((cell_status == CellStatus::cell_invalid) ?
241 0 :
242 ((variable_size_data_stored ? 1 : 0) + n_callbacks_fixed));
243 data_cell_fixed_it->resize(n_fixed_size_data_sets_on_cell);
244
245 // We continue with packing all data on this specific cell.
246 auto data_fixed_it = data_cell_fixed_it->begin();
247
248 // First, we pack the CellStatus information.
249 // to get consistent data sizes on each cell for the fixed size
250 // transfer, we won't allow compression
251 *data_fixed_it =
252 Utilities::pack(cell_status, /*allow_compression=*/false);
253 ++data_fixed_it;
254
255 // Proceed with all registered callback functions.
256 // Skip cells with the CellStatus::cell_invalid flag.
257 if (cell_status != CellStatus::cell_invalid)
258 {
259 // Pack fixed size data.
260 for (auto callback_it = pack_callbacks_fixed.cbegin();
261 callback_it != pack_callbacks_fixed.cend();
262 ++callback_it, ++data_fixed_it)
263 {
264 *data_fixed_it = (*callback_it)(dealii_cell, cell_status);
265 }
266
267 // Pack variable size data.
268 // If we store variable size data, we need to transfer
269 // the sizes of each corresponding callback function
270 // via fixed size transfer as well.
271 if (variable_size_data_stored)
272 {
273 const unsigned int n_variable_size_data_sets_on_cell =
274 ((cell_status == CellStatus::cell_invalid) ?
275 0 :
276 n_callbacks_variable);
277 data_cell_variable_it->resize(
278 n_variable_size_data_sets_on_cell);
279
280 auto callback_it = pack_callbacks_variable.cbegin();
281 auto data_variable_it = data_cell_variable_it->begin();
282 auto sizes_variable_it =
283 cell_sizes_variable_cumulative.begin();
284 for (; callback_it != pack_callbacks_variable.cend();
285 ++callback_it, ++data_variable_it, ++sizes_variable_it)
286 {
287 *data_variable_it =
288 (*callback_it)(dealii_cell, cell_status);
289
290 // Store data sizes for each callback function first.
291 // Make it cumulative below.
292 *sizes_variable_it = data_variable_it->size();
293 }
294
295 // Turn size vector into its cumulative representation.
296 std::partial_sum(cell_sizes_variable_cumulative.begin(),
297 cell_sizes_variable_cumulative.end(),
298 cell_sizes_variable_cumulative.begin());
299
300 // Serialize cumulative variable size vector
301 // value-by-value. This way we can circumvent the overhead
302 // of storing the container object as a whole, since we
303 // know its size by the number of registered callback
304 // functions.
305 data_fixed_it->resize(n_callbacks_variable *
306 sizeof(unsigned int));
307 for (unsigned int i = 0; i < n_callbacks_variable; ++i)
308 std::memcpy(&(data_fixed_it->at(i * sizeof(unsigned int))),
309 &(cell_sizes_variable_cumulative.at(i)),
310 sizeof(unsigned int));
311
312 ++data_fixed_it;
313 }
314
315 // Double check that we packed everything we wanted
316 // in the fixed size buffers.
317 Assert(data_fixed_it == data_cell_fixed_it->end(),
319 }
320
321 ++data_cell_fixed_it;
322
323 // Increment the variable size data iterator
324 // only if we actually pack this kind of data
325 // to avoid getting out of bounds.
326 if (variable_size_data_stored)
327 ++data_cell_variable_it;
328 } // loop over cell_relations
329 }
330
331 //
332 // ----------- Gather data sizes for fixed size transfer ------------
333 //
334 // Generate a vector which stores the sizes of each callback function,
335 // including the packed CellStatus transfer.
336 // Find the very first cell that we wrote to with all callback
337 // functions (i.e. a cell that was not flagged with
338 // CellStatus::cell_invalid) and store the sizes of each buffer.
339 //
340 // To deal with the case that at least one of the processors does not
341 // own any cell at all, we will exchange the information about the data
342 // sizes among them later. The code in between is still well-defined,
343 // since the following loops will be skipped.
344 std::vector<unsigned int> local_sizes_fixed(
345 1 + n_callbacks_fixed + (variable_size_data_stored ? 1 : 0));
346 for (const auto &data_cell : packed_fixed_size_data)
347 {
348 if (data_cell.size() == local_sizes_fixed.size())
349 {
350 auto sizes_fixed_it = local_sizes_fixed.begin();
351 auto data_fixed_it = data_cell.cbegin();
352 for (; data_fixed_it != data_cell.cend();
353 ++data_fixed_it, ++sizes_fixed_it)
354 {
355 *sizes_fixed_it = data_fixed_it->size();
356 }
357
358 break;
359 }
360 }
361
362 // Check if all cells have valid sizes.
363 for (auto data_cell_fixed_it = packed_fixed_size_data.cbegin();
364 data_cell_fixed_it != packed_fixed_size_data.cend();
365 ++data_cell_fixed_it)
366 {
367 Assert((data_cell_fixed_it->size() == 1) ||
368 (data_cell_fixed_it->size() == local_sizes_fixed.size()),
370 }
371
372 // Share information about the packed data sizes
373 // of all callback functions across all processors, in case one
374 // of them does not own any cells at all.
375 std::vector<unsigned int> global_sizes_fixed(local_sizes_fixed.size());
376 Utilities::MPI::max(local_sizes_fixed,
377 mpi_communicator,
378 global_sizes_fixed);
379
380 // Construct cumulative sizes, since this is the only information
381 // we need from now on.
382 sizes_fixed_cumulative.resize(global_sizes_fixed.size());
383 std::partial_sum(global_sizes_fixed.begin(),
384 global_sizes_fixed.end(),
385 sizes_fixed_cumulative.begin());
386
387 //
388 // ---------- Gather data sizes for variable size transfer ----------
389 //
390 if (variable_size_data_stored)
391 {
392 src_sizes_variable.reserve(packed_variable_size_data.size());
393 for (const auto &data_cell : packed_variable_size_data)
394 {
395 int variable_data_size_on_cell = 0;
396
397 for (const auto &data : data_cell)
398 variable_data_size_on_cell += data.size();
399
400 src_sizes_variable.push_back(variable_data_size_on_cell);
401 }
402 }
403
404 //
405 // ------------------------ Build buffers ---------------------------
406 //
407 const unsigned int expected_size_fixed =
408 cell_relations.size() * sizes_fixed_cumulative.back();
409 const unsigned int expected_size_variable =
410 std::accumulate(src_sizes_variable.begin(),
411 src_sizes_variable.end(),
412 std::vector<int>::size_type(0));
413
414 // Move every piece of packed fixed size data into the consecutive
415 // buffer.
416 src_data_fixed.reserve(expected_size_fixed);
417 for (const auto &data_cell_fixed : packed_fixed_size_data)
418 {
419 // Move every fraction of packed data into the buffer
420 // reserved for this particular cell.
421 for (const auto &data_fixed : data_cell_fixed)
422 std::move(data_fixed.begin(),
423 data_fixed.end(),
424 std::back_inserter(src_data_fixed));
425
426 // If we only packed the CellStatus information
427 // (i.e. encountered a cell flagged CellStatus::cell_invalid),
428 // fill the remaining space with invalid entries.
429 // We can skip this if there is nothing else to pack.
430 if ((data_cell_fixed.size() == 1) &&
431 (sizes_fixed_cumulative.size() > 1))
432 {
433 const std::size_t bytes_skipped =
434 sizes_fixed_cumulative.back() - sizes_fixed_cumulative.front();
435
436 src_data_fixed.insert(src_data_fixed.end(),
437 bytes_skipped,
438 static_cast<char>(-1)); // invalid_char
440 }
441
442 // Move every piece of packed variable size data into the consecutive
443 // buffer.
444 if (variable_size_data_stored)
445 {
446 src_data_variable.reserve(expected_size_variable);
447 for (const auto &data_cell : packed_variable_size_data)
448 {
449 // Move every fraction of packed data into the buffer
450 // reserved for this particular cell.
451 for (const auto &data : data_cell)
452 std::move(data.begin(),
453 data.end(),
454 std::back_inserter(src_data_variable));
455 }
456 }
457
458 // Double check that we packed everything correctly.
459 Assert(src_data_fixed.size() == expected_size_fixed, ExcInternalError());
460 Assert(src_data_variable.size() == expected_size_variable,
462 }
464
465
466 template <int dim, int spacedim>
468 void CellAttachedDataSerializer<dim, spacedim>::unpack_cell_status(
469 std::vector<
470 typename CellAttachedDataSerializer<dim, spacedim>::cell_relation_t>
471 &cell_relations) const
472 {
473 Assert(sizes_fixed_cumulative.size() > 0,
474 ExcMessage("No data has been packed!"));
475 if (cell_relations.size() > 0)
476 {
477 Assert(dest_data_fixed.size() > 0,
478 ExcMessage("No data has been received!"));
479 }
480
481 // Size of CellStatus object that will be unpacked on each cell.
482 const unsigned int size = sizes_fixed_cumulative.front();
483
484 // Iterate over all cells and overwrite the CellStatus
485 // information from the transferred data.
486 // Proceed buffer iterator position to next cell after
487 // each iteration.
488 auto cell_rel_it = cell_relations.begin();
489 auto dest_fixed_it = dest_data_fixed.cbegin();
490 for (; cell_rel_it != cell_relations.end();
491 ++cell_rel_it, dest_fixed_it += sizes_fixed_cumulative.back())
492 {
493 cell_rel_it->second = // cell_status
494 Utilities::unpack<CellStatus>(dest_fixed_it,
495 dest_fixed_it + size,
496 /*allow_compression=*/false);
497 }
498 }
499
500
501
502 template <int dim, int spacedim>
504 void CellAttachedDataSerializer<dim, spacedim>::unpack_data(
505 const std::vector<
506 typename CellAttachedDataSerializer<dim, spacedim>::cell_relation_t>
507 &cell_relations,
508 const unsigned int handle,
509 const std::function<
510 void(const cell_iterator &,
511 const CellStatus &,
512 const boost::iterator_range<std::vector<char>::const_iterator> &)>
513 &unpack_callback) const
514 {
515 // We decode the handle returned by register_data_attach() back into
516 // a format we can use. All even handles belong to those callback
517 // functions which write/read variable size data, all odd handles
518 // interact with fixed size buffers.
519 const bool callback_variable_transfer = (handle % 2 == 0);
520 const unsigned int callback_index = handle / 2;
521
522 // Cells will always receive fixed size data (i.e., CellStatus
523 // information), but not necessarily variable size data (e.g., with a
524 // ParticleHandler a cell might not contain any particle at all).
525 // Thus it is sufficient to check if fixed size data has been received.
526 Assert(sizes_fixed_cumulative.size() > 0,
527 ExcMessage("No data has been packed!"));
528 if (cell_relations.size() > 0)
529 {
530 Assert(dest_data_fixed.size() > 0,
531 ExcMessage("No data has been received!"));
532 }
533
534 std::vector<char>::const_iterator dest_data_it;
535 std::vector<char>::const_iterator dest_sizes_cell_it;
536
537 // Depending on whether our callback function unpacks fixed or
538 // variable size data, we have to pursue different approaches
539 // to localize the correct fraction of the buffer from which
540 // we are allowed to read.
541 unsigned int offset = numbers::invalid_unsigned_int;
542 unsigned int size = numbers::invalid_unsigned_int;
543 unsigned int data_increment = numbers::invalid_unsigned_int;
544
545 if (callback_variable_transfer)
546 {
547 // For the variable size data, we need to extract the
548 // data size from the fixed size buffer on each cell.
549 //
550 // We packed this information last, so the last packed
551 // object in the fixed size buffer corresponds to the
552 // variable data sizes.
553 //
554 // The last entry of sizes_fixed_cumulative corresponds
555 // to the size of all fixed size data packed on the cell.
556 // To get the offset for the last packed object, we need
557 // to get the next-to-last entry.
558 const unsigned int offset_variable_data_sizes =
559 sizes_fixed_cumulative[sizes_fixed_cumulative.size() - 2];
560
561 // This iterator points to the data size that the
562 // callback_function packed for each specific cell.
563 // Adjust buffer iterator to the offset of the callback
564 // function so that we only have to advance its position
565 // to the next cell after each iteration.
566 dest_sizes_cell_it = dest_data_fixed.cbegin() +
567 offset_variable_data_sizes +
568 callback_index * sizeof(unsigned int);
569
570 // Let the data iterator point to the correct buffer.
571 dest_data_it = dest_data_variable.cbegin();
572 }
573 else
574 {
575 // For the fixed size data, we can get the information about
576 // the buffer location on each cell directly from the
577 // sizes_fixed_cumulative vector.
578 offset = sizes_fixed_cumulative[callback_index];
579 size = sizes_fixed_cumulative[callback_index + 1] - offset;
580 data_increment = sizes_fixed_cumulative.back();
581
582 // Let the data iterator point to the correct buffer.
583 // Adjust buffer iterator to the offset of the callback
584 // function so that we only have to advance its position
585 // to the next cell after each iteration.
586 if (cell_relations.begin() != cell_relations.end())
587 dest_data_it = dest_data_fixed.cbegin() + offset;
588 }
589
590 // Iterate over all cells and unpack the transferred data.
591 auto cell_rel_it = cell_relations.begin();
592 auto dest_sizes_it = dest_sizes_variable.cbegin();
593 for (; cell_rel_it != cell_relations.end(); ++cell_rel_it)
594 {
595 const auto &dealii_cell = cell_rel_it->first;
596 const auto &cell_status = cell_rel_it->second;
597
598 if (callback_variable_transfer)
599 {
600 // Update the increment according to the whole data size
601 // of the current cell.
602 data_increment = *dest_sizes_it;
603
604 if (cell_status != CellStatus::cell_invalid)
605 {
606 // Extract the corresponding values for offset and size from
607 // the cumulative sizes array stored in the fixed size
608 // buffer.
609 if (callback_index == 0)
610 offset = 0;
611 else
612 std::memcpy(&offset,
613 &(*(dest_sizes_cell_it - sizeof(unsigned int))),
614 sizeof(unsigned int));
615
616 std::memcpy(&size,
617 &(*dest_sizes_cell_it),
618 sizeof(unsigned int));
619
620 size -= offset;
621
622 // Move the data iterator to the corresponding position
623 // of the callback function and adjust the increment
624 // accordingly.
625 dest_data_it += offset;
626 data_increment -= offset;
627 }
628
629 // Advance data size iterators to the next cell, avoid iterating
630 // past the end of dest_sizes_cell_it
631 if (cell_rel_it != cell_relations.end() - 1)
632 dest_sizes_cell_it += sizes_fixed_cumulative.back();
633 ++dest_sizes_it;
634 }
635
636 switch (cell_status)
637 {
640 unpack_callback(dealii_cell,
641 cell_status,
642 boost::make_iterator_range(dest_data_it,
643 dest_data_it + size));
644 break;
645
647 unpack_callback(dealii_cell->parent(),
648 cell_status,
649 boost::make_iterator_range(dest_data_it,
650 dest_data_it + size));
651 break;
652
654 // Skip this cell.
655 break;
656
657 default:
659 break;
660 }
661
662 if (cell_rel_it != cell_relations.end() - 1)
663 dest_data_it += data_increment;
664 }
665 }
666
667
668
669 template <int dim, int spacedim>
671 void CellAttachedDataSerializer<dim, spacedim>::save(
672 const unsigned int global_first_cell,
673 const unsigned int global_num_cells,
674 const std::string &file_basename,
675 const MPI_Comm &mpi_communicator) const
676 {
677 Assert(sizes_fixed_cumulative.size() > 0,
678 ExcMessage("No data has been packed!"));
679
680#ifdef DEAL_II_WITH_MPI
681 // Large fractions of this function have been copied from
682 // DataOutInterface::write_vtu_in_parallel.
683 // TODO: Write general MPIIO interface.
684
685 const unsigned int myrank =
686 Utilities::MPI::this_mpi_process(mpi_communicator);
687 const unsigned int mpisize =
688 Utilities::MPI::n_mpi_processes(mpi_communicator);
689
690 if (mpisize > 1)
691 {
692 const unsigned int bytes_per_cell = sizes_fixed_cumulative.back();
693
694 //
695 // ---------- Fixed size data ----------
696 //
697 {
698 const std::string fname_fixed =
699 std::string(file_basename) + "_fixed.data";
700
701 MPI_Info info;
702 int ierr = MPI_Info_create(&info);
703 AssertThrowMPI(ierr);
704
705 MPI_File fh;
706 ierr = MPI_File_open(mpi_communicator,
707 fname_fixed.c_str(),
708 MPI_MODE_CREATE | MPI_MODE_WRONLY,
709 info,
710 &fh);
711 AssertThrowMPI(ierr);
712
713 ierr = MPI_File_set_size(fh, 0); // delete the file contents
714 AssertThrowMPI(ierr);
715 // this barrier is necessary, because otherwise others might already
716 // write while one core is still setting the size to zero.
717 ierr = MPI_Barrier(mpi_communicator);
718 AssertThrowMPI(ierr);
719 ierr = MPI_Info_free(&info);
720 AssertThrowMPI(ierr);
721 // ------------------
722
723 // Write cumulative sizes to file.
724 // Since each processor owns the same information about the data
725 // sizes, it is sufficient to let only the first processor perform
726 // this task.
727 if (myrank == 0)
728 {
730 fh,
731 0,
732 sizes_fixed_cumulative.data(),
733 sizes_fixed_cumulative.size(),
734 MPI_UNSIGNED,
735 MPI_STATUS_IGNORE);
736 AssertThrowMPI(ierr);
737 }
738
739 // Write packed data to file simultaneously.
740 const MPI_Offset size_header =
741 sizes_fixed_cumulative.size() * sizeof(unsigned int);
742
743 // Make sure we do the following computation in 64bit integers to be
744 // able to handle 4GB+ files:
745 const MPI_Offset my_global_file_position =
746 size_header +
747 static_cast<MPI_Offset>(global_first_cell) * bytes_per_cell;
748
749 ierr =
751 my_global_file_position,
752 src_data_fixed.data(),
753 src_data_fixed.size(),
754 MPI_BYTE,
755 MPI_STATUS_IGNORE);
756 AssertThrowMPI(ierr);
757
758 ierr = MPI_File_close(&fh);
759 AssertThrowMPI(ierr);
760 }
761
762
763
764 //
765 // ---------- Variable size data ----------
766 //
767 if (variable_size_data_stored)
768 {
769 const std::string fname_variable =
770 std::string(file_basename) + "_variable.data";
771
772 MPI_Info info;
773 int ierr = MPI_Info_create(&info);
774 AssertThrowMPI(ierr);
775
776 MPI_File fh;
777 ierr = MPI_File_open(mpi_communicator,
778 fname_variable.c_str(),
779 MPI_MODE_CREATE | MPI_MODE_WRONLY,
780 info,
781 &fh);
782 AssertThrowMPI(ierr);
783
784 ierr = MPI_File_set_size(fh, 0); // delete the file contents
785 AssertThrowMPI(ierr);
786 // this barrier is necessary, because otherwise others might already
787 // write while one core is still setting the size to zero.
788 ierr = MPI_Barrier(mpi_communicator);
789 AssertThrowMPI(ierr);
790 ierr = MPI_Info_free(&info);
791 AssertThrowMPI(ierr);
792
793 // Write sizes of each cell into file simultaneously.
794 {
795 const MPI_Offset my_global_file_position =
796 static_cast<MPI_Offset>(global_first_cell) *
797 sizeof(unsigned int);
798
799 // It is very unlikely that a single process has more than
800 // 2 billion cells, but we might as well check.
801 AssertThrow(src_sizes_variable.size() <
802 static_cast<std::size_t>(
803 std::numeric_limits<int>::max()),
805
807 fh,
808 my_global_file_position,
809 src_sizes_variable.data(),
810 src_sizes_variable.size(),
811 MPI_INT,
812 MPI_STATUS_IGNORE);
813 AssertThrowMPI(ierr);
814 }
815
816 // Gather size of data in bytes we want to store from this
817 // processor and compute the prefix sum. We do this in 64 bit
818 // to avoid overflow for files larger than 4GB:
819 const std::uint64_t size_on_proc = src_data_variable.size();
820 std::uint64_t prefix_sum = 0;
821 ierr = MPI_Exscan(&size_on_proc,
822 &prefix_sum,
823 1,
824 MPI_UINT64_T,
825 MPI_SUM,
826 mpi_communicator);
827 AssertThrowMPI(ierr);
828
829 const MPI_Offset my_global_file_position =
830 static_cast<MPI_Offset>(global_num_cells) * sizeof(unsigned int) +
831 prefix_sum;
832
833 // Write data consecutively into file.
835 fh,
836 my_global_file_position,
837 src_data_variable.data(),
838 src_data_variable.size(),
839 MPI_BYTE,
840 MPI_STATUS_IGNORE);
841 AssertThrowMPI(ierr);
842
843
844 ierr = MPI_File_close(&fh);
845 AssertThrowMPI(ierr);
846 }
847 } // if (mpisize > 1)
848 else
849#endif
850 {
851 (void)global_first_cell;
852 (void)global_num_cells;
853 (void)mpi_communicator;
854
855 //
856 // ---------- Fixed size data ----------
857 //
858 {
859 const std::string fname_fixed =
860 std::string(file_basename) + "_fixed.data";
861
862 std::ofstream file(fname_fixed, std::ios::binary | std::ios::out);
863 AssertThrow(file.fail() == false, ExcIO());
864
865 // Write header data.
866 file.write(reinterpret_cast<const char *>(
867 sizes_fixed_cumulative.data()),
868 sizes_fixed_cumulative.size() * sizeof(unsigned int));
869
870 // Write packed data.
871 file.write(reinterpret_cast<const char *>(src_data_fixed.data()),
872 src_data_fixed.size() * sizeof(char));
873 }
874
875 //
876 // ---------- Variable size data ----------
877 //
878 if (variable_size_data_stored)
879 {
880 const std::string fname_variable =
881 std::string(file_basename) + "_variable.data";
882
883 std::ofstream file(fname_variable,
884 std::ios::binary | std::ios::out);
885 AssertThrow(file.fail() == false, ExcIO());
886
887 // Write header data.
888 file.write(reinterpret_cast<const char *>(
889 src_sizes_variable.data()),
890 src_sizes_variable.size() * sizeof(int));
891
892 // Write packed data.
893 file.write(reinterpret_cast<const char *>(src_data_variable.data()),
894 src_data_variable.size() * sizeof(char));
895 }
896 }
897 }
898
899
900 template <int dim, int spacedim>
902 void CellAttachedDataSerializer<dim, spacedim>::load(
903 const unsigned int global_first_cell,
904 const unsigned int global_num_cells,
905 const unsigned int local_num_cells,
906 const std::string &file_basename,
907 const unsigned int n_attached_deserialize_fixed,
908 const unsigned int n_attached_deserialize_variable,
909 const MPI_Comm &mpi_communicator)
910 {
911 Assert(dest_data_fixed.empty(),
912 ExcMessage("Previously loaded data has not been released yet!"));
913
914 variable_size_data_stored = (n_attached_deserialize_variable > 0);
915
916#ifdef DEAL_II_WITH_MPI
917 // Large fractions of this function have been copied from
918 // DataOutInterface::write_vtu_in_parallel.
919 // TODO: Write general MPIIO interface.
920
921 const unsigned int mpisize =
922 Utilities::MPI::n_mpi_processes(mpi_communicator);
923
924 if (mpisize > 1)
925 {
926 //
927 // ---------- Fixed size data ----------
928 //
929 {
930 const std::string fname_fixed =
931 std::string(file_basename) + "_fixed.data";
932
933 MPI_Info info;
934 int ierr = MPI_Info_create(&info);
935 AssertThrowMPI(ierr);
936
937 MPI_File fh;
938 ierr = MPI_File_open(
939 mpi_communicator, fname_fixed.c_str(), MPI_MODE_RDONLY, info, &fh);
940 AssertThrowMPI(ierr);
941
942 ierr = MPI_Info_free(&info);
943 AssertThrowMPI(ierr);
944
945 // Read cumulative sizes from file.
946 // Since all processors need the same information about the data
947 // sizes, let each of them retrieve it by reading from the same
948 // location in the file.
949 sizes_fixed_cumulative.resize(1 + n_attached_deserialize_fixed +
950 (variable_size_data_stored ? 1 : 0));
952 fh,
953 0,
954 sizes_fixed_cumulative.data(),
955 sizes_fixed_cumulative.size(),
956 MPI_UNSIGNED,
957 MPI_STATUS_IGNORE);
958 AssertThrowMPI(ierr);
959
960 // Allocate sufficient memory.
961 const unsigned int bytes_per_cell = sizes_fixed_cumulative.back();
962 dest_data_fixed.resize(static_cast<size_t>(local_num_cells) *
963 bytes_per_cell);
964
965 // Read packed data from file simultaneously.
966 const MPI_Offset size_header =
967 sizes_fixed_cumulative.size() * sizeof(unsigned int);
968
969 // Make sure we do the following computation in 64bit integers to be
970 // able to handle 4GB+ files:
971 const MPI_Offset my_global_file_position =
972 size_header +
973 static_cast<MPI_Offset>(global_first_cell) * bytes_per_cell;
974
975 ierr =
977 my_global_file_position,
978 dest_data_fixed.data(),
979 dest_data_fixed.size(),
980 MPI_BYTE,
981 MPI_STATUS_IGNORE);
982 AssertThrowMPI(ierr);
983
984
985 ierr = MPI_File_close(&fh);
986 AssertThrowMPI(ierr);
987 }
988
989 //
990 // ---------- Variable size data ----------
991 //
992 if (variable_size_data_stored)
993 {
994 const std::string fname_variable =
995 std::string(file_basename) + "_variable.data";
996
997 MPI_Info info;
998 int ierr = MPI_Info_create(&info);
999 AssertThrowMPI(ierr);
1000
1001 MPI_File fh;
1002 ierr = MPI_File_open(mpi_communicator,
1003 fname_variable.c_str(),
1004 MPI_MODE_RDONLY,
1005 info,
1006 &fh);
1007 AssertThrowMPI(ierr);
1008
1009 ierr = MPI_Info_free(&info);
1010 AssertThrowMPI(ierr);
1011
1012 // Read sizes of all locally owned cells.
1013 dest_sizes_variable.resize(local_num_cells);
1014
1015 const MPI_Offset my_global_file_position_sizes =
1016 static_cast<MPI_Offset>(global_first_cell) * sizeof(unsigned int);
1017
1019 fh,
1020 my_global_file_position_sizes,
1021 dest_sizes_variable.data(),
1022 dest_sizes_variable.size(),
1023 MPI_INT,
1024 MPI_STATUS_IGNORE);
1025 AssertThrowMPI(ierr);
1026
1027
1028 // Compute my data size in bytes and compute prefix sum. We do this
1029 // in 64 bit to avoid overflow for files larger than 4 GB:
1030 const std::uint64_t size_on_proc =
1031 std::accumulate(dest_sizes_variable.begin(),
1032 dest_sizes_variable.end(),
1033 0ULL);
1034
1035 std::uint64_t prefix_sum = 0;
1036 ierr = MPI_Exscan(&size_on_proc,
1037 &prefix_sum,
1038 1,
1039 MPI_UINT64_T,
1040 MPI_SUM,
1041 mpi_communicator);
1042 AssertThrowMPI(ierr);
1043
1044 const MPI_Offset my_global_file_position =
1045 static_cast<MPI_Offset>(global_num_cells) * sizeof(unsigned int) +
1046 prefix_sum;
1047
1048 dest_data_variable.resize(size_on_proc);
1049
1051 fh,
1052 my_global_file_position,
1053 dest_data_variable.data(),
1054 dest_data_variable.size(),
1055 MPI_BYTE,
1056 MPI_STATUS_IGNORE);
1057 AssertThrowMPI(ierr);
1058
1059 ierr = MPI_File_close(&fh);
1060 AssertThrowMPI(ierr);
1061 }
1062 }
1063 else // if (mpisize > 1)
1064#endif
1065 {
1066 (void)mpi_communicator;
1067 (void)global_first_cell;
1068 (void)global_num_cells;
1069
1070 //
1071 // ---------- Fixed size data ----------
1072 //
1073 {
1074 const std::string fname_fixed =
1075 std::string(file_basename) + "_fixed.data";
1076
1077 std::ifstream file(fname_fixed, std::ios::binary | std::ios::in);
1078 AssertThrow(file.fail() == false, ExcIO());
1079
1080 sizes_fixed_cumulative.resize(1 + n_attached_deserialize_fixed +
1081 (variable_size_data_stored ? 1 : 0));
1082 // Read header data.
1083 file.read(reinterpret_cast<char *>(sizes_fixed_cumulative.data()),
1084 sizes_fixed_cumulative.size() * sizeof(unsigned int));
1085
1086 const unsigned int bytes_per_cell = sizes_fixed_cumulative.back();
1087 dest_data_fixed.resize(static_cast<size_t>(local_num_cells) *
1088 bytes_per_cell);
1089
1090 // Read packed data.
1091 file.read(reinterpret_cast<char *>(dest_data_fixed.data()),
1092 dest_data_fixed.size() * sizeof(char));
1093 }
1094
1095 //
1096 // ---------- Variable size data ----------
1097 //
1098 if (variable_size_data_stored)
1099 {
1100 const std::string fname_variable =
1101 std::string(file_basename) + "_variable.data";
1102
1103 std::ifstream file(fname_variable, std::ios::binary | std::ios::in);
1104 AssertThrow(file.fail() == false, ExcIO());
1105
1106 // Read header data.
1107 dest_sizes_variable.resize(local_num_cells);
1108 file.read(reinterpret_cast<char *>(dest_sizes_variable.data()),
1109 dest_sizes_variable.size() * sizeof(int));
1110
1111 // Read packed data.
1112 const std::uint64_t size =
1113 std::accumulate(dest_sizes_variable.begin(),
1114 dest_sizes_variable.end(),
1115 0ULL);
1116 dest_data_variable.resize(size);
1117 file.read(reinterpret_cast<char *>(dest_data_variable.data()),
1118 dest_data_variable.size() * sizeof(char));
1119 }
1120 }
1121 }
1122
1123
1124 template <int dim, int spacedim>
1126 void CellAttachedDataSerializer<dim, spacedim>::clear()
1127 {
1128 variable_size_data_stored = false;
1129
1130 // free information about data sizes
1131 sizes_fixed_cumulative.clear();
1132 sizes_fixed_cumulative.shrink_to_fit();
1133
1134 // free fixed size transfer data
1135 src_data_fixed.clear();
1136 src_data_fixed.shrink_to_fit();
1137
1138 dest_data_fixed.clear();
1139 dest_data_fixed.shrink_to_fit();
1140
1141 // free variable size transfer data
1142 src_sizes_variable.clear();
1143 src_sizes_variable.shrink_to_fit();
1144
1145 src_data_variable.clear();
1146 src_data_variable.shrink_to_fit();
1147
1148 dest_sizes_variable.clear();
1149 dest_sizes_variable.shrink_to_fit();
1150
1151 dest_data_variable.clear();
1152 dest_data_variable.shrink_to_fit();
1153 }
1154
1155} // namespace internal
1156
1157// anonymous namespace for internal helper functions
1158namespace
1159{
1160 // return whether the given cell is
1161 // patch_level_1, i.e. determine
1162 // whether either all or none of
1163 // its children are further
1164 // refined. this function can only
1165 // be called for non-active cells.
1166 template <int dim, int spacedim>
1167 bool
1168 cell_is_patch_level_1(
1170 {
1171 Assert(cell->is_active() == false, ExcInternalError());
1172
1173 unsigned int n_active_children = 0;
1174 for (unsigned int i = 0; i < cell->n_children(); ++i)
1175 if (cell->child(i)->is_active())
1176 ++n_active_children;
1177
1178 return (n_active_children == 0) ||
1179 (n_active_children == cell->n_children());
1180 }
1181
1182
1183
1184 // return, whether a given @p cell will be
1185 // coarsened, which is the case if all
1186 // children are active and have their coarsen
1187 // flag set. In case only part of the coarsen
1188 // flags are set, remove them.
1189 template <int dim, int spacedim>
1190 bool
1191 cell_will_be_coarsened(
1193 {
1194 // only cells with children should be
1195 // considered for coarsening
1196
1197 if (cell->has_children())
1198 {
1199 unsigned int children_to_coarsen = 0;
1200 const unsigned int n_children = cell->n_children();
1201
1202 for (unsigned int c = 0; c < n_children; ++c)
1203 if (cell->child(c)->is_active() && cell->child(c)->coarsen_flag_set())
1204 ++children_to_coarsen;
1205 if (children_to_coarsen == n_children)
1206 return true;
1207 else
1208 for (unsigned int c = 0; c < n_children; ++c)
1209 if (cell->child(c)->is_active())
1210 cell->child(c)->clear_coarsen_flag();
1211 }
1212 // no children, so no coarsening
1213 // possible. however, no children also
1214 // means that this cell will be in the same
1215 // state as if it had children and was
1216 // coarsened. So, what should we return -
1217 // false or true?
1218 // make sure we do not have to do this at
1219 // all...
1220 Assert(cell->has_children(), ExcInternalError());
1221 // ... and then simply return false
1222 return false;
1223 }
1224
1225
1226 // return, whether the face @p face_no of the
1227 // given @p cell will be refined after the
1228 // current refinement step, considering
1229 // refine and coarsen flags and considering
1230 // only those refinemnts that will be caused
1231 // by the neighboring cell.
1232
1233 // this function is used on both active cells
1234 // and cells with children. on cells with
1235 // children it also of interest to know 'how'
1236 // the face will be refined. thus there is an
1237 // additional third argument @p
1238 // expected_face_ref_case returning just
1239 // that. be aware, that this variable will
1240 // only contain useful information if this
1241 // function is called for an active cell.
1242 //
1243 // thus, this is an internal function, users
1244 // should call one of the two alternatives
1245 // following below.
1246 template <int dim, int spacedim>
1247 bool
1248 face_will_be_refined_by_neighbor_internal(
1250 const unsigned int face_no,
1251 RefinementCase<dim - 1> &expected_face_ref_case)
1252 {
1253 // first of all: set the default value for
1254 // expected_face_ref_case, which is no
1255 // refinement at all
1256 expected_face_ref_case = RefinementCase<dim - 1>::no_refinement;
1257
1258 const typename Triangulation<dim, spacedim>::cell_iterator neighbor =
1259 cell->neighbor(face_no);
1260
1261 // If we are at the boundary, there is no
1262 // neighbor which could refine the face
1263 if (neighbor.state() != IteratorState::valid)
1264 return false;
1265
1266 if (neighbor->has_children())
1267 {
1268 // if the neighbor is refined, it may be
1269 // coarsened. if so, then it won't refine
1270 // the face, no matter what else happens
1271 if (cell_will_be_coarsened(neighbor))
1272 return false;
1273 else
1274 // if the neighbor is refined, then it
1275 // is also refined at our current
1276 // face. It will stay so without
1277 // coarsening, so return true in that
1278 // case.
1279 {
1280 expected_face_ref_case = cell->face(face_no)->refinement_case();
1281 return true;
1282 }
1283 }
1284
1285 // now, the neighbor is not refined, but
1286 // perhaps it will be
1287 const RefinementCase<dim> nb_ref_flag = neighbor->refine_flag_set();
1288 if (nb_ref_flag != RefinementCase<dim>::no_refinement)
1289 {
1290 // now we need to know, which of the
1291 // neighbors faces points towards us
1292 const unsigned int neighbor_neighbor = cell->neighbor_face_no(face_no);
1293 // check, whether the cell will be
1294 // refined in a way that refines our
1295 // face
1296 const RefinementCase<dim - 1> face_ref_case =
1298 nb_ref_flag,
1299 neighbor_neighbor,
1300 neighbor->face_orientation(neighbor_neighbor),
1301 neighbor->face_flip(neighbor_neighbor),
1302 neighbor->face_rotation(neighbor_neighbor));
1303 if (face_ref_case != RefinementCase<dim - 1>::no_refinement)
1304 {
1306 neighbor_face = neighbor->face(neighbor_neighbor);
1307 const int this_face_index = cell->face_index(face_no);
1308
1309 // there are still two basic
1310 // possibilities here: the neighbor
1311 // might be coarser or as coarse
1312 // as we are
1313 if (neighbor_face->index() == this_face_index)
1314 // the neighbor is as coarse as
1315 // we are and will be refined at
1316 // the face of consideration, so
1317 // return true
1318 {
1319 expected_face_ref_case = face_ref_case;
1320 return true;
1321 }
1322 else
1323 {
1324 // the neighbor is coarser.
1325 // this is the most complicated
1326 // case. It might be, that the
1327 // neighbor's face will be
1328 // refined, but that we will
1329 // not see this, as we are
1330 // refined in a similar way.
1331
1332 // so, the neighbor's face must
1333 // have children. check, if our
1334 // cell's face is one of these
1335 // (it could also be a
1336 // grand_child)
1337 for (unsigned int c = 0; c < neighbor_face->n_children(); ++c)
1338 if (neighbor_face->child_index(c) == this_face_index)
1339 {
1340 // if the flagged refine
1341 // case of the face is a
1342 // subset or the same as
1343 // the current refine case,
1344 // then the face, as seen
1345 // from our cell, won't be
1346 // refined by the neighbor
1347 if ((neighbor_face->refinement_case() | face_ref_case) ==
1348 neighbor_face->refinement_case())
1349 return false;
1350 else
1351 {
1352 // if we are active, we
1353 // must be an
1354 // anisotropic child
1355 // and the coming
1356 // face_ref_case is
1357 // isotropic. Thus,
1358 // from our cell we
1359 // will see exactly the
1360 // opposite refine case
1361 // that the face has
1362 // now...
1363 Assert(
1364 face_ref_case ==
1367 expected_face_ref_case =
1368 ~neighbor_face->refinement_case();
1369 return true;
1370 }
1371 }
1372
1373 // so, obviously we were not
1374 // one of the children, but a
1375 // grandchild. This is only
1376 // possible in 3d.
1377 Assert(dim == 3, ExcInternalError());
1378 // In that case, however, no
1379 // matter what the neighbor
1380 // does, it won't be finer
1381 // after the next refinement
1382 // step.
1383 return false;
1384 }
1385 } // if face will be refined
1386 } // if neighbor is flagged for refinement
1387
1388 // no cases left, so the neighbor will not
1389 // refine the face
1390 return false;
1391 }
1392
1393 // version of above function for both active
1394 // and non-active cells
1395 template <int dim, int spacedim>
1396 bool
1397 face_will_be_refined_by_neighbor(
1399 const unsigned int face_no)
1400 {
1401 RefinementCase<dim - 1> dummy = RefinementCase<dim - 1>::no_refinement;
1402 return face_will_be_refined_by_neighbor_internal(cell, face_no, dummy);
1403 }
1404
1405 // version of above function for active cells
1406 // only. Additionally returning the refine
1407 // case (to come) of the face under
1408 // consideration
1409 template <int dim, int spacedim>
1410 bool
1411 face_will_be_refined_by_neighbor(
1413 const unsigned int face_no,
1414 RefinementCase<dim - 1> &expected_face_ref_case)
1415 {
1416 return face_will_be_refined_by_neighbor_internal(cell,
1417 face_no,
1418 expected_face_ref_case);
1419 }
1420
1421
1422
1423 template <int dim, int spacedim>
1424 bool
1425 satisfies_level1_at_vertex_rule(
1427 {
1428 std::vector<unsigned int> min_adjacent_cell_level(
1429 triangulation.n_vertices(), triangulation.n_levels());
1430 std::vector<unsigned int> max_adjacent_cell_level(
1431 triangulation.n_vertices(), 0);
1432
1433 for (const auto &cell : triangulation.active_cell_iterators())
1434 for (const unsigned int v : cell->vertex_indices())
1435 {
1436 min_adjacent_cell_level[cell->vertex_index(v)] =
1437 std::min<unsigned int>(
1438 min_adjacent_cell_level[cell->vertex_index(v)], cell->level());
1439 max_adjacent_cell_level[cell->vertex_index(v)] =
1440 std::max<unsigned int>(
1441 min_adjacent_cell_level[cell->vertex_index(v)], cell->level());
1442 }
1443
1444 for (unsigned int k = 0; k < triangulation.n_vertices(); ++k)
1445 if (triangulation.vertex_used(k))
1446 if (max_adjacent_cell_level[k] - min_adjacent_cell_level[k] > 1)
1447 return false;
1448 return true;
1449 }
1450
1451
1452
1470 template <int dim, int spacedim>
1471 unsigned int
1472 middle_vertex_index(
1474 {
1475 if (line->has_children())
1476 return line->child(0)->vertex_index(1);
1478 }
1479
1480
1481 template <int dim, int spacedim>
1482 unsigned int
1483 middle_vertex_index(
1485 {
1486 switch (static_cast<unsigned char>(quad->refinement_case()))
1487 {
1489 return middle_vertex_index<dim, spacedim>(quad->child(0)->line(1));
1490 break;
1492 return middle_vertex_index<dim, spacedim>(quad->child(0)->line(3));
1493 break;
1495 return quad->child(0)->vertex_index(3);
1496 break;
1497 default:
1498 break;
1499 }
1501 }
1502
1503
1504 template <int dim, int spacedim>
1505 unsigned int
1506 middle_vertex_index(
1508 {
1509 switch (static_cast<unsigned char>(hex->refinement_case()))
1510 {
1512 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(1));
1513 break;
1515 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(3));
1516 break;
1518 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(5));
1519 break;
1521 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(11));
1522 break;
1524 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(5));
1525 break;
1527 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(7));
1528 break;
1530 return hex->child(0)->vertex_index(7);
1531 break;
1532 default:
1533 break;
1534 }
1536 }
1537
1538
1551 template <class TRIANGULATION>
1552 inline typename TRIANGULATION::DistortedCellList
1553 collect_distorted_coarse_cells(const TRIANGULATION &)
1554 {
1555 return typename TRIANGULATION::DistortedCellList();
1556 }
1557
1558
1559
1568 template <int dim>
1570 collect_distorted_coarse_cells(const Triangulation<dim, dim> &triangulation)
1571 {
1572 typename Triangulation<dim, dim>::DistortedCellList distorted_cells;
1573 for (const auto &cell : triangulation.cell_iterators_on_level(0))
1574 {
1576 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1577 vertices[i] = cell->vertex(i);
1578
1581
1582 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1583 if (determinants[i] <=
1584 1e-9 * Utilities::fixed_power<dim>(cell->diameter()))
1585 {
1586 distorted_cells.distorted_cells.push_back(cell);
1587 break;
1588 }
1589 }
1590
1591 return distorted_cells;
1592 }
1593
1594
1601 template <int dim>
1602 bool
1603 has_distorted_children(
1604 const typename Triangulation<dim, dim>::cell_iterator &cell)
1605 {
1606 Assert(cell->has_children(), ExcInternalError());
1607
1608 for (unsigned int c = 0; c < cell->n_children(); ++c)
1609 {
1611 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1612 vertices[i] = cell->child(c)->vertex(i);
1613
1616
1617 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1618 if (determinants[i] <=
1619 1e-9 * Utilities::fixed_power<dim>(cell->child(c)->diameter()))
1620 return true;
1621 }
1622
1623 return false;
1624 }
1625
1626
1634 template <int dim, int spacedim>
1635 bool
1636 has_distorted_children(
1638 {
1639 return false;
1640 }
1641
1642
1643 template <int dim, int spacedim>
1644 void
1645 update_periodic_face_map_recursively(
1646 const typename Triangulation<dim, spacedim>::cell_iterator &cell_1,
1647 const typename Triangulation<dim, spacedim>::cell_iterator &cell_2,
1648 unsigned int n_face_1,
1649 unsigned int n_face_2,
1650 const unsigned char orientation,
1651 typename std::map<
1653 unsigned int>,
1654 std::pair<std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
1655 unsigned int>,
1656 unsigned char>> &periodic_face_map)
1657 {
1658 using FaceIterator = typename Triangulation<dim, spacedim>::face_iterator;
1659 const FaceIterator face_1 = cell_1->face(n_face_1);
1660 const FaceIterator face_2 = cell_2->face(n_face_2);
1661
1662 const unsigned char inverse_orientation =
1663 face_1->reference_cell().get_inverse_combined_orientation(orientation);
1664
1665#ifdef DEBUG
1666 const auto [face_orientation, face_rotation, face_flip] =
1668
1669 Assert((dim != 1) || (face_orientation == true && face_flip == false &&
1670 face_rotation == false),
1671 ExcMessage("The supplied orientation "
1672 "(face_orientation, face_flip, face_rotation) "
1673 "is invalid for 1d"));
1674
1675 Assert((dim != 2) || (face_flip == false && face_rotation == false),
1676 ExcMessage("The supplied orientation "
1677 "(face_orientation, face_flip, face_rotation) "
1678 "is invalid for 2d"));
1679#endif
1680
1681 Assert(face_1 != face_2, ExcMessage("face_1 and face_2 are equal!"));
1682
1683 Assert(face_1->at_boundary() && face_2->at_boundary(),
1684 ExcMessage("Periodic faces must be on the boundary"));
1685
1686 // Check if the requirement that each edge can only have at most one hanging
1687 // node, and as a consequence neighboring cells can differ by at most
1688 // one refinement level is enforced. In 1d, there are no hanging nodes and
1689 // so neighboring cells can differ by more than one refinement level.
1690 Assert(dim == 1 || std::abs(cell_1->level() - cell_2->level()) < 2,
1692
1693 // insert periodic face pair for both cells
1694 using CellFace =
1695 std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
1696 unsigned int>;
1697 const CellFace cell_face_1(cell_1, n_face_1);
1698 const CellFace cell_face_2(cell_2, n_face_2);
1699 const std::pair<CellFace, unsigned char> cell_face_orientation_2(
1700 cell_face_2, orientation);
1701
1702 const std::pair<CellFace, std::pair<CellFace, unsigned char>>
1703 periodic_faces(cell_face_1, cell_face_orientation_2);
1704
1705 // Only one periodic neighbor is allowed
1706 Assert(periodic_face_map.count(cell_face_1) == 0, ExcInternalError());
1707 periodic_face_map.insert(periodic_faces);
1708
1709 if (dim == 1)
1710 {
1711 if (cell_1->has_children())
1712 {
1713 if (cell_2->has_children())
1714 {
1715 update_periodic_face_map_recursively<dim, spacedim>(
1716 cell_1->child(n_face_1),
1717 cell_2->child(n_face_2),
1718 n_face_1,
1719 n_face_2,
1720 orientation,
1721 periodic_face_map);
1722 }
1723 else // only face_1 has children
1724 {
1725 update_periodic_face_map_recursively<dim, spacedim>(
1726 cell_1->child(n_face_1),
1727 cell_2,
1728 n_face_1,
1729 n_face_2,
1730 orientation,
1731 periodic_face_map);
1732 }
1733 }
1734 }
1735 else // dim == 2 || dim == 3
1736 {
1737 if (cell_1->has_children())
1738 {
1739 if (cell_2->has_children())
1740 {
1741 // In the case that both faces have children, we loop over all
1742 // children and apply update_periodic_face_map_recursively
1743 // recursively:
1744
1745 Assert(face_1->n_children() ==
1747 face_2->n_children() ==
1750
1751 const auto reference_cell = cell_1->reference_cell();
1752
1753 for (unsigned int i = 0;
1754 i < GeometryInfo<dim>::max_children_per_face;
1755 ++i)
1756 {
1757 // Lookup the index for the second face
1758 const unsigned int j =
1759 reference_cell.standard_to_real_face_vertex(
1760 i, n_face_1, inverse_orientation);
1761
1762 // find subcell ids that belong to the subface indices
1763 unsigned int child_cell_1 =
1765 cell_1->refinement_case(),
1766 n_face_1,
1767 i,
1768 cell_1->face_orientation(n_face_1),
1769 cell_1->face_flip(n_face_1),
1770 cell_1->face_rotation(n_face_1),
1771 face_1->refinement_case());
1772 unsigned int child_cell_2 =
1774 cell_2->refinement_case(),
1775 n_face_2,
1776 j,
1777 cell_2->face_orientation(n_face_2),
1778 cell_2->face_flip(n_face_2),
1779 cell_2->face_rotation(n_face_2),
1780 face_2->refinement_case());
1781
1782 Assert(cell_1->child(child_cell_1)->face(n_face_1) ==
1783 face_1->child(i),
1785 Assert(cell_2->child(child_cell_2)->face(n_face_2) ==
1786 face_2->child(j),
1788
1789 // precondition: subcell has the same orientation as cell
1790 // (so that the face numbers coincide) recursive call
1791 update_periodic_face_map_recursively<dim, spacedim>(
1792 cell_1->child(child_cell_1),
1793 cell_2->child(child_cell_2),
1794 n_face_1,
1795 n_face_2,
1796 orientation,
1797 periodic_face_map);
1798 }
1799 }
1800 else // only face_1 has children
1801 {
1802 for (unsigned int i = 0;
1803 i < GeometryInfo<dim>::max_children_per_face;
1804 ++i)
1805 {
1806 // find subcell ids that belong to the subface indices
1807 unsigned int child_cell_1 =
1809 cell_1->refinement_case(),
1810 n_face_1,
1811 i,
1812 cell_1->face_orientation(n_face_1),
1813 cell_1->face_flip(n_face_1),
1814 cell_1->face_rotation(n_face_1),
1815 face_1->refinement_case());
1816
1817 // recursive call
1818 update_periodic_face_map_recursively<dim, spacedim>(
1819 cell_1->child(child_cell_1),
1820 cell_2,
1821 n_face_1,
1822 n_face_2,
1823 orientation,
1824 periodic_face_map);
1825 }
1826 }
1827 }
1828 }
1829 }
1830
1831
1832} // end of anonymous namespace
1833
1834
1835namespace internal
1836{
1837 namespace TriangulationImplementation
1838 {
1839 // make sure that if in the following we
1840 // write Triangulation<dim,spacedim>
1841 // we mean the *class*
1842 // ::Triangulation, not the
1843 // enclosing namespace
1844 // internal::TriangulationImplementation
1845 using ::Triangulation;
1846
1852 int,
1853 << "Something went wrong upon construction of cell "
1854 << arg1);
1865 int,
1866 << "Cell " << arg1
1867 << " has negative measure. This typically "
1868 << "indicates some distortion in the cell, or a mistakenly "
1869 << "swapped pair of vertices in the input to "
1870 << "Triangulation::create_triangulation().");
1879 int,
1880 int,
1881 int,
1882 << "Error while creating cell " << arg1
1883 << ": the vertex index " << arg2 << " must be between 0 and "
1884 << arg3 << '.');
1891 int,
1892 int,
1894 << "The input data for creating a triangulation contained "
1895 << "information about a line with indices " << arg1 << " and " << arg2
1896 << " that is described to have boundary indicator "
1897 << static_cast<int>(arg3)
1898 << ". However, this is an internal line not located on the "
1899 << "boundary. You cannot assign a boundary indicator to it." << std::endl
1900 << std::endl
1901 << "If this happened at a place where you call "
1902 << "Triangulation::create_triangulation() yourself, you need "
1903 << "to check the SubCellData object you pass to this function."
1904 << std::endl
1905 << std::endl
1906 << "If this happened in a place where you are reading a mesh "
1907 << "from a file, then you need to investigate why such a line "
1908 << "ended up in the input file. A typical case is a geometry "
1909 << "that consisted of multiple parts and for which the mesh "
1910 << "generator program assumes that the interface between "
1911 << "two parts is a boundary when that isn't supposed to be "
1912 << "the case, or where the mesh generator simply assigns "
1913 << "'geometry indicators' to lines at the perimeter of "
1914 << "a part that are not supposed to be interpreted as "
1915 << "'boundary indicators'.");
1922 int,
1923 int,
1924 int,
1925 int,
1927 << "The input data for creating a triangulation contained "
1928 << "information about a quad with indices " << arg1 << ", " << arg2
1929 << ", " << arg3 << ", and " << arg4
1930 << " that is described to have boundary indicator "
1931 << static_cast<int>(arg5)
1932 << ". However, this is an internal quad not located on the "
1933 << "boundary. You cannot assign a boundary indicator to it." << std::endl
1934 << std::endl
1935 << "If this happened at a place where you call "
1936 << "Triangulation::create_triangulation() yourself, you need "
1937 << "to check the SubCellData object you pass to this function."
1938 << std::endl
1939 << std::endl
1940 << "If this happened in a place where you are reading a mesh "
1941 << "from a file, then you need to investigate why such a quad "
1942 << "ended up in the input file. A typical case is a geometry "
1943 << "that consisted of multiple parts and for which the mesh "
1944 << "generator program assumes that the interface between "
1945 << "two parts is a boundary when that isn't supposed to be "
1946 << "the case, or where the mesh generator simply assigns "
1947 << "'geometry indicators' to quads at the surface of "
1948 << "a part that are not supposed to be interpreted as "
1949 << "'boundary indicators'.");
1956 int,
1957 int,
1958 << "In SubCellData the line info of the line with vertex indices " << arg1
1959 << " and " << arg2 << " appears more than once. "
1960 << "This is not allowed.");
1967 int,
1968 int,
1969 std::string,
1970 << "In SubCellData the line info of the line with vertex indices " << arg1
1971 << " and " << arg2 << " appears multiple times with different (valid) "
1972 << arg3 << ". This is not allowed.");
1979 int,
1980 int,
1981 int,
1982 int,
1983 std::string,
1984 << "In SubCellData the quad info of the quad with line indices " << arg1
1985 << ", " << arg2 << ", " << arg3 << " and " << arg4
1986 << " appears multiple times with different (valid) " << arg5
1987 << ". This is not allowed.");
1988
1989 /*
1990 * Reserve space for TriaFaces. Details:
1991 *
1992 * Reserve space for line_orientations.
1993 *
1994 * @note Used only for dim=3.
1995 */
1996 void
1998 const unsigned int new_quads_in_pairs,
1999 const unsigned int new_quads_single)
2000 {
2001 AssertDimension(tria_faces.dim, 3);
2002
2003 Assert(new_quads_in_pairs % 2 == 0, ExcInternalError());
2004
2005 unsigned int next_free_single = 0;
2006 unsigned int next_free_pair = 0;
2007
2008 // count the number of objects, of unused single objects and of
2009 // unused pairs of objects
2010 [[maybe_unused]] unsigned int n_quads = 0;
2011 unsigned int n_unused_pairs = 0;
2012 unsigned int n_unused_singles = 0;
2013 for (unsigned int i = 0; i < tria_faces.quads.used.size(); ++i)
2014 {
2015 if (tria_faces.quads.used[i])
2016 ++n_quads;
2017 else if (i + 1 < tria_faces.quads.used.size())
2018 {
2019 if (tria_faces.quads.used[i + 1])
2020 {
2021 ++n_unused_singles;
2022 if (next_free_single == 0)
2023 next_free_single = i;
2024 }
2025 else
2026 {
2027 ++n_unused_pairs;
2028 if (next_free_pair == 0)
2029 next_free_pair = i;
2030 ++i;
2031 }
2032 }
2033 else
2034 ++n_unused_singles;
2035 }
2036 Assert(n_quads + 2 * n_unused_pairs + n_unused_singles ==
2037 tria_faces.quads.used.size(),
2039
2040 // how many single quads are needed in addition to n_unused_quads?
2041 const int additional_single_quads = new_quads_single - n_unused_singles;
2042
2043 unsigned int new_size =
2044 tria_faces.quads.used.size() + new_quads_in_pairs - 2 * n_unused_pairs;
2045 if (additional_single_quads > 0)
2046 new_size += additional_single_quads;
2047
2048 // see above...
2049 if (new_size > tria_faces.quads.n_objects())
2050 {
2051 // reserve the field of the derived class
2052 tria_faces.quads_line_orientations.resize(
2053 new_size * GeometryInfo<3>::lines_per_face, true);
2054
2055 auto &q_is_q = tria_faces.quad_is_quadrilateral;
2056 q_is_q.reserve(new_size);
2057 q_is_q.insert(q_is_q.end(), new_size - q_is_q.size(), true);
2058 }
2059 }
2060
2061
2062
2076 void
2078 const unsigned int total_cells,
2079 const unsigned int dimension,
2080 const unsigned int space_dimension,
2081 const bool tetraheder_in_mesh = false)
2082 {
2083 // we need space for total_cells cells. Maybe we have more already
2084 // with those cells which are unused, so only allocate new space if
2085 // needed.
2086 //
2087 // note that all arrays should have equal sizes (checked by
2088 // @p{monitor_memory}
2089 if (total_cells > tria_level.refine_flags.size())
2090 {
2091 tria_level.refine_flags.reserve(total_cells);
2092 tria_level.refine_flags.insert(tria_level.refine_flags.end(),
2093 total_cells -
2094 tria_level.refine_flags.size(),
2095 /*RefinementCase::no_refinement=*/0);
2096
2097 if (tetraheder_in_mesh)
2098 {
2099 tria_level.refine_choice.reserve(total_cells);
2100 tria_level.refine_choice.insert(
2101 tria_level.refine_choice.end(),
2102 total_cells - tria_level.refine_choice.size(),
2103 static_cast<char>(
2105 }
2106
2107 tria_level.coarsen_flags.reserve(total_cells);
2108 tria_level.coarsen_flags.insert(tria_level.coarsen_flags.end(),
2109 total_cells -
2110 tria_level.coarsen_flags.size(),
2111 false);
2112
2113 tria_level.active_cell_indices.reserve(total_cells);
2114 tria_level.active_cell_indices.insert(
2115 tria_level.active_cell_indices.end(),
2116 total_cells - tria_level.active_cell_indices.size(),
2118
2119 tria_level.subdomain_ids.reserve(total_cells);
2120 tria_level.subdomain_ids.insert(tria_level.subdomain_ids.end(),
2121 total_cells -
2122 tria_level.subdomain_ids.size(),
2123 0);
2124
2125 tria_level.level_subdomain_ids.reserve(total_cells);
2126 tria_level.level_subdomain_ids.insert(
2127 tria_level.level_subdomain_ids.end(),
2128 total_cells - tria_level.level_subdomain_ids.size(),
2129 0);
2130
2131 tria_level.global_active_cell_indices.reserve(total_cells);
2132 tria_level.global_active_cell_indices.insert(
2133 tria_level.global_active_cell_indices.end(),
2134 total_cells - tria_level.global_active_cell_indices.size(),
2136
2137 tria_level.global_level_cell_indices.reserve(total_cells);
2138 tria_level.global_level_cell_indices.insert(
2139 tria_level.global_level_cell_indices.end(),
2140 total_cells - tria_level.global_level_cell_indices.size(),
2142
2143 if (dimension == space_dimension - 1)
2144 {
2145 tria_level.direction_flags.reserve(total_cells);
2146 tria_level.direction_flags.insert(
2147 tria_level.direction_flags.end(),
2148 total_cells - tria_level.direction_flags.size(),
2149 true);
2150 }
2151 else
2152 tria_level.direction_flags.clear();
2153
2154 tria_level.parents.reserve((total_cells + 1) / 2);
2155 tria_level.parents.insert(tria_level.parents.end(),
2156 (total_cells + 1) / 2 -
2157 tria_level.parents.size(),
2158 -1);
2159
2160 tria_level.neighbors.reserve(total_cells * (2 * dimension));
2161 tria_level.neighbors.insert(tria_level.neighbors.end(),
2162 total_cells * (2 * dimension) -
2163 tria_level.neighbors.size(),
2164 std::make_pair(-1, -1));
2165
2166 if (tria_level.dim == 2 || tria_level.dim == 3)
2167 {
2168 const unsigned int max_faces_per_cell = 2 * dimension;
2169 tria_level.face_orientations.resize(total_cells *
2170 max_faces_per_cell);
2171
2172 tria_level.reference_cell.reserve(total_cells);
2173 tria_level.reference_cell.insert(
2174 tria_level.reference_cell.end(),
2175 total_cells - tria_level.reference_cell.size(),
2176 tria_level.dim == 2 ? ReferenceCells::Quadrilateral :
2178 }
2179 }
2180 }
2181
2182
2183
2188 int,
2189 int,
2190 << "The containers have sizes " << arg1 << " and " << arg2
2191 << ", which is not as expected.");
2192
2198 void
2199 monitor_memory(const TriaLevel &tria_level,
2200 const unsigned int true_dimension)
2201 {
2202 Assert(2 * true_dimension * tria_level.refine_flags.size() ==
2203 tria_level.neighbors.size(),
2204 ExcMemoryInexact(tria_level.refine_flags.size(),
2205 tria_level.neighbors.size()));
2206 Assert(2 * true_dimension * tria_level.coarsen_flags.size() ==
2207 tria_level.neighbors.size(),
2208 ExcMemoryInexact(tria_level.coarsen_flags.size(),
2209 tria_level.neighbors.size()));
2210 }
2211
2212
2213
2226 void
2228 const unsigned int new_objects_in_pairs,
2229 const unsigned int new_objects_single = 0)
2230 {
2231 if (tria_objects.structdim <= 2)
2232 {
2233 Assert(new_objects_in_pairs % 2 == 0, ExcInternalError());
2234
2235 tria_objects.next_free_single = 0;
2236 tria_objects.next_free_pair = 0;
2237 tria_objects.reverse_order_next_free_single = false;
2238
2239 // count the number of objects, of unused single objects and of
2240 // unused pairs of objects
2241 [[maybe_unused]] unsigned int n_objects = 0;
2242 unsigned int n_unused_pairs = 0;
2243 unsigned int n_unused_singles = 0;
2244 for (unsigned int i = 0; i < tria_objects.used.size(); ++i)
2245 {
2246 if (tria_objects.used[i])
2247 ++n_objects;
2248 else if (i + 1 < tria_objects.used.size())
2249 {
2250 if (tria_objects.used[i + 1])
2251 {
2252 ++n_unused_singles;
2253 if (tria_objects.next_free_single == 0)
2254 tria_objects.next_free_single = i;
2255 }
2256 else
2257 {
2258 ++n_unused_pairs;
2259 if (tria_objects.next_free_pair == 0)
2260 tria_objects.next_free_pair = i;
2261 ++i;
2262 }
2263 }
2264 else
2265 ++n_unused_singles;
2266 }
2267 Assert(n_objects + 2 * n_unused_pairs + n_unused_singles ==
2268 tria_objects.used.size(),
2270
2271 // how many single objects are needed in addition to
2272 // n_unused_objects?
2273 const int additional_single_objects =
2274 new_objects_single - n_unused_singles;
2275
2276 unsigned int new_size = tria_objects.used.size() +
2277 new_objects_in_pairs - 2 * n_unused_pairs;
2278 if (additional_single_objects > 0)
2279 new_size += additional_single_objects;
2280
2281 // only allocate space if necessary
2282 if (new_size > tria_objects.n_objects())
2283 {
2284 const unsigned int max_faces_per_cell =
2285 2 * tria_objects.structdim;
2286 const unsigned int max_children_per_cell =
2287 1 << tria_objects.structdim;
2288
2289 tria_objects.cells.reserve(new_size * max_faces_per_cell);
2290 tria_objects.cells.insert(tria_objects.cells.end(),
2291 (new_size - tria_objects.n_objects()) *
2292 max_faces_per_cell,
2293 -1);
2294
2295 tria_objects.used.reserve(new_size);
2296 tria_objects.used.insert(tria_objects.used.end(),
2297 new_size - tria_objects.used.size(),
2298 false);
2299
2300 tria_objects.user_flags.reserve(new_size);
2301 tria_objects.user_flags.insert(tria_objects.user_flags.end(),
2302 new_size -
2303 tria_objects.user_flags.size(),
2304 false);
2305
2306 const unsigned int factor = max_children_per_cell / 2;
2307 tria_objects.children.reserve(factor * new_size);
2308 tria_objects.children.insert(tria_objects.children.end(),
2309 factor * new_size -
2310 tria_objects.children.size(),
2311 -1);
2312
2313 if (tria_objects.structdim > 1)
2314 {
2315 tria_objects.refinement_cases.reserve(new_size);
2316 tria_objects.refinement_cases.insert(
2317 tria_objects.refinement_cases.end(),
2318 new_size - tria_objects.refinement_cases.size(),
2319 /*RefinementCase::no_refinement=*/0);
2320 }
2321
2322 // first reserve, then resize. Otherwise the std library can
2323 // decide to allocate more entries.
2324 tria_objects.boundary_or_material_id.reserve(new_size);
2325 tria_objects.boundary_or_material_id.resize(new_size);
2326
2327 tria_objects.user_data.reserve(new_size);
2328 tria_objects.user_data.resize(new_size);
2329
2330 tria_objects.manifold_id.reserve(new_size);
2331 tria_objects.manifold_id.insert(tria_objects.manifold_id.end(),
2332 new_size -
2333 tria_objects.manifold_id.size(),
2335 }
2336
2337 if (n_unused_singles == 0)
2338 {
2339 tria_objects.next_free_single = new_size - 1;
2340 tria_objects.reverse_order_next_free_single = true;
2341 }
2342 }
2343 else
2344 {
2345 const unsigned int new_hexes = new_objects_in_pairs;
2346
2347 const unsigned int new_size =
2348 new_hexes + std::count(tria_objects.used.begin(),
2349 tria_objects.used.end(),
2350 true);
2351
2352 // see above...
2353 if (new_size > tria_objects.n_objects())
2354 {
2355 const unsigned int max_faces_per_cell =
2356 2 * tria_objects.structdim;
2357
2358 tria_objects.cells.reserve(new_size * max_faces_per_cell);
2359 tria_objects.cells.insert(tria_objects.cells.end(),
2360 (new_size - tria_objects.n_objects()) *
2361 max_faces_per_cell,
2362 -1);
2363
2364 tria_objects.used.reserve(new_size);
2365 tria_objects.used.insert(tria_objects.used.end(),
2366 new_size - tria_objects.used.size(),
2367 false);
2368
2369 tria_objects.user_flags.reserve(new_size);
2370 tria_objects.user_flags.insert(tria_objects.user_flags.end(),
2371 new_size -
2372 tria_objects.user_flags.size(),
2373 false);
2374
2375 tria_objects.children.reserve(4 * new_size);
2376 tria_objects.children.insert(tria_objects.children.end(),
2377 4 * new_size -
2378 tria_objects.children.size(),
2379 -1);
2380
2381 // for the following fields, we know exactly how many elements
2382 // we need, so first reserve then resize (resize itself, at least
2383 // with some compiler libraries, appears to round up the size it
2384 // actually reserves)
2385 tria_objects.boundary_or_material_id.reserve(new_size);
2386 tria_objects.boundary_or_material_id.resize(new_size);
2387
2388 tria_objects.manifold_id.reserve(new_size);
2389 tria_objects.manifold_id.insert(tria_objects.manifold_id.end(),
2390 new_size -
2391 tria_objects.manifold_id.size(),
2393
2394 tria_objects.user_data.reserve(new_size);
2395 tria_objects.user_data.resize(new_size);
2396
2397 tria_objects.refinement_cases.reserve(new_size);
2398 tria_objects.refinement_cases.insert(
2399 tria_objects.refinement_cases.end(),
2400 new_size - tria_objects.refinement_cases.size(),
2401 /*RefinementCase::no_refinement=*/0);
2402 }
2403 tria_objects.next_free_single = tria_objects.next_free_pair = 0;
2404 }
2405 }
2406
2407
2408
2414 void
2415 monitor_memory(const TriaObjects &tria_object, const unsigned int)
2416 {
2417 Assert(tria_object.n_objects() == tria_object.used.size(),
2418 ExcMemoryInexact(tria_object.n_objects(),
2419 tria_object.used.size()));
2420 Assert(tria_object.n_objects() == tria_object.user_flags.size(),
2421 ExcMemoryInexact(tria_object.n_objects(),
2422 tria_object.user_flags.size()));
2423 Assert(tria_object.n_objects() ==
2424 tria_object.boundary_or_material_id.size(),
2425 ExcMemoryInexact(tria_object.n_objects(),
2426 tria_object.boundary_or_material_id.size()));
2427 Assert(tria_object.n_objects() == tria_object.manifold_id.size(),
2428 ExcMemoryInexact(tria_object.n_objects(),
2429 tria_object.manifold_id.size()));
2430 Assert(tria_object.n_objects() == tria_object.user_data.size(),
2431 ExcMemoryInexact(tria_object.n_objects(),
2432 tria_object.user_data.size()));
2433
2434 if (tria_object.structdim == 1)
2435 {
2436 Assert(1 * tria_object.n_objects() == tria_object.children.size(),
2437 ExcMemoryInexact(tria_object.n_objects(),
2438 tria_object.children.size()));
2439 }
2440 else if (tria_object.structdim == 2)
2441 {
2442 Assert(2 * tria_object.n_objects() == tria_object.children.size(),
2443 ExcMemoryInexact(tria_object.n_objects(),
2444 tria_object.children.size()));
2445 }
2446 else if (tria_object.structdim == 3)
2447 {
2448 Assert(4 * tria_object.n_objects() == tria_object.children.size(),
2449 ExcMemoryInexact(tria_object.n_objects(),
2450 tria_object.children.size()));
2451 }
2452 }
2453
2454
2455
2460 template <int dim, int spacedim>
2462 {
2463 public:
2467 virtual ~Policy() = default;
2468
2472 virtual void
2474
2478 virtual void
2482 std::vector<unsigned int> &line_cell_count,
2483 std::vector<unsigned int> &quad_cell_count) = 0;
2484
2490 const bool check_for_distorted_cells) = 0;
2491
2495 virtual void
2498
2502 virtual void
2505
2509 virtual bool
2511 const typename Triangulation<dim, spacedim>::cell_iterator &cell) = 0;
2512
2519 virtual std::unique_ptr<Policy<dim, spacedim>>
2520 clone() = 0;
2521 };
2522
2523
2524
2530 template <int dim, int spacedim, typename T>
2531 class PolicyWrapper : public Policy<dim, spacedim>
2532 {
2533 public:
2534 void
2536 {
2537 T::update_neighbors(tria);
2538 }
2539
2540 void
2544 std::vector<unsigned int> &line_cell_count,
2545 std::vector<unsigned int> &quad_cell_count) override
2546 {
2547 T::delete_children(tria, cell, line_cell_count, quad_cell_count);
2548 }
2549
2552 const bool check_for_distorted_cells) override
2553 {
2554 return T::execute_refinement(triangulation, check_for_distorted_cells);
2555 }
2556
2557 void
2560 {
2561 T::prevent_distorted_boundary_cells(triangulation);
2562 }
2563
2564 void
2567 {
2568 T::prepare_refinement_dim_dependent(triangulation);
2569 }
2570
2571 bool
2574 override
2575 {
2576 return T::template coarsening_allowed<dim, spacedim>(cell);
2577 }
2578
2579 std::unique_ptr<Policy<dim, spacedim>>
2580 clone() override
2581 {
2582 return std::make_unique<PolicyWrapper<dim, spacedim, T>>();
2583 }
2584 };
2585
2586
2587
2684 {
2696 template <int dim, int spacedim>
2697 static void
2700 const unsigned int level_objects,
2702 {
2703 using line_iterator =
2705
2706 number_cache.n_levels = 0;
2707 if (level_objects > 0)
2708 // find the last level on which there are used cells
2709 for (unsigned int level = 0; level < level_objects; ++level)
2710 if (triangulation.begin(level) != triangulation.end(level))
2711 number_cache.n_levels = level + 1;
2712
2713 // no cells at all?
2714 Assert(number_cache.n_levels > 0, ExcInternalError());
2715
2716 //---------------------------------
2717 // update the number of lines on the different levels in the
2718 // cache
2719 number_cache.n_lines = 0;
2720 number_cache.n_active_lines = 0;
2721
2722 // for 1d, lines have levels so take count the objects per
2723 // level and globally
2724 if (dim == 1)
2725 {
2726 number_cache.n_lines_level.resize(number_cache.n_levels);
2727 number_cache.n_active_lines_level.resize(number_cache.n_levels);
2728
2729 for (unsigned int level = 0; level < number_cache.n_levels; ++level)
2730 {
2731 // count lines on this level
2732 number_cache.n_lines_level[level] = 0;
2733 number_cache.n_active_lines_level[level] = 0;
2734
2735 line_iterator line = triangulation.begin_line(level),
2736 endc =
2737 (level == number_cache.n_levels - 1 ?
2738 line_iterator(triangulation.end_line()) :
2739 triangulation.begin_line(level + 1));
2740 for (; line != endc; ++line)
2741 {
2742 ++number_cache.n_lines_level[level];
2743 if (line->has_children() == false)
2744 ++number_cache.n_active_lines_level[level];
2745 }
2746
2747 // update total number of lines
2748 number_cache.n_lines += number_cache.n_lines_level[level];
2749 number_cache.n_active_lines +=
2750 number_cache.n_active_lines_level[level];
2751 }
2752 }
2753 else
2754 {
2755 // for dim>1, there are no levels for lines
2756 number_cache.n_lines_level.clear();
2757 number_cache.n_active_lines_level.clear();
2758
2759 line_iterator line = triangulation.begin_line(),
2760 endc = triangulation.end_line();
2761 for (; line != endc; ++line)
2762 {
2763 ++number_cache.n_lines;
2764 if (line->has_children() == false)
2765 ++number_cache.n_active_lines;
2766 }
2767 }
2768 }
2769
2784 template <int dim, int spacedim>
2785 static void
2788 const unsigned int level_objects,
2790 {
2791 // update lines and n_levels in number_cache. since we don't
2792 // access any of these numbers, we can do this in the
2793 // background
2795 static_cast<
2796 void (*)(const Triangulation<dim, spacedim> &,
2797 const unsigned int,
2799 &compute_number_cache_dim<dim, spacedim>),
2801 level_objects,
2803 number_cache));
2804
2805 using quad_iterator =
2807
2808 //---------------------------------
2809 // update the number of quads on the different levels in the
2810 // cache
2811 number_cache.n_quads = 0;
2812 number_cache.n_active_quads = 0;
2813
2814 // for 2d, quads have levels so take count the objects per
2815 // level and globally
2816 if (dim == 2)
2817 {
2818 // count the number of levels; the function we called above
2819 // on a separate Task for lines also does this and puts it into
2820 // number_cache.n_levels, but this datum may not yet be
2821 // available as we call the function on a separate task
2822 unsigned int n_levels = 0;
2823 if (level_objects > 0)
2824 // find the last level on which there are used cells
2825 for (unsigned int level = 0; level < level_objects; ++level)
2826 if (triangulation.begin(level) != triangulation.end(level))
2827 n_levels = level + 1;
2828
2829 number_cache.n_quads_level.resize(n_levels);
2830 number_cache.n_active_quads_level.resize(n_levels);
2831
2832 for (unsigned int level = 0; level < n_levels; ++level)
2833 {
2834 // count quads on this level
2835 number_cache.n_quads_level[level] = 0;
2836 number_cache.n_active_quads_level[level] = 0;
2837
2838 quad_iterator quad = triangulation.begin_quad(level),
2839 endc =
2840 (level == n_levels - 1 ?
2841 quad_iterator(triangulation.end_quad()) :
2842 triangulation.begin_quad(level + 1));
2843 for (; quad != endc; ++quad)
2844 {
2845 ++number_cache.n_quads_level[level];
2846 if (quad->has_children() == false)
2847 ++number_cache.n_active_quads_level[level];
2848 }
2849
2850 // update total number of quads
2851 number_cache.n_quads += number_cache.n_quads_level[level];
2852 number_cache.n_active_quads +=
2853 number_cache.n_active_quads_level[level];
2854 }
2855 }
2856 else
2857 {
2858 // for dim>2, there are no levels for quads
2859 number_cache.n_quads_level.clear();
2860 number_cache.n_active_quads_level.clear();
2861
2862 quad_iterator quad = triangulation.begin_quad(),
2863 endc = triangulation.end_quad();
2864 for (; quad != endc; ++quad)
2865 {
2866 ++number_cache.n_quads;
2867 if (quad->has_children() == false)
2868 ++number_cache.n_active_quads;
2869 }
2870 }
2871
2872 // wait for the background computation for lines
2873 update_lines.join();
2874 }
2875
2891 template <int dim, int spacedim>
2892 static void
2895 const unsigned int level_objects,
2897 {
2898 // update quads, lines and n_levels in number_cache. since we
2899 // don't access any of these numbers, we can do this in the
2900 // background
2901 Threads::Task<void> update_quads_and_lines = Threads::new_task(
2902 static_cast<
2903 void (*)(const Triangulation<dim, spacedim> &,
2904 const unsigned int,
2906 &compute_number_cache_dim<dim, spacedim>),
2908 level_objects,
2910 number_cache));
2911
2912 using hex_iterator =
2914
2915 //---------------------------------
2916 // update the number of hexes on the different levels in the
2917 // cache
2918 number_cache.n_hexes = 0;
2919 number_cache.n_active_hexes = 0;
2920
2921 // for 3d, hexes have levels so take count the objects per
2922 // level and globally
2923 if (dim == 3)
2924 {
2925 // count the number of levels; the function we called
2926 // above on a separate Task for quads (recursively, via
2927 // the lines function) also does this and puts it into
2928 // number_cache.n_levels, but this datum may not yet be
2929 // available as we call the function on a separate task
2930 unsigned int n_levels = 0;
2931 if (level_objects > 0)
2932 // find the last level on which there are used cells
2933 for (unsigned int level = 0; level < level_objects; ++level)
2934 if (triangulation.begin(level) != triangulation.end(level))
2935 n_levels = level + 1;
2936
2937 number_cache.n_hexes_level.resize(n_levels);
2938 number_cache.n_active_hexes_level.resize(n_levels);
2939
2940 for (unsigned int level = 0; level < n_levels; ++level)
2941 {
2942 // count hexes on this level
2943 number_cache.n_hexes_level[level] = 0;
2944 number_cache.n_active_hexes_level[level] = 0;
2945
2946 hex_iterator hex = triangulation.begin_hex(level),
2947 endc = (level == n_levels - 1 ?
2948 hex_iterator(triangulation.end_hex()) :
2949 triangulation.begin_hex(level + 1));
2950 for (; hex != endc; ++hex)
2951 {
2952 ++number_cache.n_hexes_level[level];
2953 if (hex->has_children() == false)
2954 ++number_cache.n_active_hexes_level[level];
2955 }
2956
2957 // update total number of hexes
2958 number_cache.n_hexes += number_cache.n_hexes_level[level];
2959 number_cache.n_active_hexes +=
2960 number_cache.n_active_hexes_level[level];
2961 }
2962 }
2963 else
2964 {
2965 // for dim>3, there are no levels for hexes
2966 number_cache.n_hexes_level.clear();
2967 number_cache.n_active_hexes_level.clear();
2968
2969 hex_iterator hex = triangulation.begin_hex(),
2970 endc = triangulation.end_hex();
2971 for (; hex != endc; ++hex)
2972 {
2973 ++number_cache.n_hexes;
2974 if (hex->has_children() == false)
2975 ++number_cache.n_active_hexes;
2976 }
2977 }
2978
2979 // wait for the background computation for quads
2980 update_quads_and_lines.join();
2981 }
2982
2983
2984 template <int dim, int spacedim>
2985 static void
2988 const unsigned int level_objects,
2990 {
2991 compute_number_cache_dim(triangulation, level_objects, number_cache);
2992
2993 number_cache.active_cell_index_partitioner =
2994 std::make_shared<const Utilities::MPI::Partitioner>(
2995 triangulation.n_active_cells());
2996
2997 number_cache.level_cell_index_partitioners.resize(
2998 triangulation.n_levels());
2999 for (unsigned int level = 0; level < triangulation.n_levels(); ++level)
3000 number_cache.level_cell_index_partitioners[level] =
3001 std::make_shared<const Utilities::MPI::Partitioner>(
3002 triangulation.n_cells(level));
3003 }
3004
3005
3006 template <int spacedim>
3007 static void
3010
3011
3012 template <int dim, int spacedim>
3013 static void
3015 {
3016 // each face can be neighbored on two sides
3017 // by cells. according to the face's
3018 // intrinsic normal we define the left
3019 // neighbor as the one for which the face
3020 // normal points outward, and store that
3021 // one first; the second one is then
3022 // the right neighbor for which the
3023 // face normal points inward. This
3024 // information depends on the type of cell
3025 // and local number of face for the
3026 // 'standard ordering and orientation' of
3027 // faces and then on the face_orientation
3028 // information for the real mesh. Set up a
3029 // table to have fast access to those
3030 // offsets (0 for left and 1 for
3031 // right). Some of the values are invalid
3032 // as they reference too large face
3033 // numbers, but we just leave them at a
3034 // zero value.
3035 //
3036 // Note, that in 2d for lines as faces the
3037 // normal direction given in the
3038 // GeometryInfo class is not consistent. We
3039 // thus define here that the normal for a
3040 // line points to the right if the line
3041 // points upwards.
3042 //
3043 // There is one more point to
3044 // consider, however: if we have
3045 // dim<spacedim, then we may have
3046 // cases where cells are
3047 // inverted. In effect, both
3048 // cells think they are the left
3049 // neighbor of an edge, for
3050 // example, which leads us to
3051 // forget neighborship
3052 // information (a case that shows
3053 // this is
3054 // codim_one/hanging_nodes_02). We
3055 // store whether a cell is
3056 // inverted using the
3057 // direction_flag, so if a cell
3058 // has a false direction_flag,
3059 // then we need to invert our
3060 // selection whether we are a
3061 // left or right neighbor in all
3062 // following computations.
3063 //
3064 // first index: dimension (minus 2)
3065 // second index: local face index
3066 // third index: face_orientation (false and true)
3067 static const unsigned int left_right_offset[2][6][2] = {
3068 // quadrilateral
3069 {{0, 1}, // face 0, face_orientation = false and true
3070 {1, 0}, // face 1, face_orientation = false and true
3071 {1, 0}, // face 2, face_orientation = false and true
3072 {0, 1}, // face 3, face_orientation = false and true
3073 {0, 0}, // face 4, invalid face
3074 {0, 0}}, // face 5, invalid face
3075 // hexahedron
3076 {{0, 1}, {1, 0}, {0, 1}, {1, 0}, {0, 1}, {1, 0}}};
3077
3078 // now create a vector of the two active
3079 // neighbors (left and right) for each face
3080 // and fill it by looping over all cells. For
3081 // cases with anisotropic refinement and more
3082 // then one cell neighboring at a given side
3083 // of the face we will automatically get the
3084 // active one on the highest level as we loop
3085 // over cells from lower levels first.
3087 std::vector<typename Triangulation<dim, spacedim>::cell_iterator>
3088 adjacent_cells(2 * triangulation.n_raw_faces(), dummy);
3089
3090 for (const auto &cell : triangulation.cell_iterators())
3091 for (auto f : cell->face_indices())
3092 {
3094 cell->face(f);
3095
3096 const unsigned int offset =
3097 (cell->direction_flag() ?
3098 left_right_offset[dim - 2][f][cell->face_orientation(f)] :
3099 1 -
3100 left_right_offset[dim - 2][f][cell->face_orientation(f)]);
3101
3102 adjacent_cells[2 * face->index() + offset] = cell;
3103
3104 // if this cell is not refined, but the
3105 // face is, then we'll have to set our
3106 // cell as neighbor for the child faces
3107 // as well. Fortunately the normal
3108 // orientation of children will be just
3109 // the same.
3110 if (dim == 2)
3111 {
3112 if (cell->is_active() && face->has_children())
3113 {
3114 adjacent_cells[2 * face->child(0)->index() + offset] =
3115 cell;
3116 adjacent_cells[2 * face->child(1)->index() + offset] =
3117 cell;
3118 }
3119 }
3120 else // -> dim == 3
3121 {
3122 // We need the same as in 2d
3123 // here. Furthermore, if the face is
3124 // refined with cut_x or cut_y then
3125 // those children again in the other
3126 // direction, and if this cell is
3127 // refined isotropically (along the
3128 // face) then the neighbor will
3129 // (probably) be refined as cut_x or
3130 // cut_y along the face. For those
3131 // neighboring children cells, their
3132 // neighbor will be the current,
3133 // inactive cell, as our children are
3134 // too fine to be neighbors. Catch that
3135 // case by also acting on inactive
3136 // cells with isotropic refinement
3137 // along the face. If the situation
3138 // described is not present, the data
3139 // will be overwritten later on when we
3140 // visit cells on finer levels, so no
3141 // harm will be done.
3142 if (face->has_children() &&
3143 (cell->is_active() ||
3145 cell->refinement_case(), f) ==
3147 {
3148 for (unsigned int c = 0; c < face->n_children(); ++c)
3149 adjacent_cells[2 * face->child(c)->index() + offset] =
3150 cell;
3151 if (face->child(0)->has_children())
3152 {
3153 adjacent_cells[2 * face->child(0)->child(0)->index() +
3154 offset] = cell;
3155 adjacent_cells[2 * face->child(0)->child(1)->index() +
3156 offset] = cell;
3157 }
3158 if (face->child(1)->has_children())
3159 {
3160 adjacent_cells[2 * face->child(1)->child(0)->index() +
3161 offset] = cell;
3162 adjacent_cells[2 * face->child(1)->child(1)->index() +
3163 offset] = cell;
3164 }
3165 } // if cell active and face refined
3166 } // else -> dim==3
3167 } // for all faces of all cells
3168
3169 // now loop again over all cells and set the
3170 // corresponding neighbor cell. Note, that we
3171 // have to use the opposite of the
3172 // left_right_offset in this case as we want
3173 // the offset of the neighbor, not our own.
3174 for (const auto &cell : triangulation.cell_iterators())
3175 for (auto f : cell->face_indices())
3176 {
3177 const unsigned int offset =
3178 (cell->direction_flag() ?
3179 left_right_offset[dim - 2][f][cell->face_orientation(f)] :
3180 1 -
3181 left_right_offset[dim - 2][f][cell->face_orientation(f)]);
3182 cell->set_neighbor(
3183 f, adjacent_cells[2 * cell->face(f)->index() + 1 - offset]);
3184 }
3185 }
3186
3187
3191 template <int dim, int spacedim>
3192 static void
3193 create_triangulation(const std::vector<Point<spacedim>> &vertices,
3194 const std::vector<CellData<dim>> &cells,
3195 const SubCellData &subcelldata,
3197 {
3198 AssertThrow(vertices.size() > 0, ExcMessage("No vertices given"));
3199 AssertThrow(cells.size() > 0, ExcMessage("No cells given"));
3200
3201 // Check that all cells have positive volume.
3202#ifndef _MSC_VER
3203 // TODO: The following code does not compile with MSVC. Find a way
3204 // around it
3205 if (dim == spacedim)
3206 for (unsigned int cell_no = 0; cell_no < cells.size(); ++cell_no)
3207 {
3208 // If we should check for distorted cells, then we permit them
3209 // to exist. If a cell has negative measure, then it must be
3210 // distorted (the converse is not necessarily true); hence
3211 // throw an exception if no such cells should exist.
3213 {
3214 const double cell_measure = GridTools::cell_measure<spacedim>(
3215 vertices,
3216 ArrayView<const unsigned int>(cells[cell_no].vertices));
3217 AssertThrow(cell_measure > 0, ExcGridHasInvalidCell(cell_no));
3218 }
3219 }
3220#endif
3221
3222 // clear old content
3223 tria.levels.clear();
3224 tria.levels.push_back(
3225 std::make_unique<
3227
3228 if (dim > 1)
3229 tria.faces = std::make_unique<
3231
3232 // copy vertices
3233 tria.vertices = vertices;
3234 tria.vertices_used.assign(vertices.size(), true);
3235
3236 // compute connectivity
3237 const auto connectivity = build_connectivity<unsigned int>(cells);
3238 const unsigned int n_cell = cells.size();
3239
3240 // TriaObjects: lines
3241 if (dim >= 2)
3242 {
3243 auto &lines_0 = tria.faces->lines; // data structure to be filled
3244
3245 // get connectivity between quads and lines
3246 const auto &crs = connectivity.entity_to_entities(1, 0);
3247 const unsigned int n_lines = crs.ptr.size() - 1;
3248
3249 // allocate memory
3250 reserve_space_(lines_0, n_lines);
3251
3252 // loop over lines
3253 for (unsigned int line = 0; line < n_lines; ++line)
3254 for (unsigned int i = crs.ptr[line], j = 0; i < crs.ptr[line + 1];
3255 ++i, ++j)
3256 lines_0.cells[line * GeometryInfo<1>::faces_per_cell + j] =
3257 crs.col[i]; // set vertex indices
3258 }
3259
3260 // TriaObjects: quads
3261 if (dim == 3)
3262 {
3263 auto &quads_0 = tria.faces->quads; // data structures to be filled
3264 auto &faces = *tria.faces;
3265
3266 // get connectivity between quads and lines
3267 const auto &crs = connectivity.entity_to_entities(2, 1);
3268 const unsigned int n_quads = crs.ptr.size() - 1;
3269
3270 // allocate memory
3271 reserve_space_(quads_0, n_quads);
3272 reserve_space_(faces, 2 /*structdim*/, n_quads);
3273
3274 // loop over all quads -> entity type, line indices/orientations
3275 for (unsigned int q = 0, k = 0; q < n_quads; ++q)
3276 {
3277 // set entity type of quads
3278 faces.set_quad_type(q, connectivity.entity_types(2)[q]);
3279
3280 // loop over all its lines
3281 for (unsigned int i = crs.ptr[q], j = 0; i < crs.ptr[q + 1];
3282 ++i, ++j, ++k)
3283 {
3284 // set line index
3285 quads_0.cells[q * GeometryInfo<3>::lines_per_face + j] =
3286 crs.col[i];
3287
3288 // set line orientations
3289 const unsigned char combined_orientation =
3290 connectivity.entity_orientations(1)
3291 .get_combined_orientation(k);
3292 // it doesn't make sense to set any flags except
3293 // orientation for a line
3294 Assert(
3295 combined_orientation ==
3297 combined_orientation ==
3300 faces.quads_line_orientations
3302 combined_orientation ==
3304 }
3305 }
3306 }
3307
3308 // TriaObjects/TriaLevel: cell
3309 {
3310 auto &cells_0 = tria.levels[0]->cells; // data structure to be filled
3311 auto &level = *tria.levels[0];
3312
3313 // get connectivity between cells/faces and cells/cells
3314 const auto &crs = connectivity.entity_to_entities(dim, dim - 1);
3315 const auto &nei = connectivity.entity_to_entities(dim, dim);
3316
3317 // in 2d optional: since in in pure QUAD meshes same line
3318 // orientations can be guaranteed
3319 bool orientation_needed = false;
3320 if (dim == 3)
3321 orientation_needed = true;
3322 else if (dim == 2)
3323 {
3324 const auto &orientations = connectivity.entity_orientations(1);
3325 for (unsigned int i = 0; i < orientations.n_objects(); ++i)
3326 if (orientations.get_combined_orientation(i) !=
3328 {
3329 orientation_needed = true;
3330 break;
3331 }
3332 }
3333
3334 // allocate memory
3335 reserve_space_(cells_0, n_cell);
3336 reserve_space_(level, spacedim, n_cell, orientation_needed);
3337
3338 // loop over all cells
3339 for (unsigned int cell = 0; cell < n_cell; ++cell)
3340 {
3341 // set material ids
3342 cells_0.boundary_or_material_id[cell].material_id =
3343 cells[cell].material_id;
3344
3345 // set manifold ids
3346 cells_0.manifold_id[cell] = cells[cell].manifold_id;
3347
3348 // set entity types
3349 level.reference_cell[cell] = connectivity.entity_types(dim)[cell];
3350
3351 // loop over faces
3352 for (unsigned int i = crs.ptr[cell], j = 0; i < crs.ptr[cell + 1];
3353 ++i, ++j)
3354 {
3355 // set neighbor if not at boundary
3356 if (nei.col[i] != static_cast<unsigned int>(-1))
3357 level.neighbors[cell * GeometryInfo<dim>::faces_per_cell +
3358 j] = {0, nei.col[i]};
3359
3360 // set face indices
3361 cells_0.cells[cell * GeometryInfo<dim>::faces_per_cell + j] =
3362 crs.col[i];
3363
3364 // set face orientation if needed
3365 if (orientation_needed)
3366 {
3367 level.face_orientations.set_combined_orientation(
3369 connectivity.entity_orientations(dim - 1)
3370 .get_combined_orientation(i));
3371 }
3372 }
3373 }
3374 }
3375
3376 // TriaFaces: boundary id of boundary faces
3377 if (dim > 1)
3378 {
3379 auto &bids_face = dim == 3 ?
3380 tria.faces->quads.boundary_or_material_id :
3381 tria.faces->lines.boundary_or_material_id;
3382
3383 // count number of cells a face is belonging to
3384 std::vector<unsigned int> count(bids_face.size(), 0);
3385
3386 // get connectivity between cells/faces
3387 const auto &crs = connectivity.entity_to_entities(dim, dim - 1);
3388
3389 // count how many cells are adjacent to the same face
3390 for (unsigned int cell = 0; cell < cells.size(); ++cell)
3391 for (unsigned int i = crs.ptr[cell]; i < crs.ptr[cell + 1]; ++i)
3392 count[crs.col[i]]++;
3393
3394 // loop over all faces
3395 for (unsigned int face = 0; face < count.size(); ++face)
3396 {
3397 if (count[face] != 1) // inner face
3398 continue;
3399
3400 // boundary faces ...
3401 bids_face[face].boundary_id = 0;
3402
3403 if (dim != 3)
3404 continue;
3405
3406 // ... and the lines of quads in 3d
3407 const auto &crs = connectivity.entity_to_entities(2, 1);
3408 for (unsigned int i = crs.ptr[face]; i < crs.ptr[face + 1]; ++i)
3409 tria.faces->lines.boundary_or_material_id[crs.col[i]]
3410 .boundary_id = 0;
3411 }
3412 }
3413 else // 1d
3414 {
3415 static const unsigned int t_tba = static_cast<unsigned int>(-1);
3416 static const unsigned int t_inner = static_cast<unsigned int>(-2);
3417
3418 std::vector<unsigned int> type(vertices.size(), t_tba);
3419
3420 const auto &crs = connectivity.entity_to_entities(1, 0);
3421
3422 for (unsigned int cell = 0; cell < cells.size(); ++cell)
3423 for (unsigned int i = crs.ptr[cell], j = 0; i < crs.ptr[cell + 1];
3424 ++i, ++j)
3425 if (type[crs.col[i]] != t_inner)
3426 type[crs.col[i]] = type[crs.col[i]] == t_tba ? j : t_inner;
3427
3428 for (unsigned int face = 0; face < type.size(); ++face)
3429 {
3430 // note: we also treat manifolds here!?
3431 (*tria.vertex_to_manifold_id_map_1d)[face] =
3433 if (type[face] != t_inner && type[face] != t_tba)
3434 (*tria.vertex_to_boundary_id_map_1d)[face] = type[face];
3435 }
3436 }
3437
3438 // SubCellData: line
3439 if (dim >= 2)
3440 process_subcelldata(connectivity.entity_to_entities(1, 0),
3441 tria.faces->lines,
3442 subcelldata.boundary_lines,
3443 vertices);
3444
3445 // SubCellData: quad
3446 if (dim == 3)
3447 process_subcelldata(connectivity.entity_to_entities(2, 0),
3448 tria.faces->quads,
3449 subcelldata.boundary_quads,
3450 vertices);
3451 }
3452
3453
3454 template <int structdim, int spacedim, typename T>
3455 static void
3457 const CRS<T> &crs,
3458 TriaObjects &obj,
3459 const std::vector<CellData<structdim>> &boundary_objects_in,
3460 const std::vector<Point<spacedim>> &vertex_locations)
3461 {
3462 AssertDimension(obj.structdim, structdim);
3463
3464 if (boundary_objects_in.empty())
3465 return; // empty subcelldata -> nothing to do
3466
3467 // pre-sort subcelldata
3468 auto boundary_objects = boundary_objects_in;
3469
3470 // ... sort vertices
3471 for (auto &boundary_object : boundary_objects)
3472 std::sort(boundary_object.vertices.begin(),
3473 boundary_object.vertices.end());
3474
3475 // ... sort cells
3476 std::sort(boundary_objects.begin(),
3477 boundary_objects.end(),
3478 [](const auto &a, const auto &b) {
3479 return a.vertices < b.vertices;
3480 });
3481
3482 [[maybe_unused]] unsigned int counter = 0;
3483
3484 std::vector<unsigned int> key;
3486
3487 for (unsigned int o = 0; o < obj.n_objects(); ++o)
3488 {
3489 auto &boundary_id = obj.boundary_or_material_id[o].boundary_id;
3490 auto &manifold_id = obj.manifold_id[o];
3491
3492 // assert that object has not been visited yet and its value
3493 // has not been modified yet
3494 AssertThrow(boundary_id == 0 ||
3499
3500 // create key
3501 key.assign(crs.col.data() + crs.ptr[o],
3502 crs.col.data() + crs.ptr[o + 1]);
3503 std::sort(key.begin(), key.end());
3504
3505 // is subcelldata provided? -> binary search
3506 const auto subcell_object =
3507 std::lower_bound(boundary_objects.begin(),
3508 boundary_objects.end(),
3509 key,
3510 [&](const auto &cell, const auto &key) {
3511 return cell.vertices < key;
3512 });
3513
3514 // no subcelldata provided for this object
3515 if (subcell_object == boundary_objects.end() ||
3516 subcell_object->vertices != key)
3517 continue;
3518
3519 ++counter;
3520
3521 // set manifold id
3522 manifold_id = subcell_object->manifold_id;
3523
3524 // set boundary id
3525 if (subcell_object->boundary_id !=
3527 {
3530 ExcMessage(
3531 "The input arguments for creating a triangulation "
3532 "specified a boundary id for an internal face. This "
3533 "is not allowed."
3534 "\n\n"
3535 "The object in question has vertex indices " +
3536 [subcell_object]() {
3537 std::string s;
3538 for (const auto v : subcell_object->vertices)
3539 s += std::to_string(v) + ',';
3540 return s;
3541 }() +
3542 " which are located at coordinates " +
3543 [vertex_locations, subcell_object]() {
3544 std::ostringstream s;
3545 for (unsigned int i = 0;
3546 i < subcell_object->vertices.size();
3547 ++i)
3548 s << '('
3549 << vertex_locations[subcell_object->vertices[i]]
3550 << (i != subcell_object->vertices.size() - 1 ? "), " :
3551 ")");
3552 return s.str();
3553 }() +
3554 "."));
3555 boundary_id = subcell_object->boundary_id;
3556 }
3557 }
3558
3559 // make sure that all subcelldata entries have been processed
3560 // TODO: this is not guaranteed, why?
3561 // AssertDimension(counter, boundary_objects_in.size());
3562 }
3563
3564
3565
3566 static void
3568 const unsigned structdim,
3569 const unsigned int size)
3570 {
3571 const unsigned int dim = faces.dim;
3572
3573 const unsigned int max_lines_per_face = 2 * structdim;
3574
3575 if (dim == 3 && structdim == 2)
3576 {
3577 // quad entity types
3578 faces.quad_is_quadrilateral.assign(size, true);
3579
3580 // quad line orientations
3581 faces.quads_line_orientations.assign(size * max_lines_per_face,
3582 true);
3583 }
3584 }
3585
3586
3587
3588 static void
3590 const unsigned int spacedim,
3591 const unsigned int size,
3592 const bool orientation_needed)
3593 {
3594 const unsigned int dim = level.dim;
3595
3596 const unsigned int max_faces_per_cell = 2 * dim;
3597
3598 level.active_cell_indices.assign(size, numbers::invalid_unsigned_int);
3599 level.subdomain_ids.assign(size, 0);
3600 level.level_subdomain_ids.assign(size, 0);
3601
3602 level.refine_flags.assign(size, 0u);
3603 level.refine_choice.assign(size, 0u);
3604 level.coarsen_flags.assign(size, false);
3605
3606 level.parents.assign((size + 1) / 2, -1);
3607
3608 if (dim == spacedim - 1)
3609 level.direction_flags.assign(size, true);
3610
3611 level.neighbors.assign(size * max_faces_per_cell, {-1, -1});
3612
3613 level.reference_cell.assign(size, ReferenceCells::Invalid);
3614
3615 if (orientation_needed)
3616 level.face_orientations.reinit(size * max_faces_per_cell);
3617
3618
3619 level.global_active_cell_indices.assign(size,
3621 level.global_level_cell_indices.assign(size,
3623 }
3624
3625
3626
3627 static void
3628 reserve_space_(TriaObjects &obj, const unsigned int size)
3629 {
3630 const unsigned int structdim = obj.structdim;
3631
3632 const unsigned int max_children_per_cell = 1 << structdim;
3633 const unsigned int max_faces_per_cell = 2 * structdim;
3634
3635 obj.used.assign(size, true);
3636 obj.boundary_or_material_id.assign(
3637 size,
3639 BoundaryOrMaterialId());
3640 obj.manifold_id.assign(size, -1);
3641 obj.user_flags.assign(size, false);
3642 obj.user_data.resize(size);
3643
3644 if (structdim > 1) // TODO: why?
3645 obj.refinement_cases.assign(size, 0);
3646
3647 obj.children.assign(max_children_per_cell / 2 * size, -1);
3648
3649 obj.cells.assign(max_faces_per_cell * size, -1);
3650
3651 if (structdim <= 2)
3652 {
3653 obj.next_free_single = size - 1;
3654 obj.next_free_pair = 0;
3656 }
3657 else
3658 {
3659 obj.next_free_single = obj.next_free_pair = 0;
3660 }
3661 }
3662
3663
3679 template <int spacedim>
3680 static void
3683 std::vector<unsigned int> &,
3684 std::vector<unsigned int> &)
3685 {
3686 const unsigned int dim = 1;
3687
3688 // first we need to reset the
3689 // neighbor pointers of the
3690 // neighbors of this cell's
3691 // children to this cell. This is
3692 // different for one dimension,
3693 // since there neighbors can have a
3694 // refinement level differing from
3695 // that of this cell's children by
3696 // more than one level.
3697
3698 Assert(!cell->child(0)->has_children() &&
3699 !cell->child(1)->has_children(),
3701
3702 // first do it for the cells to the
3703 // left
3704 if (cell->neighbor(0).state() == IteratorState::valid)
3705 if (cell->neighbor(0)->has_children())
3706 {
3708 cell->neighbor(0);
3709 Assert(neighbor->level() == cell->level(), ExcInternalError());
3710
3711 // right child
3712 neighbor = neighbor->child(1);
3713 while (true)
3714 {
3715 Assert(neighbor->neighbor(1) == cell->child(0),
3717 neighbor->set_neighbor(1, cell);
3718
3719 // move on to further
3720 // children on the
3721 // boundary between this
3722 // cell and its neighbor
3723 if (neighbor->has_children())
3724 neighbor = neighbor->child(1);
3725 else
3726 break;
3727 }
3728 }
3729
3730 // now do it for the cells to the
3731 // left
3732 if (cell->neighbor(1).state() == IteratorState::valid)
3733 if (cell->neighbor(1)->has_children())
3734 {
3736 cell->neighbor(1);
3737 Assert(neighbor->level() == cell->level(), ExcInternalError());
3738
3739 // left child
3740 neighbor = neighbor->child(0);
3741 while (true)
3742 {
3743 Assert(neighbor->neighbor(0) == cell->child(1),
3745 neighbor->set_neighbor(0, cell);
3746
3747 // move on to further
3748 // children on the
3749 // boundary between this
3750 // cell and its neighbor
3751 if (neighbor->has_children())
3752 neighbor = neighbor->child(0);
3753 else
3754 break;
3755 }
3756 }
3757
3758
3759 // delete the vertex which will not
3760 // be needed anymore. This vertex
3761 // is the second of the first child
3762 triangulation.vertices_used[cell->child(0)->vertex_index(1)] = false;
3763
3764 // invalidate children. clear user
3765 // pointers, to avoid that they may
3766 // appear at unwanted places later
3767 // on...
3768 for (unsigned int child = 0; child < cell->n_children(); ++child)
3769 {
3770 cell->child(child)->clear_user_data();
3771 cell->child(child)->clear_user_flag();
3772 cell->child(child)->clear_used_flag();
3773 }
3774
3775
3776 // delete pointer to children
3777 cell->clear_children();
3778 cell->clear_user_flag();
3779 }
3780
3781
3782
3783 template <int spacedim>
3784 static void
3787 std::vector<unsigned int> &line_cell_count,
3788 std::vector<unsigned int> &)
3789 {
3790 const unsigned int dim = 2;
3791 const RefinementCase<dim> ref_case = cell->refinement_case();
3792
3793 Assert(line_cell_count.size() == triangulation.n_raw_lines(),
3795
3796 // vectors to hold all lines which
3797 // may be deleted
3798 std::vector<typename Triangulation<dim, spacedim>::line_iterator>
3799 lines_to_delete(0);
3800
3801 lines_to_delete.reserve(4 * 2 + 4);
3802
3803 // now we decrease the counters for
3804 // lines contained in the child
3805 // cells
3806 for (unsigned int c = 0; c < cell->n_children(); ++c)
3807 {
3809 cell->child(c);
3810 for (unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++l)
3811 --line_cell_count[child->line_index(l)];
3812 }
3813
3814
3815 // delete the vertex which will not
3816 // be needed anymore. This vertex
3817 // is the second of the second line
3818 // of the first child, if the cell
3819 // is refined with cut_xy, else there
3820 // is no inner vertex.
3821 // additionally delete unneeded inner
3822 // lines
3823 if (ref_case == RefinementCase<dim>::cut_xy)
3824 {
3826 .vertices_used[cell->child(0)->line(1)->vertex_index(1)] = false;
3827
3828 lines_to_delete.push_back(cell->child(0)->line(1));
3829 lines_to_delete.push_back(cell->child(0)->line(3));
3830 lines_to_delete.push_back(cell->child(3)->line(0));
3831 lines_to_delete.push_back(cell->child(3)->line(2));
3832 }
3833 else
3834 {
3835 unsigned int inner_face_no =
3836 ref_case == RefinementCase<dim>::cut_x ? 1 : 3;
3837
3838 // the inner line will not be
3839 // used any more
3840 lines_to_delete.push_back(cell->child(0)->line(inner_face_no));
3841 }
3842
3843 // invalidate children
3844 for (unsigned int child = 0; child < cell->n_children(); ++child)
3845 {
3846 cell->child(child)->clear_user_data();
3847 cell->child(child)->clear_user_flag();
3848 cell->child(child)->clear_used_flag();
3849 }
3850
3851
3852 // delete pointer to children
3853 cell->clear_children();
3854 cell->clear_refinement_case();
3855 cell->clear_user_flag();
3856
3857 // look at the refinement of outer
3858 // lines. if nobody needs those
3859 // anymore we can add them to the
3860 // list of lines to be deleted.
3861 for (unsigned int line_no = 0;
3862 line_no < GeometryInfo<dim>::lines_per_cell;
3863 ++line_no)
3864 {
3866 cell->line(line_no);
3867
3868 if (line->has_children())
3869 {
3870 // if one of the cell counters is
3871 // zero, the other has to be as well
3872
3873 Assert((line_cell_count[line->child_index(0)] == 0 &&
3874 line_cell_count[line->child_index(1)] == 0) ||
3875 (line_cell_count[line->child_index(0)] > 0 &&
3876 line_cell_count[line->child_index(1)] > 0),
3878
3879 if (line_cell_count[line->child_index(0)] == 0)
3880 {
3881 for (unsigned int c = 0; c < 2; ++c)
3882 Assert(!line->child(c)->has_children(),
3884
3885 // we may delete the line's
3886 // children and the middle vertex
3887 // as no cell references them
3888 // anymore
3890 .vertices_used[line->child(0)->vertex_index(1)] = false;
3891
3892 lines_to_delete.push_back(line->child(0));
3893 lines_to_delete.push_back(line->child(1));
3894
3895 line->clear_children();
3896 }
3897 }
3898 }
3899
3900 // finally, delete unneeded lines
3901
3902 // clear user pointers, to avoid that
3903 // they may appear at unwanted places
3904 // later on...
3905 // same for user flags, then finally
3906 // delete the lines
3907 typename std::vector<
3909 line = lines_to_delete.begin(),
3910 endline = lines_to_delete.end();
3911 for (; line != endline; ++line)
3912 {
3913 (*line)->clear_user_data();
3914 (*line)->clear_user_flag();
3915 (*line)->clear_used_flag();
3916 }
3917 }
3918
3919
3920
3921 template <int spacedim>
3922 static void
3925 std::vector<unsigned int> &line_cell_count,
3926 std::vector<unsigned int> &quad_cell_count)
3927 {
3928 const unsigned int dim = 3;
3929
3930 Assert(line_cell_count.size() == triangulation.n_raw_lines(),
3932 Assert(quad_cell_count.size() == triangulation.n_raw_quads(),
3934
3935 // first of all, we store the RefineCase of
3936 // this cell
3937 const RefinementCase<dim> ref_case = cell->refinement_case();
3938 // vectors to hold all lines and quads which
3939 // may be deleted
3940 std::vector<typename Triangulation<dim, spacedim>::line_iterator>
3941 lines_to_delete(0);
3942 std::vector<typename Triangulation<dim, spacedim>::quad_iterator>
3943 quads_to_delete(0);
3944
3945 lines_to_delete.reserve(12 * 2 + 6 * 4 + 6);
3946 quads_to_delete.reserve(6 * 4 + 12);
3947
3948 // now we decrease the counters for lines and
3949 // quads contained in the child cells
3950 for (unsigned int c = 0; c < cell->n_children(); ++c)
3951 {
3953 cell->child(c);
3954 const auto line_indices = TriaAccessorImplementation::
3955 Implementation::get_line_indices_of_cell(*child);
3956 for (const unsigned int l : cell->line_indices())
3957 --line_cell_count[line_indices[l]];
3958 for (auto f : GeometryInfo<dim>::face_indices())
3959 --quad_cell_count[child->quad_index(f)];
3960 }
3961
3962 //-------------------------------------
3963 // delete interior quads and lines and the
3964 // interior vertex, depending on the
3965 // refinement case of the cell
3966 //
3967 // for append quads and lines: only append
3968 // them to the list of objects to be deleted
3969
3970 switch (ref_case)
3971 {
3973 quads_to_delete.push_back(cell->child(0)->face(1));
3974 break;
3976 quads_to_delete.push_back(cell->child(0)->face(3));
3977 break;
3979 quads_to_delete.push_back(cell->child(0)->face(5));
3980 break;
3982 quads_to_delete.push_back(cell->child(0)->face(1));
3983 quads_to_delete.push_back(cell->child(0)->face(3));
3984 quads_to_delete.push_back(cell->child(3)->face(0));
3985 quads_to_delete.push_back(cell->child(3)->face(2));
3986
3987 lines_to_delete.push_back(cell->child(0)->line(11));
3988 break;
3990 quads_to_delete.push_back(cell->child(0)->face(1));
3991 quads_to_delete.push_back(cell->child(0)->face(5));
3992 quads_to_delete.push_back(cell->child(3)->face(0));
3993 quads_to_delete.push_back(cell->child(3)->face(4));
3994
3995 lines_to_delete.push_back(cell->child(0)->line(5));
3996 break;
3998 quads_to_delete.push_back(cell->child(0)->face(3));
3999 quads_to_delete.push_back(cell->child(0)->face(5));
4000 quads_to_delete.push_back(cell->child(3)->face(2));
4001 quads_to_delete.push_back(cell->child(3)->face(4));
4002
4003 lines_to_delete.push_back(cell->child(0)->line(7));
4004 break;
4006 quads_to_delete.push_back(cell->child(0)->face(1));
4007 quads_to_delete.push_back(cell->child(2)->face(1));
4008 quads_to_delete.push_back(cell->child(4)->face(1));
4009 quads_to_delete.push_back(cell->child(6)->face(1));
4010
4011 quads_to_delete.push_back(cell->child(0)->face(3));
4012 quads_to_delete.push_back(cell->child(1)->face(3));
4013 quads_to_delete.push_back(cell->child(4)->face(3));
4014 quads_to_delete.push_back(cell->child(5)->face(3));
4015
4016 quads_to_delete.push_back(cell->child(0)->face(5));
4017 quads_to_delete.push_back(cell->child(1)->face(5));
4018 quads_to_delete.push_back(cell->child(2)->face(5));
4019 quads_to_delete.push_back(cell->child(3)->face(5));
4020
4021 lines_to_delete.push_back(cell->child(0)->line(5));
4022 lines_to_delete.push_back(cell->child(0)->line(7));
4023 lines_to_delete.push_back(cell->child(0)->line(11));
4024 lines_to_delete.push_back(cell->child(7)->line(0));
4025 lines_to_delete.push_back(cell->child(7)->line(2));
4026 lines_to_delete.push_back(cell->child(7)->line(8));
4027 // delete the vertex which will not
4028 // be needed anymore. This vertex
4029 // is the vertex at the heart of
4030 // this cell, which is the sixth of
4031 // the first child
4032 triangulation.vertices_used[cell->child(0)->vertex_index(7)] =
4033 false;
4034 break;
4035 default:
4036 // only remaining case is
4037 // no_refinement, thus an error
4039 break;
4040 }
4041
4042
4043 // invalidate children
4044 for (unsigned int child = 0; child < cell->n_children(); ++child)
4045 {
4046 cell->child(child)->clear_user_data();
4047 cell->child(child)->clear_user_flag();
4048
4049 for (auto f : GeometryInfo<dim>::face_indices())
4050 // set flags denoting deviations from standard orientation of
4051 // faces back to initialization values
4052 cell->child(child)->set_combined_face_orientation(
4054
4055 cell->child(child)->clear_used_flag();
4056 }
4057
4058
4059 // delete pointer to children
4060 cell->clear_children();
4061 cell->clear_refinement_case();
4062 cell->clear_user_flag();
4063
4064 // so far we only looked at inner quads,
4065 // lines and vertices. Now we have to
4066 // consider outer ones as well. here, we have
4067 // to check, whether there are other cells
4068 // still needing these objects. otherwise we
4069 // can delete them. first for quads (and
4070 // their inner lines).
4071
4072 for (const unsigned int quad_no : GeometryInfo<dim>::face_indices())
4073 {
4075 cell->face(quad_no);
4076
4077 Assert(
4078 (GeometryInfo<dim>::face_refinement_case(ref_case, quad_no) &&
4079 quad->has_children()) ||
4080 GeometryInfo<dim>::face_refinement_case(ref_case, quad_no) ==
4083
4084 switch (quad->refinement_case())
4085 {
4086 case RefinementCase<dim - 1>::no_refinement:
4087 // nothing to do as the quad
4088 // is not refined
4089 break;
4090 case RefinementCase<dim - 1>::cut_x:
4091 case RefinementCase<dim - 1>::cut_y:
4092 {
4093 // if one of the cell counters is
4094 // zero, the other has to be as
4095 // well
4096 Assert((quad_cell_count[quad->child_index(0)] == 0 &&
4097 quad_cell_count[quad->child_index(1)] == 0) ||
4098 (quad_cell_count[quad->child_index(0)] > 0 &&
4099 quad_cell_count[quad->child_index(1)] > 0),
4101 // it might be, that the quad is
4102 // refined twice anisotropically,
4103 // first check, whether we may
4104 // delete possible grand_children
4105 unsigned int deleted_grandchildren = 0;
4106 unsigned int number_of_child_refinements = 0;
4107
4108 for (unsigned int c = 0; c < 2; ++c)
4109 if (quad->child(c)->has_children())
4110 {
4111 ++number_of_child_refinements;
4112 // if one of the cell counters is
4113 // zero, the other has to be as
4114 // well
4115 Assert(
4116 (quad_cell_count[quad->child(c)->child_index(0)] ==
4117 0 &&
4118 quad_cell_count[quad->child(c)->child_index(1)] ==
4119 0) ||
4120 (quad_cell_count[quad->child(c)->child_index(0)] >
4121 0 &&
4122 quad_cell_count[quad->child(c)->child_index(1)] >
4123 0),
4125 if (quad_cell_count[quad->child(c)->child_index(0)] ==
4126 0)
4127 {
4128 // Assert, that the two
4129 // anisotropic
4130 // refinements add up to
4131 // isotropic refinement
4132 Assert(quad->refinement_case() +
4133 quad->child(c)->refinement_case() ==
4136 // we may delete the
4137 // quad's children and
4138 // the inner line as no
4139 // cell references them
4140 // anymore
4141 quads_to_delete.push_back(
4142 quad->child(c)->child(0));
4143 quads_to_delete.push_back(
4144 quad->child(c)->child(1));
4145 if (quad->child(c)->refinement_case() ==
4147 lines_to_delete.push_back(
4148 quad->child(c)->child(0)->line(1));
4149 else
4150 lines_to_delete.push_back(
4151 quad->child(c)->child(0)->line(3));
4152 quad->child(c)->clear_children();
4153 quad->child(c)->clear_refinement_case();
4154 ++deleted_grandchildren;
4155 }
4156 }
4157 // if no grandchildren are left, we
4158 // may as well delete the
4159 // refinement of the inner line
4160 // between our children and the
4161 // corresponding vertex
4162 if (number_of_child_refinements > 0 &&
4163 deleted_grandchildren == number_of_child_refinements)
4164 {
4166 middle_line;
4167 if (quad->refinement_case() == RefinementCase<2>::cut_x)
4168 middle_line = quad->child(0)->line(1);
4169 else
4170 middle_line = quad->child(0)->line(3);
4171
4172 lines_to_delete.push_back(middle_line->child(0));
4173 lines_to_delete.push_back(middle_line->child(1));
4175 .vertices_used[middle_vertex_index<dim, spacedim>(
4176 middle_line)] = false;
4177 middle_line->clear_children();
4178 }
4179
4180 // now consider the direct children
4181 // of the given quad
4182 if (quad_cell_count[quad->child_index(0)] == 0)
4183 {
4184 // we may delete the quad's
4185 // children and the inner line
4186 // as no cell references them
4187 // anymore
4188 quads_to_delete.push_back(quad->child(0));
4189 quads_to_delete.push_back(quad->child(1));
4190 if (quad->refinement_case() == RefinementCase<2>::cut_x)
4191 lines_to_delete.push_back(quad->child(0)->line(1));
4192 else
4193 lines_to_delete.push_back(quad->child(0)->line(3));
4194
4195 // if the counters just dropped
4196 // to zero, otherwise the
4197 // children would have been
4198 // deleted earlier, then this
4199 // cell's children must have
4200 // contained the anisotropic
4201 // quad children. thus, if
4202 // those have again anisotropic
4203 // children, which are in
4204 // effect isotropic children of
4205 // the original quad, those are
4206 // still needed by a
4207 // neighboring cell and we
4208 // cannot delete them. instead,
4209 // we have to reset this quad's
4210 // refine case to isotropic and
4211 // set the children
4212 // accordingly.
4213 if (quad->child(0)->has_children())
4214 if (quad->refinement_case() ==
4216 {
4217 // now evereything is
4218 // quite complicated. we
4219 // have the children
4220 // numbered according to
4221 //
4222 // *---*---*
4223 // |n+1|m+1|
4224 // *---*---*
4225 // | n | m |
4226 // *---*---*
4227 //
4228 // from the original
4229 // anisotropic
4230 // refinement. we have to
4231 // reorder them as
4232 //
4233 // *---*---*
4234 // | m |m+1|
4235 // *---*---*
4236 // | n |n+1|
4237 // *---*---*
4238 //
4239 // for isotropic refinement.
4240 //
4241 // this is a bit ugly, of
4242 // course: loop over all
4243 // cells on all levels
4244 // and look for faces n+1
4245 // (switch_1) and m
4246 // (switch_2).
4247 const typename Triangulation<dim, spacedim>::
4248 quad_iterator switch_1 =
4249 quad->child(0)->child(1),
4250 switch_2 =
4251 quad->child(1)->child(0);
4252
4253 Assert(!switch_1->has_children(),
4255 Assert(!switch_2->has_children(),
4257
4258 const int switch_1_index = switch_1->index();
4259 const int switch_2_index = switch_2->index();
4260 for (unsigned int l = 0;
4261 l < triangulation.levels.size();
4262 ++l)
4263 for (unsigned int h = 0;
4264 h <
4265 triangulation.levels[l]->cells.n_objects();
4266 ++h)
4267 for (const unsigned int q :
4269 {
4270 const int index =
4272 ->cells.get_bounding_object_indices(
4273 h)[q];
4274 if (index == switch_1_index)
4275 triangulation.levels[l]
4276 ->cells.get_bounding_object_indices(
4277 h)[q] = switch_2_index;
4278 else if (index == switch_2_index)
4279 triangulation.levels[l]
4280 ->cells.get_bounding_object_indices(
4281 h)[q] = switch_1_index;
4282 }
4283 // now we have to copy
4284 // all information of the
4285 // two quads
4286 const int switch_1_lines[4] = {
4287 static_cast<signed int>(
4288 switch_1->line_index(0)),
4289 static_cast<signed int>(
4290 switch_1->line_index(1)),
4291 static_cast<signed int>(
4292 switch_1->line_index(2)),
4293 static_cast<signed int>(
4294 switch_1->line_index(3))};
4295 const bool switch_1_line_orientations[4] = {
4296 switch_1->line_orientation(0),
4297 switch_1->line_orientation(1),
4298 switch_1->line_orientation(2),
4299 switch_1->line_orientation(3)};
4300 const types::boundary_id switch_1_boundary_id =
4301 switch_1->boundary_id();
4302 const unsigned int switch_1_user_index =
4303 switch_1->user_index();
4304 const bool switch_1_user_flag =
4305 switch_1->user_flag_set();
4306
4307 switch_1->set_bounding_object_indices(
4308 {switch_2->line_index(0),
4309 switch_2->line_index(1),
4310 switch_2->line_index(2),
4311 switch_2->line_index(3)});
4312 switch_1->set_line_orientation(
4313 0, switch_2->line_orientation(0));
4314 switch_1->set_line_orientation(
4315 1, switch_2->line_orientation(1));
4316 switch_1->set_line_orientation(
4317 2, switch_2->line_orientation(2));
4318 switch_1->set_line_orientation(
4319 3, switch_2->line_orientation(3));
4320 switch_1->set_boundary_id_internal(
4321 switch_2->boundary_id());
4322 switch_1->set_manifold_id(
4323 switch_2->manifold_id());
4324 switch_1->set_user_index(switch_2->user_index());
4325 if (switch_2->user_flag_set())
4326 switch_1->set_user_flag();
4327 else
4328 switch_1->clear_user_flag();
4329
4330 switch_2->set_bounding_object_indices(
4331 {switch_1_lines[0],
4332 switch_1_lines[1],
4333 switch_1_lines[2],
4334 switch_1_lines[3]});
4335 switch_2->set_line_orientation(
4336 0, switch_1_line_orientations[0]);
4337 switch_2->set_line_orientation(
4338 1, switch_1_line_orientations[1]);
4339 switch_2->set_line_orientation(
4340 2, switch_1_line_orientations[2]);
4341 switch_2->set_line_orientation(
4342 3, switch_1_line_orientations[3]);
4343 switch_2->set_boundary_id_internal(
4344 switch_1_boundary_id);
4345 switch_2->set_manifold_id(
4346 switch_1->manifold_id());
4347 switch_2->set_user_index(switch_1_user_index);
4348 if (switch_1_user_flag)
4349 switch_2->set_user_flag();
4350 else
4351 switch_2->clear_user_flag();
4352
4353 const unsigned int child_0 =
4354 quad->child(0)->child_index(0);
4355 const unsigned int child_2 =
4356 quad->child(1)->child_index(0);
4357 quad->clear_children();
4358 quad->clear_refinement_case();
4359 quad->set_refinement_case(
4361 quad->set_children(0, child_0);
4362 quad->set_children(2, child_2);
4363 std::swap(quad_cell_count[child_0 + 1],
4364 quad_cell_count[child_2]);
4365 }
4366 else
4367 {
4368 // the face was refined
4369 // with cut_y, thus the
4370 // children are already
4371 // in correct order. we
4372 // only have to set them
4373 // correctly, deleting
4374 // the indirection of two
4375 // anisotropic refinement
4376 // and going directly
4377 // from the quad to
4378 // isotropic children
4379 const unsigned int child_0 =
4380 quad->child(0)->child_index(0);
4381 const unsigned int child_2 =
4382 quad->child(1)->child_index(0);
4383 quad->clear_children();
4384 quad->clear_refinement_case();
4385 quad->set_refinement_case(
4387 quad->set_children(0, child_0);
4388 quad->set_children(2, child_2);
4389 }
4390 else
4391 {
4392 quad->clear_children();
4393 quad->clear_refinement_case();
4394 }
4395 }
4396 break;
4397 }
4398 case RefinementCase<dim - 1>::cut_xy:
4399 {
4400 // if one of the cell counters is
4401 // zero, the others have to be as
4402 // well
4403
4404 Assert((quad_cell_count[quad->child_index(0)] == 0 &&
4405 quad_cell_count[quad->child_index(1)] == 0 &&
4406 quad_cell_count[quad->child_index(2)] == 0 &&
4407 quad_cell_count[quad->child_index(3)] == 0) ||
4408 (quad_cell_count[quad->child_index(0)] > 0 &&
4409 quad_cell_count[quad->child_index(1)] > 0 &&
4410 quad_cell_count[quad->child_index(2)] > 0 &&
4411 quad_cell_count[quad->child_index(3)] > 0),
4413
4414 if (quad_cell_count[quad->child_index(0)] == 0)
4415 {
4416 // we may delete the quad's
4417 // children, the inner lines
4418 // and the middle vertex as no
4419 // cell references them anymore
4420 lines_to_delete.push_back(quad->child(0)->line(1));
4421 lines_to_delete.push_back(quad->child(3)->line(0));
4422 lines_to_delete.push_back(quad->child(0)->line(3));
4423 lines_to_delete.push_back(quad->child(3)->line(2));
4424
4425 for (unsigned int child = 0; child < quad->n_children();
4426 ++child)
4427 quads_to_delete.push_back(quad->child(child));
4428
4430 .vertices_used[quad->child(0)->vertex_index(3)] =
4431 false;
4432
4433 quad->clear_children();
4434 quad->clear_refinement_case();
4435 }
4436 }
4437 break;
4438
4439 default:
4441 break;
4442 }
4443 }
4444
4445 // now we repeat a similar procedure
4446 // for the outer lines of this cell.
4447
4448 // if in debug mode: check that each
4449 // of the lines for which we consider
4450 // deleting the children in fact has
4451 // children (the bits/coarsening_3d
4452 // test tripped over this initially)
4453 for (unsigned int line_no = 0;
4454 line_no < GeometryInfo<dim>::lines_per_cell;
4455 ++line_no)
4456 {
4458 cell->line(line_no);
4459
4460 Assert(
4461 (GeometryInfo<dim>::line_refinement_case(ref_case, line_no) &&
4462 line->has_children()) ||
4463 GeometryInfo<dim>::line_refinement_case(ref_case, line_no) ==
4466
4467 if (line->has_children())
4468 {
4469 // if one of the cell counters is
4470 // zero, the other has to be as well
4471
4472 Assert((line_cell_count[line->child_index(0)] == 0 &&
4473 line_cell_count[line->child_index(1)] == 0) ||
4474 (line_cell_count[line->child_index(0)] > 0 &&
4475 line_cell_count[line->child_index(1)] > 0),
4477
4478 if (line_cell_count[line->child_index(0)] == 0)
4479 {
4480 for (unsigned int c = 0; c < 2; ++c)
4481 Assert(!line->child(c)->has_children(),
4483
4484 // we may delete the line's
4485 // children and the middle vertex
4486 // as no cell references them
4487 // anymore
4489 .vertices_used[line->child(0)->vertex_index(1)] = false;
4490
4491 lines_to_delete.push_back(line->child(0));
4492 lines_to_delete.push_back(line->child(1));
4493
4494 line->clear_children();
4495 }
4496 }
4497 }
4498
4499 // finally, delete unneeded quads and lines
4500
4501 // clear user pointers, to avoid that
4502 // they may appear at unwanted places
4503 // later on...
4504 // same for user flags, then finally
4505 // delete the quads and lines
4506 typename std::vector<
4508 line = lines_to_delete.begin(),
4509 endline = lines_to_delete.end();
4510 for (; line != endline; ++line)
4511 {
4512 (*line)->clear_user_data();
4513 (*line)->clear_user_flag();
4514 (*line)->clear_used_flag();
4515 }
4516
4517 typename std::vector<
4519 quad = quads_to_delete.begin(),
4520 endquad = quads_to_delete.end();
4521 for (; quad != endquad; ++quad)
4522 {
4523 (*quad)->clear_user_data();
4524 (*quad)->clear_children();
4525 (*quad)->clear_refinement_case();
4526 (*quad)->clear_user_flag();
4527 (*quad)->clear_used_flag();
4528 }
4529 }
4530
4531
4549 template <int spacedim>
4550 static void
4553 unsigned int &next_unused_vertex,
4555 &next_unused_line,
4557 &next_unused_cell,
4558 const typename Triangulation<2, spacedim>::cell_iterator &cell)
4559 {
4560 const unsigned int dim = 2;
4561 // clear refinement flag
4562 const RefinementCase<dim> ref_case = cell->refine_flag_set();
4563 cell->clear_refine_flag();
4564
4565 /* For the refinement process: since we go the levels up from the
4566 lowest, there are (unlike above) only two possibilities: a neighbor
4567 cell is on the same level or one level up (in both cases, it may or
4568 may not be refined later on, but we don't care here).
4569
4570 First:
4571 Set up an array of the 3x3 vertices, which are distributed on the
4572 cell (the array consists of indices into the @p{vertices} std::vector
4573
4574 2--7--3
4575 | | |
4576 4--8--5
4577 | | |
4578 0--6--1
4579
4580 note: in case of cut_x or cut_y not all these vertices are needed for
4581 the new cells
4582
4583 Second:
4584 Set up an array of the new lines (the array consists of iterator
4585 pointers into the lines arrays)
4586
4587 .-6-.-7-. The directions are: .->-.->-.
4588 1 9 3 ^ ^ ^
4589 .-10.11-. .->-.->-.
4590 0 8 2 ^ ^ ^
4591 .-4-.-5-. .->-.->-.
4592
4593 cut_x:
4594 .-4-.-5-.
4595 | | |
4596 0 6 1
4597 | | |
4598 .-2-.-3-.
4599
4600 cut_y:
4601 .---5---.
4602 1 3
4603 .---6---.
4604 0 2
4605 .---4---.
4606
4607
4608 Third:
4609 Set up an array of neighbors:
4610
4611 6 7
4612 .--.--.
4613 1| | |3
4614 .--.--.
4615 0| | |2
4616 .--.--.
4617 4 5
4618
4619 We need this array for two reasons: first to get the lines which will
4620 bound the four subcells (if the neighboring cell is refined, these
4621 lines already exist), and second to update neighborship information.
4622 Since if a neighbor is not refined, its neighborship record only
4623 points to the present, unrefined, cell rather than the children we
4624 are presently creating, we only need the neighborship information
4625 if the neighbor cells are refined. In all other cases, we store
4626 the unrefined neighbor address
4627
4628 We also need for every neighbor (if refined) which number among its
4629 neighbors the present (unrefined) cell has, since that number is to
4630 be replaced and because that also is the number of the subline which
4631 will be the interface between that neighbor and the to be created
4632 cell. We will store this number (between 0 and 3) in the field
4633 @p{neighbors_neighbor}.
4634
4635 It would be sufficient to use the children of the common line to the
4636 neighbor, if we only wanted to get the new sublines and the new
4637 vertex, but because we need to update the neighborship information of
4638 the two refined subcells of the neighbor, we need to search these
4639 anyway.
4640
4641 Convention:
4642 The created children are numbered like this:
4643
4644 .--.--.
4645 |2 . 3|
4646 .--.--.
4647 |0 | 1|
4648 .--.--.
4649 */
4650 // collect the indices of the eight surrounding vertices
4651 // 2--7--3
4652 // | | |
4653 // 4--8--5
4654 // | | |
4655 // 0--6--1
4656 int new_vertices[9];
4657 for (unsigned int vertex_no = 0; vertex_no < 4; ++vertex_no)
4658 new_vertices[vertex_no] = cell->vertex_index(vertex_no);
4659 for (unsigned int line_no = 0; line_no < 4; ++line_no)
4660 if (cell->line(line_no)->has_children())
4661 new_vertices[4 + line_no] =
4662 cell->line(line_no)->child(0)->vertex_index(1);
4663
4664 if (ref_case == RefinementCase<dim>::cut_xy)
4665 {
4666 // find the next
4667 // unused vertex and
4668 // allocate it for
4669 // the new vertex we
4670 // need here
4671 while (triangulation.vertices_used[next_unused_vertex] == true)
4672 ++next_unused_vertex;
4673 Assert(next_unused_vertex < triangulation.vertices.size(),
4674 ExcMessage(
4675 "Internal error: During refinement, the triangulation "
4676 "wants to access an element of the 'vertices' array "
4677 "but it turns out that the array is not large enough."));
4678 triangulation.vertices_used[next_unused_vertex] = true;
4679
4680 new_vertices[8] = next_unused_vertex;
4681
4682 // determine middle vertex by transfinite interpolation to be
4683 // consistent with what happens to quads in a
4684 // Triangulation<3,3> when they are refined
4685 triangulation.vertices[next_unused_vertex] =
4686 cell->center(true, true);
4687 }
4688
4689
4690 // Now the lines:
4692 unsigned int lmin = 8;
4693 unsigned int lmax = 12;
4694 if (ref_case != RefinementCase<dim>::cut_xy)
4695 {
4696 lmin = 6;
4697 lmax = 7;
4698 }
4699
4700 for (unsigned int l = lmin; l < lmax; ++l)
4701 {
4702 while (next_unused_line->used() == true)
4703 ++next_unused_line;
4704 new_lines[l] = next_unused_line;
4705 ++next_unused_line;
4706
4707 AssertIsNotUsed(new_lines[l]);
4708 }
4709
4710 if (ref_case == RefinementCase<dim>::cut_xy)
4711 {
4712 // .-6-.-7-.
4713 // 1 9 3
4714 // .-10.11-.
4715 // 0 8 2
4716 // .-4-.-5-.
4717
4718 // lines 0-7 already exist, create only the four interior
4719 // lines 8-11
4720 unsigned int l = 0;
4721 for (const unsigned int face_no : GeometryInfo<dim>::face_indices())
4722 for (unsigned int c = 0; c < 2; ++c, ++l)
4723 new_lines[l] = cell->line(face_no)->child(c);
4724 Assert(l == 8, ExcInternalError());
4725
4726 new_lines[8]->set_bounding_object_indices(
4727 {new_vertices[6], new_vertices[8]});
4728 new_lines[9]->set_bounding_object_indices(
4729 {new_vertices[8], new_vertices[7]});
4730 new_lines[10]->set_bounding_object_indices(
4731 {new_vertices[4], new_vertices[8]});
4732 new_lines[11]->set_bounding_object_indices(
4733 {new_vertices[8], new_vertices[5]});
4734 }
4735 else if (ref_case == RefinementCase<dim>::cut_x)
4736 {
4737 // .-4-.-5-.
4738 // | | |
4739 // 0 6 1
4740 // | | |
4741 // .-2-.-3-.
4742 new_lines[0] = cell->line(0);
4743 new_lines[1] = cell->line(1);
4744 new_lines[2] = cell->line(2)->child(0);
4745 new_lines[3] = cell->line(2)->child(1);
4746 new_lines[4] = cell->line(3)->child(0);
4747 new_lines[5] = cell->line(3)->child(1);
4748 new_lines[6]->set_bounding_object_indices(
4749 {new_vertices[6], new_vertices[7]});
4750 }
4751 else
4752 {
4754 // .---5---.
4755 // 1 3
4756 // .---6---.
4757 // 0 2
4758 // .---4---.
4759 new_lines[0] = cell->line(0)->child(0);
4760 new_lines[1] = cell->line(0)->child(1);
4761 new_lines[2] = cell->line(1)->child(0);
4762 new_lines[3] = cell->line(1)->child(1);
4763 new_lines[4] = cell->line(2);
4764 new_lines[5] = cell->line(3);
4765 new_lines[6]->set_bounding_object_indices(
4766 {new_vertices[4], new_vertices[5]});
4767 }
4768
4769 for (unsigned int l = lmin; l < lmax; ++l)
4770 {
4771 new_lines[l]->set_used_flag();
4772 new_lines[l]->clear_user_flag();
4773 new_lines[l]->clear_user_data();
4774 new_lines[l]->clear_children();
4775 // interior line
4776 new_lines[l]->set_boundary_id_internal(
4778 new_lines[l]->set_manifold_id(cell->manifold_id());
4779 }
4780
4781 // Now add the four (two)
4782 // new cells!
4785 while (next_unused_cell->used() == true)
4786 ++next_unused_cell;
4787
4788 const unsigned int n_children = GeometryInfo<dim>::n_children(ref_case);
4789 for (unsigned int i = 0; i < n_children; ++i)
4790 {
4791 AssertIsNotUsed(next_unused_cell);
4792 subcells[i] = next_unused_cell;
4793 ++next_unused_cell;
4794 if (i % 2 == 1 && i < n_children - 1)
4795 while (next_unused_cell->used() == true)
4796 ++next_unused_cell;
4797 }
4798
4799 if (ref_case == RefinementCase<dim>::cut_xy)
4800 {
4801 // children:
4802 // .--.--.
4803 // |2 . 3|
4804 // .--.--.
4805 // |0 | 1|
4806 // .--.--.
4807 // lines:
4808 // .-6-.-7-.
4809 // 1 9 3
4810 // .-10.11-.
4811 // 0 8 2
4812 // .-4-.-5-.
4813 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
4814 new_lines[8]->index(),
4815 new_lines[4]->index(),
4816 new_lines[10]->index()});
4817 subcells[1]->set_bounding_object_indices({new_lines[8]->index(),
4818 new_lines[2]->index(),
4819 new_lines[5]->index(),
4820 new_lines[11]->index()});
4821 subcells[2]->set_bounding_object_indices({new_lines[1]->index(),
4822 new_lines[9]->index(),
4823 new_lines[10]->index(),
4824 new_lines[6]->index()});
4825 subcells[3]->set_bounding_object_indices({new_lines[9]->index(),
4826 new_lines[3]->index(),
4827 new_lines[11]->index(),
4828 new_lines[7]->index()});
4829 }
4830 else if (ref_case == RefinementCase<dim>::cut_x)
4831 {
4832 // children:
4833 // .--.--.
4834 // | . |
4835 // .0 . 1.
4836 // | | |
4837 // .--.--.
4838 // lines:
4839 // .-4-.-5-.
4840 // | | |
4841 // 0 6 1
4842 // | | |
4843 // .-2-.-3-.
4844 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
4845 new_lines[6]->index(),
4846 new_lines[2]->index(),
4847 new_lines[4]->index()});
4848 subcells[1]->set_bounding_object_indices({new_lines[6]->index(),
4849 new_lines[1]->index(),
4850 new_lines[3]->index(),
4851 new_lines[5]->index()});
4852 }
4853 else
4854 {
4856 // children:
4857 // .-----.
4858 // | 1 |
4859 // .-----.
4860 // | 0 |
4861 // .-----.
4862 // lines:
4863 // .---5---.
4864 // 1 3
4865 // .---6---.
4866 // 0 2
4867 // .---4---.
4868 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
4869 new_lines[2]->index(),
4870 new_lines[4]->index(),
4871 new_lines[6]->index()});
4872 subcells[1]->set_bounding_object_indices({new_lines[1]->index(),
4873 new_lines[3]->index(),
4874 new_lines[6]->index(),
4875 new_lines[5]->index()});
4876 }
4877
4878 types::subdomain_id subdomainid = cell->subdomain_id();
4879
4880 for (unsigned int i = 0; i < n_children; ++i)
4881 {
4882 subcells[i]->set_used_flag();
4883 subcells[i]->clear_refine_flag();
4884 subcells[i]->clear_user_flag();
4885 subcells[i]->clear_user_data();
4886 subcells[i]->clear_children();
4887 // inherit material properties
4888 subcells[i]->set_material_id(cell->material_id());
4889 subcells[i]->set_manifold_id(cell->manifold_id());
4890 subcells[i]->set_subdomain_id(subdomainid);
4891
4892 if (i % 2 == 0)
4893 subcells[i]->set_parent(cell->index());
4894 }
4895
4896
4897
4898 // set child index for even children i=0,2 (0)
4899 for (unsigned int i = 0; i < n_children / 2; ++i)
4900 cell->set_children(2 * i, subcells[2 * i]->index());
4901 // set the refine case
4902 cell->set_refinement_case(ref_case);
4903
4904 // note that the
4905 // refinement flag was
4906 // already cleared at the
4907 // beginning of this function
4908
4909 if (dim == spacedim - 1)
4910 for (unsigned int c = 0; c < n_children; ++c)
4911 cell->child(c)->set_direction_flag(cell->direction_flag());
4912 }
4913
4914
4915
4916 template <int dim, int spacedim>
4919 const bool check_for_distorted_cells)
4920 {
4921 AssertDimension(dim, 2);
4922
4923 // Check whether a new level is needed. We have to check for
4924 // this on the highest level only
4925 for (const auto &cell : triangulation.active_cell_iterators_on_level(
4926 triangulation.levels.size() - 1))
4927 if (cell->refine_flag_set())
4928 {
4929 triangulation.levels.push_back(
4930 std::make_unique<
4932 break;
4933 }
4934
4937 line != triangulation.end_line();
4938 ++line)
4939 {
4940 line->clear_user_flag();
4941 line->clear_user_data();
4942 }
4943
4944 unsigned int n_single_lines = 0;
4945 unsigned int n_lines_in_pairs = 0;
4946 unsigned int needed_vertices = 0;
4947
4948 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
4949 {
4950 // count number of flagged cells on this level and compute
4951 // how many new vertices and new lines will be needed
4952 unsigned int needed_cells = 0;
4953
4954 for (const auto &cell :
4955 triangulation.active_cell_iterators_on_level(level))
4956 if (cell->refine_flag_set())
4957 {
4958 if (cell->reference_cell() == ReferenceCells::Triangle)
4959 {
4960 needed_cells += 4;
4961 needed_vertices += 0;
4962 n_single_lines += 3;
4963 }
4964 else if (cell->reference_cell() ==
4966 {
4967 needed_cells += 4;
4968 needed_vertices += 1;
4969 n_single_lines += 4;
4970 }
4971 else
4972 {
4974 }
4975
4976 for (const auto line_no : cell->face_indices())
4977 {
4978 auto line = cell->line(line_no);
4979 if (line->has_children() == false)
4980 line->set_user_flag();
4981 }
4982 }
4983
4984
4985 const unsigned int used_cells =
4986 std::count(triangulation.levels[level + 1]->cells.used.begin(),
4987 triangulation.levels[level + 1]->cells.used.end(),
4988 true);
4989
4990
4991 reserve_space(*triangulation.levels[level + 1],
4992 used_cells + needed_cells,
4993 2,
4994 spacedim);
4995
4996 reserve_space(triangulation.levels[level + 1]->cells,
4997 needed_cells,
4998 0);
4999 }
5000
5001 for (auto line = triangulation.begin_line();
5002 line != triangulation.end_line();
5003 ++line)
5004 if (line->user_flag_set())
5005 {
5006 Assert(line->has_children() == false, ExcInternalError());
5007 n_lines_in_pairs += 2;
5008 needed_vertices += 1;
5009 }
5010
5011 reserve_space(triangulation.faces->lines, n_lines_in_pairs, 0);
5012
5013 needed_vertices += std::count(triangulation.vertices_used.begin(),
5014 triangulation.vertices_used.end(),
5015 true);
5016
5017 if (needed_vertices > triangulation.vertices.size())
5018 {
5019 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
5020 triangulation.vertices_used.resize(needed_vertices, false);
5021 }
5022
5023 unsigned int next_unused_vertex = 0;
5024
5025 {
5028 endl = triangulation.end_line();
5030 next_unused_line = triangulation.begin_raw_line();
5031
5032 for (; line != endl; ++line)
5033 if (line->user_flag_set())
5034 {
5035 // This line needs to be refined. Find the next unused vertex
5036 // and set it appropriately
5037 while (triangulation.vertices_used[next_unused_vertex] == true)
5038 ++next_unused_vertex;
5039 Assert(next_unused_vertex < triangulation.vertices.size(),
5040 ExcMessage(
5041 "Internal error: During refinement, the triangulation "
5042 "wants to access an element of the 'vertices' array "
5043 "but it turns out that the array is not large "
5044 "enough."));
5045 triangulation.vertices_used[next_unused_vertex] = true;
5046
5047 triangulation.vertices[next_unused_vertex] = line->center(true);
5048
5049 [[maybe_unused]] bool pair_found = false;
5050 for (; next_unused_line != endl; ++next_unused_line)
5051 if (!next_unused_line->used() &&
5052 !(++next_unused_line)->used())
5053 {
5054 --next_unused_line;
5055 pair_found = true;
5056 break;
5057 }
5058 Assert(pair_found, ExcInternalError());
5059
5060 line->set_children(0, next_unused_line->index());
5061
5063 children[2] = {next_unused_line, ++next_unused_line};
5064
5065 AssertIsNotUsed(children[0]);
5066 AssertIsNotUsed(children[1]);
5067
5068 children[0]->set_bounding_object_indices(
5069 {line->vertex_index(0), next_unused_vertex});
5070 children[1]->set_bounding_object_indices(
5071 {next_unused_vertex, line->vertex_index(1)});
5072
5073 for (auto &child : children)
5074 {
5075 child->set_used_flag();
5076 child->clear_children();
5077 child->clear_user_data();
5078 child->clear_user_flag();
5079 child->set_boundary_id_internal(line->boundary_id());
5080 child->set_manifold_id(line->manifold_id());
5081 // Line orientation is relative to the cell it is on so
5082 // those cannot be set at this point.
5083 }
5084
5085 line->clear_user_flag();
5086 }
5087 }
5088
5089 reserve_space(triangulation.faces->lines, 0, n_single_lines);
5090
5092 cells_with_distorted_children;
5093
5095 next_unused_line = triangulation.begin_raw_line();
5096
5097 const auto create_children = [](auto &triangulation,
5098 unsigned int &next_unused_vertex,
5099 auto &next_unused_line,
5100 auto &next_unused_cell,
5101 const auto &cell) {
5102 const auto ref_case = cell->refine_flag_set();
5103 cell->clear_refine_flag();
5104
5105 unsigned int n_new_vertices = 0;
5106
5107 if (cell->reference_cell() == ReferenceCells::Triangle)
5108 n_new_vertices = 6;
5109 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5110 n_new_vertices = 9;
5111 else
5113
5114 std::vector<unsigned int> new_vertices(n_new_vertices,
5116 for (unsigned int vertex_no = 0; vertex_no < cell->n_vertices();
5117 ++vertex_no)
5118 new_vertices[vertex_no] = cell->vertex_index(vertex_no);
5119 for (unsigned int line_no = 0; line_no < cell->n_lines(); ++line_no)
5120 if (cell->line(line_no)->has_children())
5121 new_vertices[cell->n_vertices() + line_no] =
5122 cell->line(line_no)->child(0)->vertex_index(1);
5123
5124 if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5125 {
5126 while (triangulation.vertices_used[next_unused_vertex] == true)
5127 ++next_unused_vertex;
5128 Assert(
5129 next_unused_vertex < triangulation.vertices.size(),
5130 ExcMessage(
5131 "Internal error: During refinement, the triangulation wants "
5132 "to access an element of the 'vertices' array but it turns "
5133 "out that the array is not large enough."));
5134 triangulation.vertices_used[next_unused_vertex] = true;
5135
5136 new_vertices[8] = next_unused_vertex;
5137
5138 triangulation.vertices[next_unused_vertex] =
5139 cell->center(true, true);
5140 }
5141
5142 std::array<typename Triangulation<dim, spacedim>::raw_line_iterator,
5143 12>
5144 new_lines;
5145 std::array<unsigned char, 12> inherited_orientations;
5146 inherited_orientations.fill(
5148 unsigned int lmin = 0;
5149 unsigned int lmax = 0;
5150
5151 if (cell->reference_cell() == ReferenceCells::Triangle)
5152 {
5153 lmin = 6;
5154 lmax = 9;
5155 // For triangles, the innermost faces are always reversed for the
5156 // first three children and are in the standard orientation for
5157 // the last one.
5158 std::fill(inherited_orientations.begin() + lmin,
5159 inherited_orientations.begin() + lmax,
5161 }
5162 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5163 {
5164 lmin = 8;
5165 lmax = 12;
5166 }
5167 else
5168 {
5170 }
5171
5172 for (unsigned int l = lmin; l < lmax; ++l)
5173 {
5174 while (next_unused_line->used() == true)
5175 ++next_unused_line;
5176 new_lines[l] = next_unused_line;
5177 ++next_unused_line;
5178
5179 AssertIsNotUsed(new_lines[l]);
5180 }
5181
5182 // set up lines which have parents:
5183 for (const unsigned int face_no : cell->face_indices())
5184 {
5185 // Check the face (line) orientation to ensure that the (six or
5186 // eight) outer lines in new_lines are indexed in the default
5187 // orientation. This way we can index into this array in the
5188 // without special casing orientations (e.g., quadrilateral child
5189 // 3 will always have lines 9, 3, 11, 7) when setting child lines.
5190 const unsigned char combined_orientation =
5191 cell->combined_face_orientation(face_no);
5192 Assert(combined_orientation ==
5194 combined_orientation ==
5197 for (unsigned int c = 0; c < 2; ++c)
5198 {
5199 new_lines[2 * face_no + c] = cell->line(face_no)->child(c);
5200 inherited_orientations[2 * face_no + c] =
5201 cell->combined_face_orientation(face_no);
5202 }
5203 if (combined_orientation ==
5205 std::swap(new_lines[2 * face_no], new_lines[2 * face_no + 1]);
5206 }
5207
5208 // set up lines which do not have parents:
5209 if (cell->reference_cell() == ReferenceCells::Triangle)
5210 {
5211 new_lines[6]->set_bounding_object_indices(
5212 {new_vertices[3], new_vertices[4]});
5213 new_lines[7]->set_bounding_object_indices(
5214 {new_vertices[4], new_vertices[5]});
5215 new_lines[8]->set_bounding_object_indices(
5216 {new_vertices[5], new_vertices[3]});
5217 }
5218 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5219 {
5220 new_lines[8]->set_bounding_object_indices(
5221 {new_vertices[6], new_vertices[8]});
5222 new_lines[9]->set_bounding_object_indices(
5223 {new_vertices[8], new_vertices[7]});
5224 new_lines[10]->set_bounding_object_indices(
5225 {new_vertices[4], new_vertices[8]});
5226 new_lines[11]->set_bounding_object_indices(
5227 {new_vertices[8], new_vertices[5]});
5228 }
5229 else
5230 {
5232 }
5233
5234 for (unsigned int l = lmin; l < lmax; ++l)
5235 {
5236 new_lines[l]->set_used_flag();
5237 new_lines[l]->clear_user_flag();
5238 new_lines[l]->clear_user_data();
5239 new_lines[l]->clear_children();
5240 // new lines are always internal.
5241 new_lines[l]->set_boundary_id_internal(
5243 new_lines[l]->set_manifold_id(cell->manifold_id());
5244 }
5245
5248 while (next_unused_cell->used() == true)
5249 ++next_unused_cell;
5250
5251 unsigned int n_children = 0;
5252 if (cell->reference_cell() == ReferenceCells::Triangle)
5253 n_children = 4;
5254 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5255 n_children = 4;
5256 else
5258
5259 for (unsigned int i = 0; i < n_children; ++i)
5260 {
5261 AssertIsNotUsed(next_unused_cell);
5262 subcells[i] = next_unused_cell;
5263 ++next_unused_cell;
5264 if (i % 2 == 1 && i < n_children - 1)
5265 while (next_unused_cell->used() == true)
5266 ++next_unused_cell;
5267 }
5268
5269 // Assign lines to child cells:
5270 constexpr unsigned int X = numbers::invalid_unsigned_int;
5271 static constexpr ::ndarray<unsigned int, 4, 4> tri_child_lines =
5272 {{{{0, 8, 5, X}}, {{1, 2, 6, X}}, {{7, 3, 4, X}}, {{6, 7, 8, X}}}};
5273 static constexpr ::ndarray<unsigned int, 4, 4>
5274 quad_child_lines = {{{{0, 8, 4, 10}},
5275 {{8, 2, 5, 11}},
5276 {{1, 9, 10, 6}},
5277 {{9, 3, 11, 7}}}};
5278 // Here and below we assume that child cells have the same reference
5279 // cell type as the parent.
5280 const auto &child_lines =
5281 cell->reference_cell() == ReferenceCells::Triangle ?
5282 tri_child_lines :
5283 quad_child_lines;
5284 for (unsigned int i = 0; i < n_children; ++i)
5285 {
5286 if (cell->reference_cell() == ReferenceCells::Triangle)
5287 subcells[i]->set_bounding_object_indices(
5288 {new_lines[child_lines[i][0]]->index(),
5289 new_lines[child_lines[i][1]]->index(),
5290 new_lines[child_lines[i][2]]->index()});
5291 else
5292 subcells[i]->set_bounding_object_indices(
5293 {new_lines[child_lines[i][0]]->index(),
5294 new_lines[child_lines[i][1]]->index(),
5295 new_lines[child_lines[i][2]]->index(),
5296 new_lines[child_lines[i][3]]->index()});
5297
5298 subcells[i]->set_used_flag();
5299 subcells[i]->clear_refine_flag();
5300 subcells[i]->clear_user_flag();
5301 subcells[i]->clear_user_data();
5302 subcells[i]->clear_children();
5303 // inherit material properties
5304 subcells[i]->set_material_id(cell->material_id());
5305 subcells[i]->set_manifold_id(cell->manifold_id());
5306 subcells[i]->set_subdomain_id(cell->subdomain_id());
5307
5308 triangulation.levels[subcells[i]->level()]
5309 ->reference_cell[subcells[i]->index()] = cell->reference_cell();
5310
5311 // Finally, now that children are marked as used, we can set
5312 // orientation flags:
5313 for (unsigned int face_no : cell->face_indices())
5314 subcells[i]->set_combined_face_orientation(
5315 face_no, inherited_orientations[child_lines[i][face_no]]);
5316
5317 if (i % 2 == 0)
5318 subcells[i]->set_parent(cell->index());
5319 }
5320
5321 // Unlike the same lines on other children, the innermost triangle's
5322 // faces are all in the default orientation:
5323 if (cell->reference_cell() == ReferenceCells::Triangle)
5324 for (unsigned int face_no : cell->face_indices())
5325 subcells[3]->set_combined_face_orientation(
5327
5328 for (unsigned int i = 0; i < n_children / 2; ++i)
5329 cell->set_children(2 * i, subcells[2 * i]->index());
5330
5331 cell->set_refinement_case(ref_case);
5332
5333 if (dim == spacedim - 1)
5334 for (unsigned int c = 0; c < n_children; ++c)
5335 cell->child(c)->set_direction_flag(cell->direction_flag());
5336 };
5337
5338 for (int level = 0;
5339 level < static_cast<int>(triangulation.levels.size()) - 1;
5340 ++level)
5341 {
5343 next_unused_cell = triangulation.begin_raw(level + 1);
5344
5345 for (const auto &cell :
5346 triangulation.active_cell_iterators_on_level(level))
5347 if (cell->refine_flag_set())
5348 {
5349 create_children(triangulation,
5350 next_unused_vertex,
5351 next_unused_line,
5352 next_unused_cell,
5353 cell);
5354
5355 if (cell->reference_cell() == ReferenceCells::Quadrilateral &&
5356 check_for_distorted_cells &&
5357 has_distorted_children<dim, spacedim>(cell))
5358 cells_with_distorted_children.distorted_cells.push_back(
5359 cell);
5360
5361 triangulation.signals.post_refinement_on_cell(cell);
5362 }
5363 }
5364
5365 return cells_with_distorted_children;
5366 }
5367
5368
5369
5374 template <int spacedim>
5377 const bool /*check_for_distorted_cells*/)
5378 {
5379 const unsigned int dim = 1;
5380
5381 // Check whether a new level is needed. We have to check for
5382 // this on the highest level only
5383 for (const auto &cell : triangulation.active_cell_iterators_on_level(
5384 triangulation.levels.size() - 1))
5385 if (cell->refine_flag_set())
5386 {
5387 triangulation.levels.push_back(
5388 std::make_unique<
5390 break;
5391 }
5392
5393
5394 // check how much space is needed on every level. We need not
5395 // check the highest level since either - on the highest level
5396 // no cells are flagged for refinement - there are, but
5397 // prepare_refinement added another empty level
5398 unsigned int needed_vertices = 0;
5399 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5400 {
5401 // count number of flagged
5402 // cells on this level
5403 unsigned int flagged_cells = 0;
5404
5405 for (const auto &acell :
5406 triangulation.active_cell_iterators_on_level(level))
5407 if (acell->refine_flag_set())
5408 ++flagged_cells;
5409
5410 // count number of used cells
5411 // on the next higher level
5412 const unsigned int used_cells =
5413 std::count(triangulation.levels[level + 1]->cells.used.begin(),
5414 triangulation.levels[level + 1]->cells.used.end(),
5415 true);
5416
5417 // reserve space for the used_cells cells already existing
5418 // on the next higher level as well as for the
5419 // 2*flagged_cells that will be created on that level
5420 reserve_space(*triangulation.levels[level + 1],
5422 flagged_cells,
5423 1,
5424 spacedim);
5425 // reserve space for 2*flagged_cells new lines on the next
5426 // higher level
5427 reserve_space(triangulation.levels[level + 1]->cells,
5429 flagged_cells,
5430 0);
5431
5432 needed_vertices += flagged_cells;
5433 }
5434
5435 // add to needed vertices how many
5436 // vertices are already in use
5437 needed_vertices += std::count(triangulation.vertices_used.begin(),
5438 triangulation.vertices_used.end(),
5439 true);
5440 // if we need more vertices: create them, if not: leave the
5441 // array as is, since shrinking is not really possible because
5442 // some of the vertices at the end may be in use
5443 if (needed_vertices > triangulation.vertices.size())
5444 {
5445 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
5446 triangulation.vertices_used.resize(needed_vertices, false);
5447 }
5448
5449
5450 // Do REFINEMENT on every level; exclude highest level as
5451 // above
5452
5453 // index of next unused vertex
5454 unsigned int next_unused_vertex = 0;
5455
5456 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5457 {
5459 next_unused_cell = triangulation.begin_raw(level + 1);
5460
5461 for (const auto &cell :
5462 triangulation.active_cell_iterators_on_level(level))
5463 if (cell->refine_flag_set())
5464 {
5465 // clear refinement flag
5466 cell->clear_refine_flag();
5467
5468 // search for next unused
5469 // vertex
5470 while (triangulation.vertices_used[next_unused_vertex] ==
5471 true)
5472 ++next_unused_vertex;
5473 Assert(
5474 next_unused_vertex < triangulation.vertices.size(),
5475 ExcMessage(
5476 "Internal error: During refinement, the triangulation "
5477 "wants to access an element of the 'vertices' array "
5478 "but it turns out that the array is not large enough."));
5479
5480 // Now we always ask the cell itself where to put
5481 // the new point. The cell in turn will query the
5482 // manifold object internally.
5483 triangulation.vertices[next_unused_vertex] =
5484 cell->center(true);
5485
5486 triangulation.vertices_used[next_unused_vertex] = true;
5487
5488 // search for next two unused cell (++ takes care of
5489 // the end of the vector)
5491 first_child,
5492 second_child;
5493 while (next_unused_cell->used() == true)
5494 ++next_unused_cell;
5495 first_child = next_unused_cell;
5496 first_child->set_used_flag();
5497 first_child->clear_user_data();
5498 ++next_unused_cell;
5499 AssertIsNotUsed(next_unused_cell);
5500 second_child = next_unused_cell;
5501 second_child->set_used_flag();
5502 second_child->clear_user_data();
5503
5504 types::subdomain_id subdomainid = cell->subdomain_id();
5505
5506 // insert first child
5507 cell->set_children(0, first_child->index());
5508 first_child->clear_children();
5509 first_child->set_bounding_object_indices(
5510 {cell->vertex_index(0), next_unused_vertex});
5511 first_child->set_material_id(cell->material_id());
5512 first_child->set_manifold_id(cell->manifold_id());
5513 first_child->set_subdomain_id(subdomainid);
5514 if (dim == spacedim - 1)
5515 first_child->set_direction_flag(cell->direction_flag());
5516
5517 first_child->set_parent(cell->index());
5518
5519 // Set manifold id of the right face. Only do this
5520 // on the first child.
5521 first_child->face(1)->set_manifold_id(cell->manifold_id());
5522
5523 // reset neighborship info (refer to
5524 // internal::TriangulationImplementation::TriaLevel<0> for
5525 // details)
5526 first_child->set_neighbor(1, second_child);
5527 if (cell->neighbor(0).state() != IteratorState::valid)
5528 first_child->set_neighbor(0, cell->neighbor(0));
5529 else if (cell->neighbor(0)->is_active())
5530 {
5531 // since the neighbors level is always <=level,
5532 // if the cell is active, then there are no
5533 // cells to the left which may want to know
5534 // about this new child cell.
5535 Assert(cell->neighbor(0)->level() <= cell->level(),
5537 first_child->set_neighbor(0, cell->neighbor(0));
5538 }
5539 else
5540 // left neighbor is refined
5541 {
5542 // set neighbor to cell on same level
5543 const unsigned int nbnb = cell->neighbor_of_neighbor(0);
5544 first_child->set_neighbor(0,
5545 cell->neighbor(0)->child(nbnb));
5546
5547 // reset neighbor info of all right descendant
5548 // of the left neighbor of cell
5550 left_neighbor = cell->neighbor(0);
5551 while (left_neighbor->has_children())
5552 {
5553 left_neighbor = left_neighbor->child(nbnb);
5554 left_neighbor->set_neighbor(nbnb, first_child);
5555 }
5556 }
5557
5558 // insert second child
5559 second_child->clear_children();
5560 second_child->set_bounding_object_indices(
5561 {next_unused_vertex, cell->vertex_index(1)});
5562 second_child->set_neighbor(0, first_child);
5563 second_child->set_material_id(cell->material_id());
5564 second_child->set_manifold_id(cell->manifold_id());
5565 second_child->set_subdomain_id(subdomainid);
5566 if (dim == spacedim - 1)
5567 second_child->set_direction_flag(cell->direction_flag());
5568
5569 if (cell->neighbor(1).state() != IteratorState::valid)
5570 second_child->set_neighbor(1, cell->neighbor(1));
5571 else if (cell->neighbor(1)->is_active())
5572 {
5573 Assert(cell->neighbor(1)->level() <= cell->level(),
5575 second_child->set_neighbor(1, cell->neighbor(1));
5576 }
5577 else
5578 // right neighbor is refined same as above
5579 {
5580 const unsigned int nbnb = cell->neighbor_of_neighbor(1);
5581 second_child->set_neighbor(
5582 1, cell->neighbor(1)->child(nbnb));
5583
5585 right_neighbor = cell->neighbor(1);
5586 while (right_neighbor->has_children())
5587 {
5588 right_neighbor = right_neighbor->child(nbnb);
5589 right_neighbor->set_neighbor(nbnb, second_child);
5590 }
5591 }
5592 // inform all listeners that cell refinement is done
5593 triangulation.signals.post_refinement_on_cell(cell);
5594 }
5595 }
5596
5597 // in 1d, we can not have distorted children unless the parent
5598 // was already distorted (that is because we don't use
5599 // boundary information for 1d triangulations). so return an
5600 // empty list
5602 }
5603
5604
5609 template <int spacedim>
5612 const bool check_for_distorted_cells)
5613 {
5614 const unsigned int dim = 2;
5615
5616 // First check whether we can get away with isotropic refinement, or
5617 // whether we need to run through the full anisotropic algorithm
5618 {
5619 bool do_isotropic_refinement = true;
5620 for (const auto &cell : triangulation.active_cell_iterators())
5621 if (cell->refine_flag_set() == RefinementCase<dim>::cut_x ||
5622 cell->refine_flag_set() == RefinementCase<dim>::cut_y)
5623 {
5624 do_isotropic_refinement = false;
5625 break;
5626 }
5627
5628 if (do_isotropic_refinement)
5629 return execute_refinement_isotropic(triangulation,
5630 check_for_distorted_cells);
5631 }
5632
5633 // If we get here, we are doing anisotropic refinement.
5634
5635 // Check whether a new level is needed. We have to check for
5636 // this on the highest level only
5637 for (const auto &cell : triangulation.active_cell_iterators_on_level(
5638 triangulation.levels.size() - 1))
5639 if (cell->refine_flag_set())
5640 {
5641 triangulation.levels.push_back(
5642 std::make_unique<
5644 break;
5645 }
5646
5647 // TODO[WB]: we clear user flags and pointers of lines; we're going
5648 // to use them to flag which lines need refinement
5651 line != triangulation.end_line();
5652 ++line)
5653 {
5654 line->clear_user_flag();
5655 line->clear_user_data();
5656 }
5657 // running over all cells and lines count the number
5658 // n_single_lines of lines which can be stored as single
5659 // lines, e.g. inner lines
5660 unsigned int n_single_lines = 0;
5661
5662 // New lines to be created: number lines which are stored in
5663 // pairs (the children of lines must be stored in pairs)
5664 unsigned int n_lines_in_pairs = 0;
5665
5666 // check how much space is needed on every level. We need not
5667 // check the highest level since either - on the highest level
5668 // no cells are flagged for refinement - there are, but
5669 // prepare_refinement added another empty level
5670 unsigned int needed_vertices = 0;
5671 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5672 {
5673 // count number of flagged cells on this level and compute
5674 // how many new vertices and new lines will be needed
5675 unsigned int needed_cells = 0;
5676
5677 for (const auto &cell :
5678 triangulation.active_cell_iterators_on_level(level))
5679 if (cell->refine_flag_set())
5680 {
5681 if (cell->refine_flag_set() == RefinementCase<dim>::cut_xy)
5682 {
5683 needed_cells += 4;
5684
5685 // new vertex at center of cell is needed in any
5686 // case
5687 ++needed_vertices;
5688
5689 // the four inner lines can be stored as singles
5690 n_single_lines += 4;
5691 }
5692 else // cut_x || cut_y
5693 {
5694 // set the flag showing that anisotropic
5695 // refinement is used for at least one cell
5696 triangulation.anisotropic_refinement = true;
5697
5698 needed_cells += 2;
5699 // no vertex at center
5700
5701 // the inner line can be stored as single
5702 n_single_lines += 1;
5703 }
5704
5705 // mark all faces (lines) for refinement; checking
5706 // locally whether the neighbor would also like to
5707 // refine them is rather difficult for lines so we
5708 // only flag them and after visiting all cells, we
5709 // decide which lines need refinement;
5710 for (const unsigned int line_no :
5712 {
5714 cell->refine_flag_set(), line_no) ==
5716 {
5718 line = cell->line(line_no);
5719 if (line->has_children() == false)
5720 line->set_user_flag();
5721 }
5722 }
5723 }
5724
5725
5726 // count number of used cells on the next higher level
5727 const unsigned int used_cells =
5728 std::count(triangulation.levels[level + 1]->cells.used.begin(),
5729 triangulation.levels[level + 1]->cells.used.end(),
5730 true);
5731
5732
5733 // reserve space for the used_cells cells already existing
5734 // on the next higher level as well as for the
5735 // needed_cells that will be created on that level
5736 reserve_space(*triangulation.levels[level + 1],
5737 used_cells + needed_cells,
5738 2,
5739 spacedim);
5740
5741 // reserve space for needed_cells new quads on the next
5742 // higher level
5743 reserve_space(triangulation.levels[level + 1]->cells,
5744 needed_cells,
5745 0);
5746 }
5747
5748 // now count the lines which were flagged for refinement
5751 line != triangulation.end_line();
5752 ++line)
5753 if (line->user_flag_set())
5754 {
5755 Assert(line->has_children() == false, ExcInternalError());
5756 n_lines_in_pairs += 2;
5757 needed_vertices += 1;
5758 }
5759 // reserve space for n_lines_in_pairs new lines. note, that
5760 // we can't reserve space for the single lines here as well,
5761 // as all the space reserved for lines in pairs would be
5762 // counted as unused and we would end up with too little space
5763 // to store all lines. memory reservation for n_single_lines
5764 // can only be done AFTER we refined the lines of the current
5765 // cells
5766 reserve_space(triangulation.faces->lines, n_lines_in_pairs, 0);
5767
5768 // add to needed vertices how many vertices are already in use
5769 needed_vertices += std::count(triangulation.vertices_used.begin(),
5770 triangulation.vertices_used.end(),
5771 true);
5772 // if we need more vertices: create them, if not: leave the
5773 // array as is, since shrinking is not really possible because
5774 // some of the vertices at the end may be in use
5775 if (needed_vertices > triangulation.vertices.size())
5776 {
5777 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
5778 triangulation.vertices_used.resize(needed_vertices, false);
5779 }
5780
5781
5782 // Do REFINEMENT on every level; exclude highest level as
5783 // above
5784
5785 // index of next unused vertex
5786 unsigned int next_unused_vertex = 0;
5787
5788 // first the refinement of lines. children are stored
5789 // pairwise
5790 {
5791 // only active objects can be refined further
5794 endl = triangulation.end_line();
5796 next_unused_line = triangulation.begin_raw_line();
5797
5798 for (; line != endl; ++line)
5799 if (line->user_flag_set())
5800 {
5801 // this line needs to be refined
5802
5803 // find the next unused vertex and set it
5804 // appropriately
5805 while (triangulation.vertices_used[next_unused_vertex] == true)
5806 ++next_unused_vertex;
5807 Assert(
5808 next_unused_vertex < triangulation.vertices.size(),
5809 ExcMessage(
5810 "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."));
5811 triangulation.vertices_used[next_unused_vertex] = true;
5812
5813 triangulation.vertices[next_unused_vertex] = line->center(true);
5814
5815 // now that we created the right point, make up the
5816 // two child lines. To this end, find a pair of
5817 // unused lines
5818 [[maybe_unused]] bool pair_found = false;
5819 for (; next_unused_line != endl; ++next_unused_line)
5820 if (!next_unused_line->used() &&
5821 !(++next_unused_line)->used())
5822 {
5823 // go back to the first of the two unused
5824 // lines
5825 --next_unused_line;
5826 pair_found = true;
5827 break;
5828 }
5829 Assert(pair_found, ExcInternalError());
5830
5831 // there are now two consecutive unused lines, such
5832 // that the children of a line will be consecutive.
5833 // then set the child pointer of the present line
5834 line->set_children(0, next_unused_line->index());
5835
5836 // set the two new lines
5838 children[2] = {next_unused_line, ++next_unused_line};
5839 // some tests; if any of the iterators should be
5840 // invalid, then already dereferencing will fail
5841 AssertIsNotUsed(children[0]);
5842 AssertIsNotUsed(children[1]);
5843
5844 children[0]->set_bounding_object_indices(
5845 {line->vertex_index(0), next_unused_vertex});
5846 children[1]->set_bounding_object_indices(
5847 {next_unused_vertex, line->vertex_index(1)});
5848
5849 children[0]->set_used_flag();
5850 children[1]->set_used_flag();
5851 children[0]->clear_children();
5852 children[1]->clear_children();
5853 children[0]->clear_user_data();
5854 children[1]->clear_user_data();
5855 children[0]->clear_user_flag();
5856 children[1]->clear_user_flag();
5857
5858
5859 children[0]->set_boundary_id_internal(line->boundary_id());
5860 children[1]->set_boundary_id_internal(line->boundary_id());
5861
5862 children[0]->set_manifold_id(line->manifold_id());
5863 children[1]->set_manifold_id(line->manifold_id());
5864
5865 // finally clear flag indicating the need for
5866 // refinement
5867 line->clear_user_flag();
5868 }
5869 }
5870
5871
5872 // Now set up the new cells
5873
5874 // reserve space for inner lines (can be stored as single
5875 // lines)
5876 reserve_space(triangulation.faces->lines, 0, n_single_lines);
5877
5879 cells_with_distorted_children;
5880
5881 // reset next_unused_line, as now also single empty places in
5882 // the vector can be used
5884 next_unused_line = triangulation.begin_raw_line();
5885
5886 for (int level = 0;
5887 level < static_cast<int>(triangulation.levels.size()) - 1;
5888 ++level)
5889 {
5891 next_unused_cell = triangulation.begin_raw(level + 1);
5892
5893 for (const auto &cell :
5894 triangulation.active_cell_iterators_on_level(level))
5895 if (cell->refine_flag_set())
5896 {
5897 // actually set up the children and update neighbor
5898 // information
5899 create_children(triangulation,
5900 next_unused_vertex,
5901 next_unused_line,
5902 next_unused_cell,
5903 cell);
5904
5905 if (check_for_distorted_cells &&
5906 has_distorted_children<dim, spacedim>(cell))
5907 cells_with_distorted_children.distorted_cells.push_back(
5908 cell);
5909 // inform all listeners that cell refinement is done
5910 triangulation.signals.post_refinement_on_cell(cell);
5911 }
5912 }
5913
5914 return cells_with_distorted_children;
5915 }
5916
5917
5918 template <int spacedim>
5921 const bool check_for_distorted_cells)
5922 {
5923 static const int dim = 3;
5924 static const unsigned int X = numbers::invalid_unsigned_int;
5925 using raw_line_iterator =
5927 using raw_quad_iterator =
5929
5930 Assert(spacedim == 3, ExcNotImplemented());
5931
5932 Assert(triangulation.vertices.size() ==
5933 triangulation.vertices_used.size(),
5935
5936 // Check whether a new level is needed. We have to check for
5937 // this on the highest level only
5938 for (const auto &cell : triangulation.active_cell_iterators_on_level(
5939 triangulation.levels.size() - 1))
5940 if (cell->refine_flag_set())
5941 {
5942 triangulation.levels.push_back(
5943 std::make_unique<
5945 break;
5946 }
5947
5948 // first clear user flags for quads and lines; we're going to
5949 // use them to flag which lines and quads need refinement
5950 triangulation.faces->quads.clear_user_data();
5951 triangulation.faces->lines.clear_user_flags();
5952 triangulation.faces->quads.clear_user_flags();
5953
5954 // check how much space is needed on every level. We need not
5955 // check the highest level since either
5956 // - on the highest level no cells are flagged for refinement
5957 // - there are, but prepare_refinement added another empty
5958 // level which then is the highest level
5959
5960 // variables to hold the number of newly to be created
5961 // vertices, lines and quads. as these are stored globally,
5962 // declare them outside the loop over al levels. we need lines
5963 // and quads in pairs for refinement of old ones and lines and
5964 // quads, that can be stored as single ones, as they are newly
5965 // created in the inside of an existing cell
5966 unsigned int needed_vertices = 0;
5967 unsigned int needed_lines_single = 0;
5968 unsigned int needed_quads_single = 0;
5969 unsigned int needed_lines_pair = 0;
5970 unsigned int needed_quads_pair = 0;
5971 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5972 {
5973 unsigned int new_cells = 0;
5974
5975 for (const auto &cell :
5976 triangulation.active_cell_iterators_on_level(level))
5977 if (cell->refine_flag_set())
5978 {
5979 // Only support isotropic refinement
5980 Assert(cell->refine_flag_set() ==
5983
5984 // Now count up how many new cells, faces, edges, and vertices
5985 // we will need to allocate to do this refinement.
5986 new_cells += cell->reference_cell().n_isotropic_children();
5987
5988 if (cell->reference_cell() == ReferenceCells::Hexahedron)
5989 {
5990 ++needed_vertices;
5991 needed_lines_single += 6;
5992 needed_quads_single += 12;
5993 }
5994 else if (cell->reference_cell() ==
5996 {
5997 needed_lines_single += 1;
5998 needed_quads_single += 8;
5999 }
6000 else
6001 {
6003 }
6004
6005 // Also check whether we have to refine any of the faces and
6006 // edges that bound this cell. They may of course already be
6007 // refined, so we only *mark* them for refinement by setting
6008 // the user flags
6009 for (const auto face : cell->face_indices())
6010 if (cell->face(face)->n_children() == 0)
6011 cell->face(face)->set_user_flag();
6012 else
6013 Assert(cell->face(face)->n_children() ==
6014 cell->reference_cell()
6015 .face_reference_cell(face)
6016 .n_isotropic_children(),
6018
6019 for (const auto line : cell->line_indices())
6020 if (cell->line(line)->has_children() == false)
6021 cell->line(line)->set_user_flag();
6022 else
6023 Assert(cell->line(line)->n_children() == 2,
6025 }
6026
6027 const unsigned int used_cells =
6028 std::count(triangulation.levels[level + 1]->cells.used.begin(),
6029 triangulation.levels[level + 1]->cells.used.end(),
6030 true);
6031
6032 if (triangulation.all_reference_cells_are_hyper_cube())
6033 reserve_space(*triangulation.levels[level + 1],
6034 used_cells + new_cells,
6035 3,
6036 spacedim,
6037 false);
6038 else
6039 reserve_space(*triangulation.levels[level + 1],
6040 used_cells + new_cells,
6041 3,
6042 spacedim,
6043 true);
6044
6045 reserve_space(triangulation.levels[level + 1]->cells, new_cells);
6046 }
6047
6048 // now count the quads and lines which were flagged for
6049 // refinement
6052 quad != triangulation.end_quad();
6053 ++quad)
6054 {
6055 if (quad->user_flag_set() == false)
6056 continue;
6057
6058 if (quad->reference_cell() == ReferenceCells::Quadrilateral)
6059 {
6060 needed_quads_pair += 4;
6061 needed_lines_pair += 4;
6062 needed_vertices += 1;
6063 }
6064 else if (quad->reference_cell() == ReferenceCells::Triangle)
6065 {
6066 needed_quads_pair += 4;
6067 needed_lines_single += 3;
6068 }
6069 else
6070 {
6072 }
6073 }
6074
6077 line != triangulation.end_line();
6078 ++line)
6079 {
6080 if (line->user_flag_set() == false)
6081 continue;
6082
6083 needed_lines_pair += 2;
6084 needed_vertices += 1;
6085 }
6086
6087 reserve_space(triangulation.faces->lines,
6088 needed_lines_pair,
6089 needed_lines_single);
6091 needed_quads_pair,
6092 needed_quads_single);
6093 reserve_space(triangulation.faces->quads,
6094 needed_quads_pair,
6095 needed_quads_single);
6096
6097
6098 // add to needed vertices how many vertices are already in use
6099 needed_vertices += std::count(triangulation.vertices_used.begin(),
6100 triangulation.vertices_used.end(),
6101 true);
6102
6103 if (needed_vertices > triangulation.vertices.size())
6104 {
6105 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
6106 triangulation.vertices_used.resize(needed_vertices, false);
6107 }
6108
6109 //-----------------------------------------
6110 // Before we start with the actual refinement, we do some
6111 // sanity checks if in debug mode. especially, we try to catch
6112 // the notorious problem with lines being twice refined,
6113 // i.e. there are cells adjacent at one line ("around the
6114 // edge", but not at a face), with two cells differing by more
6115 // than one refinement level
6116 //
6117 // this check is very simple to implement here, since we have
6118 // all lines flagged if they shall be refined
6119#ifdef DEBUG
6120 for (const auto &cell : triangulation.active_cell_iterators())
6121 if (!cell->refine_flag_set())
6122 for (unsigned int line_n = 0; line_n < cell->n_lines(); ++line_n)
6123 if (cell->line(line_n)->has_children())
6124 for (unsigned int c = 0; c < 2; ++c)
6125 Assert(cell->line(line_n)->child(c)->user_flag_set() == false,
6127#endif
6128
6129 unsigned int current_vertex = 0;
6130
6131 // helper function - find the next available vertex number and mark it
6132 // as used.
6133 auto get_next_unused_vertex = [](const unsigned int current_vertex,
6134 std::vector<bool> &vertices_used) {
6135 unsigned int next_vertex = current_vertex;
6136 while (next_vertex < vertices_used.size() &&
6137 vertices_used[next_vertex] == true)
6138 ++next_vertex;
6139 Assert(next_vertex < vertices_used.size(), ExcInternalError());
6140 vertices_used[next_vertex] = true;
6141
6142 return next_vertex;
6143 };
6144
6145 // LINES
6146 {
6149 endl = triangulation.end_line();
6150 raw_line_iterator next_unused_line = triangulation.begin_raw_line();
6151
6152 for (; line != endl; ++line)
6153 {
6154 if (line->user_flag_set() == false)
6155 continue;
6156
6157 next_unused_line =
6158 triangulation.faces->lines.template next_free_pair_object<1>(
6160 Assert(next_unused_line.state() == IteratorState::valid,
6162
6163 // now we found two consecutive unused lines, such
6164 // that the children of a line will be consecutive.
6165 // then set the child pointer of the present line
6166 line->set_children(0, next_unused_line->index());
6167
6168 const std::array<raw_line_iterator, 2> children{
6169 {next_unused_line, ++next_unused_line}};
6170
6171 AssertIsNotUsed(children[0]);
6172 AssertIsNotUsed(children[1]);
6173
6174 current_vertex =
6175 get_next_unused_vertex(current_vertex,
6176 triangulation.vertices_used);
6177 triangulation.vertices[current_vertex] = line->center(true);
6178
6179 children[0]->set_bounding_object_indices(
6180 {line->vertex_index(0), current_vertex});
6181 children[1]->set_bounding_object_indices(
6182 {current_vertex, line->vertex_index(1)});
6183
6184 const auto manifold_id = line->manifold_id();
6185 const auto boundary_id = line->boundary_id();
6186 for (const auto &child : children)
6187 {
6188 child->set_used_flag();
6189 child->clear_children();
6190 child->clear_user_data();
6191 child->clear_user_flag();
6192 child->set_boundary_id_internal(boundary_id);
6193 child->set_manifold_id(manifold_id);
6194 }
6195
6196 line->clear_user_flag();
6197 }
6198 }
6199
6200 // QUADS
6201 {
6203 quad = triangulation.begin_quad(),
6204 endq = triangulation.end_quad();
6205
6206 for (; quad != endq; ++quad)
6207 {
6208 if (quad->user_flag_set() == false)
6209 continue;
6210
6211 const auto reference_face_type = quad->reference_cell();
6212
6213 // 1) create new lines (property is set later)
6214 // maximum of 4 new lines (4 quadrilateral, 3 triangle)
6215 std::array<raw_line_iterator, 4> new_lines;
6216 if (reference_face_type == ReferenceCells::Quadrilateral)
6217 {
6218 for (unsigned int l = 0; l < 2; ++l)
6219 {
6220 auto next_unused_line =
6221 triangulation.faces->lines
6222 .template next_free_pair_object<1>(triangulation);
6223 new_lines[2 * l] = next_unused_line;
6224 new_lines[2 * l + 1] = ++next_unused_line;
6225 }
6226 }
6227 else if (reference_face_type == ReferenceCells::Triangle)
6228 {
6229 for (unsigned int l = 0; l < 3; ++l)
6230 new_lines[l] =
6231 triangulation.faces->lines
6232 .template next_free_single_object<1>(triangulation);
6233 }
6234 else
6235 {
6237 }
6238
6239#ifdef DEBUG
6240 for (const unsigned int line : quad->line_indices())
6241 AssertIsNotUsed(new_lines[line]);
6242#endif
6243
6244 // 2) create new quads (properties are set below). Both triangles
6245 // and quads are divided in four.
6246 std::array<raw_quad_iterator, 4> new_quads;
6247 for (unsigned int q = 0; q < 2; ++q)
6248 {
6249 auto next_unused_quad =
6250 triangulation.faces->quads
6251 .template next_free_pair_object<2>(triangulation);
6252
6253 new_quads[2 * q] = next_unused_quad;
6254 new_quads[2 * q + 1] = ++next_unused_quad;
6255
6256 quad->set_children(2 * q, new_quads[2 * q]->index());
6257 }
6258 quad->set_refinement_case(RefinementCase<2>::cut_xy);
6259
6260#ifdef DEBUG
6261 for (const auto &quad : new_quads)
6262 AssertIsNotUsed(quad);
6263#endif
6264
6265 // 3) set vertex indices and set new vertex
6266
6267 // Maximum of 9 vertices per refined quad (9 for Quadrilateral, 6
6268 // for Triangle)
6269 std::array<unsigned int, 9> vertex_indices = {};
6270 unsigned int k = 0;
6271 for (const auto i : quad->vertex_indices())
6272 vertex_indices[k++] = quad->vertex_index(i);
6273
6274 for (const auto i : quad->line_indices())
6275 vertex_indices[k++] = quad->line(i)->child(0)->vertex_index(1);
6276
6277 if (reference_face_type == ReferenceCells::Quadrilateral)
6278 {
6279 current_vertex =
6280 get_next_unused_vertex(current_vertex,
6281 triangulation.vertices_used);
6282 vertex_indices[k++] = current_vertex;
6283
6284 triangulation.vertices[current_vertex] =
6285 quad->center(true, true);
6286 }
6287
6288 // 4) set new lines on quads and their properties
6289 std::array<raw_line_iterator, 12> lines;
6290 unsigned int n_lines = 0;
6291 for (unsigned int l = 0; l < quad->n_lines(); ++l)
6292 for (unsigned int c = 0; c < 2; ++c)
6293 {
6294 static constexpr ::ndarray<unsigned int, 2, 2> index =
6295 {{// child 0, line_orientation=false and true
6296 {{1, 0}},
6297 // child 1, line_orientation=false and true
6298 {{0, 1}}}};
6299
6300 lines[n_lines++] =
6301 quad->line(l)->child(index[c][quad->line_orientation(l)]);
6302 }
6303
6304 for (unsigned int l = 0; l < quad->n_lines(); ++l)
6305 lines[n_lines++] = new_lines[l];
6306
6307 std::array<int, 12> line_indices;
6308 for (unsigned int i = 0; i < n_lines; ++i)
6309 line_indices[i] = lines[i]->index();
6310
6311 static constexpr ::ndarray<unsigned int, 12, 2>
6312 line_vertices_quad{{{{0, 4}},
6313 {{4, 2}},
6314 {{1, 5}},
6315 {{5, 3}},
6316 {{0, 6}},
6317 {{6, 1}},
6318 {{2, 7}},
6319 {{7, 3}},
6320 {{6, 8}},
6321 {{8, 7}},
6322 {{4, 8}},
6323 {{8, 5}}}};
6324
6325 static constexpr ::ndarray<unsigned int, 4, 4>
6326 quad_lines_quad{{{{0, 8, 4, 10}},
6327 {{8, 2, 5, 11}},
6328 {{1, 9, 10, 6}},
6329 {{9, 3, 11, 7}}}};
6330
6331 static constexpr ::ndarray<unsigned int, 12, 2>
6332 line_vertices_tri{{{{0, 3}},
6333 {{3, 1}},
6334 {{1, 4}},
6335 {{4, 2}},
6336 {{2, 5}},
6337 {{5, 0}},
6338 {{3, 4}},
6339 {{4, 5}},
6340 {{3, 5}},
6341 {{X, X}},
6342 {{X, X}},
6343 {{X, X}}}};
6344
6345 static constexpr ::ndarray<unsigned int, 4, 4>
6346 quad_lines_tri{{{{0, 8, 5, X}},
6347 {{1, 2, 6, X}},
6348 {{7, 3, 4, X}},
6349 {{6, 7, 8, X}}}};
6350
6351 static constexpr ::ndarray<unsigned int, 4, 4, 2>
6352 quad_line_vertices_tri{
6353 {{{{{0, 3}}, {{3, 5}}, {{5, 0}}, {{X, X}}}},
6354 {{{{3, 1}}, {{1, 4}}, {{4, 3}}, {{X, X}}}},
6355 {{{{5, 4}}, {{4, 2}}, {{2, 5}}, {{X, X}}}},
6356 {{{{3, 4}}, {{4, 5}}, {{5, 3}}, {{X, X}}}}}};
6357
6358 const auto &line_vertices =
6359 (reference_face_type == ReferenceCells::Quadrilateral) ?
6360 line_vertices_quad :
6361 line_vertices_tri;
6362 const auto &quad_lines =
6363 (reference_face_type == ReferenceCells::Quadrilateral) ?
6364 quad_lines_quad :
6365 quad_lines_tri;
6366
6367 for (unsigned int i = 0, j = 2 * quad->n_lines();
6368 i < quad->n_lines();
6369 ++i, ++j)
6370 {
6371 auto &new_line = new_lines[i];
6372 new_line->set_bounding_object_indices(
6373 {vertex_indices[line_vertices[j][0]],
6374 vertex_indices[line_vertices[j][1]]});
6375 new_line->set_used_flag();
6376 new_line->clear_user_flag();
6377 new_line->clear_user_data();
6378 new_line->clear_children();
6379 new_line->set_boundary_id_internal(quad->boundary_id());
6380 new_line->set_manifold_id(quad->manifold_id());
6381 }
6382
6383 // 5) set properties of quads
6384 for (unsigned int i = 0; i < new_quads.size(); ++i)
6385 {
6386 auto &new_quad = new_quads[i];
6387
6388 // TODO: we assume here that all children have the same type
6389 // as the parent
6390 triangulation.faces->set_quad_type(new_quad->index(),
6391 reference_face_type);
6392
6393 if (reference_face_type == ReferenceCells::Triangle)
6394 new_quad->set_bounding_object_indices(
6395 {line_indices[quad_lines[i][0]],
6396 line_indices[quad_lines[i][1]],
6397 line_indices[quad_lines[i][2]]});
6398 else if (reference_face_type == ReferenceCells::Quadrilateral)
6399 new_quad->set_bounding_object_indices(
6400 {line_indices[quad_lines[i][0]],
6401 line_indices[quad_lines[i][1]],
6402 line_indices[quad_lines[i][2]],
6403 line_indices[quad_lines[i][3]]});
6404 else
6406
6407 new_quad->set_used_flag();
6408 new_quad->clear_user_flag();
6409 new_quad->clear_user_data();
6410 new_quad->clear_children();
6411 new_quad->set_boundary_id_internal(quad->boundary_id());
6412 new_quad->set_manifold_id(quad->manifold_id());
6413
6414#ifdef DEBUG
6415 std::set<unsigned int> s;
6416#endif
6417
6418 // ... and fix orientation of lines of face for triangles,
6419 // using an expensive algorithm, quadrilaterals are treated
6420 // a few lines below by a cheaper algorithm
6421 if (reference_face_type == ReferenceCells::Triangle)
6422 {
6423 for (const auto f : new_quad->line_indices())
6424 {
6425 const std::array<unsigned int, 2> vertices_0 = {
6426 {lines[quad_lines[i][f]]->vertex_index(0),
6427 lines[quad_lines[i][f]]->vertex_index(1)}};
6428
6429 const std::array<unsigned int, 2> vertices_1 = {
6430 {vertex_indices[quad_line_vertices_tri[i][f][0]],
6431 vertex_indices[quad_line_vertices_tri[i][f][1]]}};
6432
6433 const auto orientation =
6435 make_array_view(vertices_0),
6436 make_array_view(vertices_1));
6437
6438#ifdef DEBUG
6439 for (const auto i : vertices_0)
6440 s.insert(i);
6441 for (const auto i : vertices_1)
6442 s.insert(i);
6443#endif
6444
6445 new_quad->set_line_orientation(
6446 f,
6447 orientation ==
6449 default_combined_face_orientation());
6450 }
6451#ifdef DEBUG
6452 AssertDimension(s.size(), 3);
6453#endif
6454 }
6455 }
6456
6457 // fix orientation of lines of faces for quadrilaterals with
6458 // cheap algorithm
6459 if (reference_face_type == ReferenceCells::Quadrilateral)
6460 {
6461 static constexpr ::ndarray<unsigned int, 4, 2>
6462 quad_child_boundary_lines{
6463 {{{0, 2}}, {{1, 3}}, {{0, 1}}, {{2, 3}}}};
6464
6465 for (unsigned int i = 0; i < 4; ++i)
6466 for (unsigned int j = 0; j < 2; ++j)
6467 new_quads[quad_child_boundary_lines[i][j]]
6468 ->set_line_orientation(i, quad->line_orientation(i));
6469 }
6470
6471 quad->clear_user_flag();
6472 }
6473 }
6474
6476 cells_with_distorted_children;
6477
6480 for (unsigned int level = 0; level != triangulation.levels.size() - 1;
6481 ++level)
6482 {
6484 next_unused_hex = triangulation.begin_raw_hex(level + 1);
6485 Assert(hex == triangulation.end() ||
6486 hex->level() >= static_cast<int>(level),
6488
6489 for (; hex != triangulation.end() &&
6490 hex->level() == static_cast<int>(level);
6491 ++hex)
6492 {
6493 if (hex->refine_flag_set() ==
6495 continue;
6496
6497 const auto &reference_cell_type = hex->reference_cell();
6498
6499 const RefinementCase<dim> ref_case = hex->refine_flag_set();
6500 hex->clear_refine_flag();
6501 hex->set_refinement_case(ref_case);
6502
6503 unsigned int n_new_lines = 0;
6504 unsigned int n_new_quads = 0;
6505 unsigned int n_new_hexes = 0;
6506
6507 if (reference_cell_type == ReferenceCells::Hexahedron)
6508 {
6509 n_new_lines = 6;
6510 n_new_quads = 12;
6511 n_new_hexes = 8;
6512 }
6513 else if (reference_cell_type == ReferenceCells::Tetrahedron)
6514 {
6515 n_new_lines = 1;
6516 n_new_quads = 8;
6517 n_new_hexes = 8;
6518 }
6519 else
6521
6522 std::array<raw_line_iterator, 6> new_lines;
6523 for (unsigned int i = 0; i < n_new_lines; ++i)
6524 {
6525 new_lines[i] =
6526 triangulation.faces->lines
6527 .template next_free_single_object<1>(triangulation);
6528
6529 AssertIsNotUsed(new_lines[i]);
6530 new_lines[i]->set_used_flag();
6531 new_lines[i]->clear_user_flag();
6532 new_lines[i]->clear_user_data();
6533 new_lines[i]->clear_children();
6534 new_lines[i]->set_boundary_id_internal(
6536 new_lines[i]->set_manifold_id(hex->manifold_id());
6537 }
6538
6539 std::array<raw_quad_iterator, 12> new_quads;
6540 for (unsigned int i = 0; i < n_new_quads; ++i)
6541 {
6542 new_quads[i] =
6543 triangulation.faces->quads
6544 .template next_free_single_object<2>(triangulation);
6545
6546 auto &new_quad = new_quads[i];
6547
6548 // TODO: faces of children have the same type as the faces
6549 // of the parent
6550 triangulation.faces->set_quad_type(
6551 new_quad->index(),
6552 reference_cell_type.face_reference_cell(0));
6553
6554 AssertIsNotUsed(new_quad);
6555 new_quad->set_used_flag();
6556 new_quad->clear_user_flag();
6557 new_quad->clear_user_data();
6558 new_quad->clear_children();
6559 new_quad->set_boundary_id_internal(
6561 new_quad->set_manifold_id(hex->manifold_id());
6562 for (const auto j : new_quads[i]->line_indices())
6563 new_quad->set_line_orientation(j, true);
6564 }
6565
6566 // we always get 8 children per refined cell
6567 std::array<
6569 8>
6570 new_hexes;
6571 {
6572 for (unsigned int i = 0; i < n_new_hexes; ++i)
6573 {
6574 if (i % 2 == 0)
6575 next_unused_hex =
6576 triangulation.levels[level + 1]->cells.next_free_hex(
6577 triangulation, level + 1);
6578 else
6579 ++next_unused_hex;
6580
6581 new_hexes[i] = next_unused_hex;
6582
6583 auto &new_hex = new_hexes[i];
6584
6585 // children have the same type as the parent
6586 triangulation.levels[new_hex->level()]
6587 ->reference_cell[new_hex->index()] =
6588 reference_cell_type;
6589
6590 AssertIsNotUsed(new_hex);
6591 new_hex->set_used_flag();
6592 new_hex->clear_user_flag();
6593 new_hex->clear_user_data();
6594 new_hex->clear_children();
6595 new_hex->set_material_id(hex->material_id());
6596 new_hex->set_manifold_id(hex->manifold_id());
6597 new_hex->set_subdomain_id(hex->subdomain_id());
6598
6599 if (i % 2)
6600 new_hex->set_parent(hex->index());
6601
6602 // set the orientation flag to its default state for all
6603 // faces initially. later on go the other way round and
6604 // reset faces that are at the boundary of the mother cube
6605 for (const auto f : new_hex->face_indices())
6606 new_hex->set_combined_face_orientation(
6607 f,
6609 }
6610 for (unsigned int i = 0; i < n_new_hexes / 2; ++i)
6611 hex->set_children(2 * i, new_hexes[2 * i]->index());
6612 }
6613
6614 {
6615 // load vertex indices
6616 std::array<unsigned int, 27> vertex_indices = {};
6617
6618 {
6619 unsigned int k = 0;
6620
6621 // avoid a compiler warning by fixing the max number of
6622 // loop iterations to 8
6623 const unsigned int n_vertices =
6624 std::min(hex->n_vertices(), 8u);
6625 for (unsigned int i = 0; i < n_vertices; ++i)
6626 vertex_indices[k++] = hex->vertex_index(i);
6627
6628 const std::array<unsigned int, 12> line_indices =
6629 TriaAccessorImplementation::Implementation::
6630 get_line_indices_of_cell(*hex);
6631
6632 // For the tetrahedron the parent consists of the vertices
6633 // 0,1,2,3, the new vertices 4-9 are defined as the
6634 // midpoints of the edges: 4 -> (0,1), 5 -> (1,2), 6 ->
6635 // (2,0), 7 -> (0,3), 8 -> (1,3), 9 -> (2,3).
6636 // Order is defined by the reference cell, see
6637 // https://dealii.org/developer/doxygen/deal.II/group__simplex.html#simplex_reference_cells.
6638
6639 // Avoid a compiler warning by fixing the max number of loop
6640 // iterations to 12
6641 const unsigned int n_lines = std::min(hex->n_lines(), 12u);
6642 for (unsigned int l = 0; l < n_lines; ++l)
6643 {
6644 raw_line_iterator line(&triangulation,
6645 0,
6646 line_indices[l]);
6647 vertex_indices[k++] = line->child(0)->vertex_index(1);
6648 }
6649
6650 if (reference_cell_type == ReferenceCells::Hexahedron)
6651 {
6652 for (const unsigned int i : hex->face_indices())
6653 vertex_indices[k++] =
6654 hex->face(i)->child(0)->vertex_index(3);
6655
6656 // Set single new vertex in the center
6657 current_vertex =
6658 get_next_unused_vertex(current_vertex,
6659 triangulation.vertices_used);
6660 vertex_indices[k++] = current_vertex;
6661
6662 triangulation.vertices[current_vertex] =
6663 hex->center(true, true);
6664 }
6665 }
6666
6667 unsigned int chosen_line_tetrahedron = 0;
6668 // set up new lines
6669 if (reference_cell_type == ReferenceCells::Hexahedron)
6670 {
6671 static constexpr ::ndarray<unsigned int, 6, 2>
6672 new_line_vertices = {{{{22, 26}},
6673 {{26, 23}},
6674 {{20, 26}},
6675 {{26, 21}},
6676 {{24, 26}},
6677 {{26, 25}}}};
6678 for (unsigned int i = 0; i < n_new_lines; ++i)
6679 new_lines[i]->set_bounding_object_indices(
6680 {vertex_indices[new_line_vertices[i][0]],
6681 vertex_indices[new_line_vertices[i][1]]});
6682 }
6683 else if (reference_cell_type == ReferenceCells::Tetrahedron)
6684 {
6685 // in the tetrahedron case, we have the three
6686 // possibilities (6,8), (5,7), (4,9) -> pick the
6687 // shortest line to guarantee the best possible aspect
6688 // ratios
6689 static constexpr ::ndarray<unsigned int, 3, 2>
6690 new_line_vertices = {{{{6, 8}}, {{5, 7}}, {{4, 9}}}};
6691
6692 // choose line to cut either by refinement case or by
6693 // shortest distance between edge midpoints
6694 std::uint8_t refinement_choice = hex->refine_choice();
6695 if (refinement_choice ==
6696 static_cast<char>(
6698 {
6699 const auto &vertices = triangulation.get_vertices();
6700 double min_distance =
6701 std::numeric_limits<double>::infinity();
6702 for (unsigned int i = 0; i < new_line_vertices.size();
6703 ++i)
6704 {
6705 const double current_distance =
6706 vertices
6707 [vertex_indices[new_line_vertices[i][0]]]
6708 .distance(
6709 vertices[vertex_indices
6710 [new_line_vertices[i][1]]]);
6711 if (current_distance < min_distance)
6712 {
6713 chosen_line_tetrahedron = i;
6714 min_distance = current_distance;
6715 }
6716 }
6717 }
6718 else if (refinement_choice ==
6719 static_cast<char>(
6721 chosen_line_tetrahedron = 0;
6722 else if (refinement_choice ==
6723 static_cast<char>(
6725 chosen_line_tetrahedron = 1;
6726 else if (refinement_choice ==
6727 static_cast<char>(
6729 chosen_line_tetrahedron = 2;
6730 else
6732
6733 hex->set_refinement_case(
6734 RefinementCase<dim>(chosen_line_tetrahedron + 1));
6735
6736 new_lines[0]->set_bounding_object_indices(
6738 [new_line_vertices[chosen_line_tetrahedron][0]],
6740 [new_line_vertices[chosen_line_tetrahedron][1]]});
6741 }
6742
6743 // set up new quads
6744 {
6745 boost::container::small_vector<raw_line_iterator, 30>
6746 relevant_lines;
6747
6748 if (reference_cell_type == ReferenceCells::Hexahedron)
6749 {
6750 relevant_lines.resize(30);
6751 for (unsigned int f = 0, k = 0; f < 6; ++f)
6752 for (unsigned int c = 0; c < 4; ++c, ++k)
6753 {
6754 static constexpr ::
6755 ndarray<unsigned int, 4, 2>
6756 temp = {
6757 {{{0, 1}}, {{3, 0}}, {{0, 3}}, {{3, 2}}}};
6758
6759 relevant_lines[k] =
6760 hex->face(f)
6761 ->isotropic_child(
6763 standard_to_real_face_vertex(
6764 temp[c][0],
6765 hex->face_orientation(f),
6766 hex->face_flip(f),
6767 hex->face_rotation(f)))
6768 ->line(GeometryInfo<dim>::
6769 standard_to_real_face_line(
6770 temp[c][1],
6771 hex->face_orientation(f),
6772 hex->face_flip(f),
6773 hex->face_rotation(f)));
6774 }
6775
6776 for (unsigned int i = 0, k = 24; i < 6; ++i, ++k)
6777 relevant_lines[k] = new_lines[i];
6778 }
6779 else if (reference_cell_type == ReferenceCells::Tetrahedron)
6780 {
6781 // The order of the lines is defined by the ordering
6782 // of the faces of the reference cell and the ordering
6783 // of the lines within a face.
6784 // Each face is split into 4 child triangles, the
6785 // relevant lines are defined by the vertices of the
6786 // center triangles: 0 -> (4,5), 1 -> (5,6), 2 -> (4,6),
6787 // 3 -> (4,7), 4 -> (7,8), 5 -> (4,8), 6 -> (6,9), 7 ->
6788 // (9,7), 8 -> (6,7), 9 -> (5,8), 10 -> (8,9), 11 ->
6789 // (5,9), Line 12 is determined by
6790 // chosen_line_tetrahedron i.e. (6,8), (5,7) or (4,9)
6791
6792 relevant_lines.resize(13);
6793
6794 unsigned int k = 0;
6795 for (unsigned int f = 0; f < 4; ++f)
6796 for (unsigned int l = 0; l < 3; ++l, ++k)
6797 {
6798 // TODO: add comment
6799 static const std::
6800 array<std::array<unsigned int, 3>, 6>
6801 table = {{{{1, 0, 2}}, // 0
6802 {{0, 1, 2}},
6803 {{0, 2, 1}}, // 2
6804 {{1, 2, 0}},
6805 {{2, 1, 0}}, // 4
6806 {{2, 0, 1}}}};
6807
6808 const unsigned char combined_orientation =
6809 hex->combined_face_orientation(f);
6810 relevant_lines[k] =
6811 hex->face(f)
6812 ->child(3 /*center triangle*/)
6813 ->line(table[combined_orientation][l]);
6814 }
6815
6816 relevant_lines[k++] = new_lines[0];
6817 AssertDimension(k, 13);
6818 }
6819 else
6821
6822 boost::container::small_vector<unsigned int, 30>
6823 relevant_line_indices(relevant_lines.size());
6824 for (unsigned int i = 0; i < relevant_line_indices.size();
6825 ++i)
6826 relevant_line_indices[i] = relevant_lines[i]->index();
6827
6828 // It is easierst to start at table cell_vertices,
6829 // there the vertices are listed which build up the
6830 // 8 child tets. To build the child tets, 8 new faces are
6831 // needed. The the vertices, which define the lines of these
6832 // new faces are listed in table_tet. Now only the
6833 // corresponding index of the lines and quads have to be
6834 // listed in new_quad_lines_tet and cell_quads_tet.
6835 const auto &new_quad_lines =
6836 hex->reference_cell().new_isotropic_child_face_lines(
6837 chosen_line_tetrahedron);
6838
6839 // The first 4 define the faces which cut off the
6840 // parent tetrahedron at the edges. the numbers are the
6841 // index of the relevant_lines defined above the last 4
6842 // faces cut apart the remaining octahedron, such that all
6843 // of these contain line number 12. the ordering of the
6844 // faces is arbitrary, the ordering within the faces has to
6845 // follow the righthand convention for triangles
6846 // The table defines the vertices of the lines above
6847 // see relevant_lines for mapping between line indices and
6848 // vertex numbering
6849 const auto &table =
6850 hex->reference_cell()
6851 .new_isotropic_child_face_line_vertices(
6852 chosen_line_tetrahedron);
6853
6854 static constexpr ::ndarray<unsigned int, 4, 2>
6855 representative_lines{
6856 {{{0, 2}}, {{2, 0}}, {{3, 3}}, {{1, 1}}}};
6857
6858 for (unsigned int q = 0; q < n_new_quads; ++q)
6859 {
6860 auto &new_quad = new_quads[q];
6861
6862 if (new_quad->n_lines() == 3)
6863 new_quad->set_bounding_object_indices(
6864 {relevant_line_indices[new_quad_lines[q][0]],
6865 relevant_line_indices[new_quad_lines[q][1]],
6866 relevant_line_indices[new_quad_lines[q][2]]});
6867 else if (new_quad->n_lines() == 4)
6868 new_quad->set_bounding_object_indices(
6869 {relevant_line_indices[new_quad_lines[q][0]],
6870 relevant_line_indices[new_quad_lines[q][1]],
6871 relevant_line_indices[new_quad_lines[q][2]],
6872 relevant_line_indices[new_quad_lines[q][3]]});
6873 else
6875
6876 // On hexes, we must only determine a single line
6877 // according to the representative_lines array above
6878 // (this saves expensive operations), for tets we do
6879 // all lines manually
6880 const unsigned int n_compute_lines =
6881 reference_cell_type == ReferenceCells::Hexahedron ?
6882 1 :
6883 new_quad->n_lines();
6884 for (unsigned int line = 0; line < n_compute_lines;
6885 ++line)
6886 {
6887 const unsigned int l =
6888 (reference_cell_type ==
6890 representative_lines[q % 4][0] :
6891 line;
6892
6893 const std::array<unsigned int, 2> vertices_0 = {
6894 {relevant_lines[new_quad_lines[q][l]]
6895 ->vertex_index(0),
6896 relevant_lines[new_quad_lines[q][l]]
6897 ->vertex_index(1)}};
6898
6899 const std::array<unsigned int, 2> vertices_1 = {
6900 {vertex_indices[table[q][l][0]],
6901 vertex_indices[table[q][l][1]]}};
6902
6903 const auto orientation =
6905 make_array_view(vertices_0),
6906 make_array_view(vertices_1));
6907
6908 new_quad->set_line_orientation(
6909 l,
6910 orientation ==
6912 default_combined_face_orientation());
6913
6914 // on a hex, inject the status of the current line
6915 // also to the line on the other quad along the
6916 // same direction
6917 if (reference_cell_type ==
6919 new_quads[representative_lines[q % 4][1] + q -
6920 (q % 4)]
6921 ->set_line_orientation(
6922 l,
6923 orientation ==
6925 default_combined_face_orientation());
6926 }
6927 }
6928 }
6929
6930 // set up new hex
6931 {
6932 std::array<int, 36> quad_indices;
6933
6934 if (reference_cell_type == ReferenceCells::Hexahedron)
6935 {
6936 for (unsigned int i = 0; i < n_new_quads; ++i)
6937 quad_indices[i] = new_quads[i]->index();
6938
6939 for (unsigned int f = 0, k = n_new_quads; f < 6; ++f)
6940 for (unsigned int c = 0; c < 4; ++c, ++k)
6941 quad_indices[k] =
6942 hex->face(f)->isotropic_child_index(
6944 c,
6945 hex->face_orientation(f),
6946 hex->face_flip(f),
6947 hex->face_rotation(f)));
6948 }
6949 else if (reference_cell_type == ReferenceCells::Tetrahedron)
6950 {
6951 // list of the indices of the surfaces which define the
6952 // 8 new tets. the indices 0-7 are the new quads defined
6953 // above (so 0-3 cut off the corners and 4-7 separate
6954 // the remaining octahedral), the indices between 8-11
6955 // are the children of the first face, from 12-15 of the
6956 // second, etc.
6957 for (unsigned int i = 0; i < n_new_quads; ++i)
6958 quad_indices[i] = new_quads[i]->index();
6959
6960 for (unsigned int f = 0, k = n_new_quads; f < 4; ++f)
6961 for (unsigned int c = 0; c < 4; ++c, ++k)
6962 {
6963 const unsigned char combined_orientation =
6964 hex->combined_face_orientation(f);
6965 quad_indices[k] = hex->face(f)->child_index(
6966 (c == 3) ? 3 :
6967 reference_cell_type
6968 .standard_to_real_face_vertex(
6969 c, f, combined_orientation));
6970 }
6971 }
6972 else
6973 {
6975 }
6976
6977 // indices of the faces which define the new tets
6978 // the ordering of the tets is arbitrary
6979 // the first 4 determine the tets cutting of the corners
6980 // the last 4 are ordered after their appearance in the
6981 // faces.
6982 // the ordering within the faces is determined by
6983 // convention for the tetrahedron unit cell, see
6984 // cell_vertices_tet below
6985 const auto &cell_quads =
6986 hex->reference_cell().new_isotropic_child_cell_faces(
6987 chosen_line_tetrahedron);
6988
6989 for (unsigned int c = 0;
6990 c < GeometryInfo<dim>::max_children_per_cell;
6991 ++c)
6992 {
6993 auto &new_hex = new_hexes[c];
6994
6995 if (new_hex->n_faces() == 4)
6996 {
6997 new_hex->set_bounding_object_indices(
6998 {quad_indices[cell_quads[c][0]],
6999 quad_indices[cell_quads[c][1]],
7000 quad_indices[cell_quads[c][2]],
7001 quad_indices[cell_quads[c][3]]});
7002
7003
7004 // for tets, we need to go through the faces and
7005 // figure the orientation out the hard way
7006 for (const auto f : new_hex->face_indices())
7007 {
7008 const auto &face = new_hex->face(f);
7009
7010 Assert(face->n_vertices() == 3,
7012
7013 const std::array<unsigned int, 3> vertices_0 = {
7014 {face->vertex_index(0),
7015 face->vertex_index(1),
7016 face->vertex_index(2)}};
7017
7018 // the 8 child tets are each defined by 4
7019 // vertices the ordering of the tets has to be
7020 // consistent with above the ordering within the
7021 // tets is given by the reference tet i.e.
7022 // looking at the fifth line the first 3
7023 // vertices are given by face 11, the last
7024 // vertex is the remaining of the tet
7025 const auto new_hex_vertices =
7026 hex->reference_cell()
7027 .new_isotropic_child_cell_vertices(
7028 chosen_line_tetrahedron)[c];
7029
7030 // arrange after vertices of the faces of the
7031 // unit cell
7032 const std::array<unsigned int, 3> vertices_1 = {
7033 {
7035 [new_hex_vertices
7037 .face_to_cell_vertices(f, 0, 1)]],
7039 [new_hex_vertices
7041 .face_to_cell_vertices(f, 1, 1)]],
7043 [new_hex_vertices
7045 .face_to_cell_vertices(f, 2, 1)]],
7046 }};
7047
7048 new_hex->set_combined_face_orientation(
7049 f,
7050 face->reference_cell()
7051 .get_combined_orientation(
7052 make_array_view(vertices_1),
7053 make_array_view(vertices_0)));
7054 }
7055 }
7056 else if (new_hex->n_faces() == 6)
7057 new_hex->set_bounding_object_indices(
7058 {quad_indices[cell_quads[c][0]],
7059 quad_indices[cell_quads[c][1]],
7060 quad_indices[cell_quads[c][2]],
7061 quad_indices[cell_quads[c][3]],
7062 quad_indices[cell_quads[c][4]],
7063 quad_indices[cell_quads[c][5]]});
7064 else
7066 }
7067
7068 // for hexes, we can simply inherit the orientation values
7069 // from the parent on the outer faces; the inner faces can
7070 // be skipped as their orientation is always the default
7071 // one set above
7072 static constexpr ::ndarray<unsigned int, 6, 4>
7073 face_to_child_indices_hex{{{{0, 2, 4, 6}},
7074 {{1, 3, 5, 7}},
7075 {{0, 1, 4, 5}},
7076 {{2, 3, 6, 7}},
7077 {{0, 1, 2, 3}},
7078 {{4, 5, 6, 7}}}};
7079 if (hex->n_faces() == 6)
7080 for (const auto f : hex->face_indices())
7081 {
7082 const unsigned char combined_orientation =
7083 hex->combined_face_orientation(f);
7084 for (unsigned int c = 0; c < 4; ++c)
7085 new_hexes[face_to_child_indices_hex[f][c]]
7086 ->set_combined_face_orientation(
7087 f, combined_orientation);
7088 }
7089 }
7090 }
7091
7092 if (check_for_distorted_cells &&
7093 has_distorted_children<dim, spacedim>(hex))
7094 cells_with_distorted_children.distorted_cells.push_back(hex);
7095
7096 triangulation.signals.post_refinement_on_cell(hex);
7097 }
7098 }
7099
7100 triangulation.faces->quads.clear_user_data();
7101
7102 return cells_with_distorted_children;
7103 }
7104
7109 template <int spacedim>
7112 const bool check_for_distorted_cells)
7113 {
7114 const unsigned int dim = 3;
7115
7116 {
7117 bool flag_isotropic_mesh = true;
7119 cell = triangulation.begin(),
7120 endc = triangulation.end();
7121 for (; cell != endc; ++cell)
7122 if (cell->used())
7123 if (triangulation.get_anisotropic_refinement_flag() ||
7124 cell->refine_flag_set() == RefinementCase<dim>::cut_x ||
7125 cell->refine_flag_set() == RefinementCase<dim>::cut_y ||
7126 cell->refine_flag_set() == RefinementCase<dim>::cut_z ||
7127 cell->refine_flag_set() == RefinementCase<dim>::cut_xy ||
7128 cell->refine_flag_set() == RefinementCase<dim>::cut_xz ||
7129 cell->refine_flag_set() == RefinementCase<dim>::cut_yz)
7130 {
7131 flag_isotropic_mesh = false;
7132 break;
7133 }
7134
7135 if (flag_isotropic_mesh)
7136 return execute_refinement_isotropic(triangulation,
7137 check_for_distorted_cells);
7138 }
7139
7140 // this function probably also works for spacedim>3 but it
7141 // isn't tested. it will probably be necessary to pull new
7142 // vertices onto the manifold just as we do for the other
7143 // functions above.
7144 Assert(spacedim == 3, ExcNotImplemented());
7145
7146 // Check whether a new level is needed. We have to check for
7147 // this on the highest level only
7148 for (const auto &cell : triangulation.active_cell_iterators_on_level(
7149 triangulation.levels.size() - 1))
7150 if (cell->refine_flag_set())
7151 {
7152 triangulation.levels.push_back(
7153 std::make_unique<
7155 break;
7156 }
7157
7158
7159 // first clear user flags for quads and lines; we're going to
7160 // use them to flag which lines and quads need refinement
7161 triangulation.faces->quads.clear_user_data();
7162
7165 line != triangulation.end_line();
7166 ++line)
7167 line->clear_user_flag();
7170 quad != triangulation.end_quad();
7171 ++quad)
7172 quad->clear_user_flag();
7173
7174 // create an array of face refine cases. User indices of faces
7175 // will be set to values corresponding with indices in this
7176 // array.
7177 const RefinementCase<dim - 1> face_refinement_cases[4] = {
7178 RefinementCase<dim - 1>::no_refinement,
7179 RefinementCase<dim - 1>::cut_x,
7180 RefinementCase<dim - 1>::cut_y,
7181 RefinementCase<dim - 1>::cut_xy};
7182
7183 // check how much space is needed on every level. We need not
7184 // check the highest level since either
7185 // - on the highest level no cells are flagged for refinement
7186 // - there are, but prepare_refinement added another empty
7187 // level which then is the highest level
7188
7189 // variables to hold the number of newly to be created
7190 // vertices, lines and quads. as these are stored globally,
7191 // declare them outside the loop over al levels. we need lines
7192 // and quads in pairs for refinement of old ones and lines and
7193 // quads, that can be stored as single ones, as they are newly
7194 // created in the inside of an existing cell
7195 unsigned int needed_vertices = 0;
7196 unsigned int needed_lines_single = 0;
7197 unsigned int needed_quads_single = 0;
7198 unsigned int needed_lines_pair = 0;
7199 unsigned int needed_quads_pair = 0;
7200 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
7201 {
7202 // count number of flagged cells on this level and compute
7203 // how many new vertices and new lines will be needed
7204 unsigned int new_cells = 0;
7205
7206 for (const auto &acell :
7207 triangulation.active_cell_iterators_on_level(level))
7208 if (acell->refine_flag_set())
7209 {
7210 RefinementCase<dim> ref_case = acell->refine_flag_set();
7211
7212 // now for interior vertices, lines and quads, which
7213 // are needed in any case
7214 if (ref_case == RefinementCase<dim>::cut_x ||
7215 ref_case == RefinementCase<dim>::cut_y ||
7216 ref_case == RefinementCase<dim>::cut_z)
7217 {
7218 ++needed_quads_single;
7219 new_cells += 2;
7220 triangulation.anisotropic_refinement = true;
7221 }
7222 else if (ref_case == RefinementCase<dim>::cut_xy ||
7223 ref_case == RefinementCase<dim>::cut_xz ||
7224 ref_case == RefinementCase<dim>::cut_yz)
7225 {
7226 ++needed_lines_single;
7227 needed_quads_single += 4;
7228 new_cells += 4;
7229 triangulation.anisotropic_refinement = true;
7230 }
7231 else if (ref_case == RefinementCase<dim>::cut_xyz)
7232 {
7233 ++needed_vertices;
7234 needed_lines_single += 6;
7235 needed_quads_single += 12;
7236 new_cells += 8;
7237 }
7238 else
7239 {
7240 // we should never get here
7242 }
7243
7244 // mark all faces for refinement; checking locally
7245 // if and how the neighbor would like to refine
7246 // these is difficult so we only flag them and after
7247 // visiting all cells, we decide which faces need
7248 // which refinement;
7249 for (const unsigned int face :
7251 {
7253 aface = acell->face(face);
7254 // get the RefineCase this faces has for the
7255 // given RefineCase of the cell
7256 RefinementCase<dim - 1> face_ref_case =
7258 ref_case,
7259 face,
7260 acell->face_orientation(face),
7261 acell->face_flip(face),
7262 acell->face_rotation(face));
7263 // only do something, if this face has to be
7264 // refined
7265 if (face_ref_case)
7266 {
7267 if (face_ref_case ==
7269 {
7270 if (aface->n_active_descendants() < 4)
7271 // we use user_flags to denote needed
7272 // isotropic refinement
7273 aface->set_user_flag();
7274 }
7275 else if (aface->refinement_case() != face_ref_case)
7276 // we use user_indices to denote needed
7277 // anisotropic refinement. note, that we
7278 // can have at most one anisotropic
7279 // refinement case for this face, as
7280 // otherwise prepare_refinement() would
7281 // have changed one of the cells to yield
7282 // isotropic refinement at this
7283 // face. therefore we set the user_index
7284 // uniquely
7285 {
7286 Assert(aface->refinement_case() ==
7288 dim - 1>::isotropic_refinement ||
7289 aface->refinement_case() ==
7292 aface->set_user_index(face_ref_case);
7293 }
7294 }
7295 } // for all faces
7296
7297 // flag all lines, that have to be refined
7298 for (unsigned int line = 0;
7299 line < GeometryInfo<dim>::lines_per_cell;
7300 ++line)
7302 line) &&
7303 !acell->line(line)->has_children())
7304 acell->line(line)->set_user_flag();
7305
7306 } // if refine_flag set and for all cells on this level
7307
7308
7309 // count number of used cells on the next higher level
7310 const unsigned int used_cells =
7311 std::count(triangulation.levels[level + 1]->cells.used.begin(),
7312 triangulation.levels[level + 1]->cells.used.end(),
7313 true);
7314
7315
7316 // reserve space for the used_cells cells already existing
7317 // on the next higher level as well as for the
7318 // 8*flagged_cells that will be created on that level
7319 reserve_space(*triangulation.levels[level + 1],
7320 used_cells + new_cells,
7321 3,
7322 spacedim);
7323 // reserve space for 8*flagged_cells new hexes on the next
7324 // higher level
7325 reserve_space(triangulation.levels[level + 1]->cells, new_cells);
7326 } // for all levels
7327 // now count the quads and lines which were flagged for
7328 // refinement
7331 quad != triangulation.end_quad();
7332 ++quad)
7333 {
7334 if (quad->user_flag_set())
7335 {
7336 // isotropic refinement: 1 interior vertex, 4 quads
7337 // and 4 interior lines. we store the interior lines
7338 // in pairs in case the face is already or will be
7339 // refined anisotropically
7340 needed_quads_pair += 4;
7341 needed_lines_pair += 4;
7342 needed_vertices += 1;
7343 }
7344 if (quad->user_index())
7345 {
7346 // anisotropic refinement: 1 interior
7347 // line and two quads
7348 needed_quads_pair += 2;
7349 needed_lines_single += 1;
7350 // there is a kind of complicated situation here which
7351 // requires our attention. if the quad is refined
7352 // isotropcally, two of the interior lines will get a
7353 // new mother line - the interior line of our
7354 // anisotropically refined quad. if those two lines
7355 // are not consecutive, we cannot do so and have to
7356 // replace them by two lines that are consecutive. we
7357 // try to avoid that situation, but it may happen
7358 // nevertheless through repeated refinement and
7359 // coarsening. thus we have to check here, as we will
7360 // need some additional space to store those new lines
7361 // in case we need them...
7362 if (quad->has_children())
7363 {
7364 Assert(quad->refinement_case() ==
7367 if ((face_refinement_cases[quad->user_index()] ==
7369 (quad->child(0)->line_index(1) + 1 !=
7370 quad->child(2)->line_index(1))) ||
7371 (face_refinement_cases[quad->user_index()] ==
7373 (quad->child(0)->line_index(3) + 1 !=
7374 quad->child(1)->line_index(3))))
7375 needed_lines_pair += 2;
7376 }
7377 }
7378 }
7379
7382 line != triangulation.end_line();
7383 ++line)
7384 if (line->user_flag_set())
7385 {
7386 needed_lines_pair += 2;
7387 needed_vertices += 1;
7388 }
7389
7390 // reserve space for needed_lines new lines stored in pairs
7391 reserve_space(triangulation.faces->lines,
7392 needed_lines_pair,
7393 needed_lines_single);
7394 // reserve space for needed_quads new quads stored in pairs
7396 needed_quads_pair,
7397 needed_quads_single);
7398 reserve_space(triangulation.faces->quads,
7399 needed_quads_pair,
7400 needed_quads_single);
7401
7402
7403 // add to needed vertices how many vertices are already in use
7404 needed_vertices += std::count(triangulation.vertices_used.begin(),
7405 triangulation.vertices_used.end(),
7406 true);
7407 // if we need more vertices: create them, if not: leave the
7408 // array as is, since shrinking is not really possible because
7409 // some of the vertices at the end may be in use
7410 if (needed_vertices > triangulation.vertices.size())
7411 {
7412 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
7413 triangulation.vertices_used.resize(needed_vertices, false);
7414 }
7415
7416
7417 //-----------------------------------------
7418 // Before we start with the actual refinement, we do some
7419 // sanity checks if in debug mode. especially, we try to catch
7420 // the notorious problem with lines being twice refined,
7421 // i.e. there are cells adjacent at one line ("around the
7422 // edge", but not at a face), with two cells differing by more
7423 // than one refinement level
7424 //
7425 // this check is very simple to implement here, since we have
7426 // all lines flagged if they shall be refined
7427#ifdef DEBUG
7428 for (const auto &cell : triangulation.active_cell_iterators())
7429 if (!cell->refine_flag_set())
7430 for (unsigned int line = 0;
7431 line < GeometryInfo<dim>::lines_per_cell;
7432 ++line)
7433 if (cell->line(line)->has_children())
7434 for (unsigned int c = 0; c < 2; ++c)
7435 Assert(cell->line(line)->child(c)->user_flag_set() == false,
7437#endif
7438
7439 //-----------------------------------------
7440 // Do refinement on every level
7441 //
7442 // To make life a bit easier, we first refine those lines and
7443 // quads that were flagged for refinement and then compose the
7444 // newly to be created cells.
7445 //
7446 // index of next unused vertex
7447 unsigned int next_unused_vertex = 0;
7448
7449 // first for lines
7450 {
7451 // only active objects can be refined further
7454 endl = triangulation.end_line();
7456 next_unused_line = triangulation.begin_raw_line();
7457
7458 for (; line != endl; ++line)
7459 if (line->user_flag_set())
7460 {
7461 // this line needs to be refined
7462
7463 // find the next unused vertex and set it
7464 // appropriately
7465 while (triangulation.vertices_used[next_unused_vertex] == true)
7466 ++next_unused_vertex;
7467 Assert(
7468 next_unused_vertex < triangulation.vertices.size(),
7469 ExcMessage(
7470 "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."));
7471 triangulation.vertices_used[next_unused_vertex] = true;
7472
7473 triangulation.vertices[next_unused_vertex] = line->center(true);
7474
7475 // now that we created the right point, make up the
7476 // two child lines (++ takes care of the end of the
7477 // vector)
7478 next_unused_line =
7479 triangulation.faces->lines.template next_free_pair_object<1>(
7481 Assert(next_unused_line.state() == IteratorState::valid,
7483
7484 // now we found two consecutive unused lines, such
7485 // that the children of a line will be consecutive.
7486 // then set the child pointer of the present line
7487 line->set_children(0, next_unused_line->index());
7488
7489 // set the two new lines
7491 children[2] = {next_unused_line, ++next_unused_line};
7492
7493 // some tests; if any of the iterators should be
7494 // invalid, then already dereferencing will fail
7495 AssertIsNotUsed(children[0]);
7496 AssertIsNotUsed(children[1]);
7497
7498 children[0]->set_bounding_object_indices(
7499 {line->vertex_index(0), next_unused_vertex});
7500 children[1]->set_bounding_object_indices(
7501 {next_unused_vertex, line->vertex_index(1)});
7502
7503 children[0]->set_used_flag();
7504 children[1]->set_used_flag();
7505 children[0]->clear_children();
7506 children[1]->clear_children();
7507 children[0]->clear_user_data();
7508 children[1]->clear_user_data();
7509 children[0]->clear_user_flag();
7510 children[1]->clear_user_flag();
7511
7512 children[0]->set_boundary_id_internal(line->boundary_id());
7513 children[1]->set_boundary_id_internal(line->boundary_id());
7514
7515 children[0]->set_manifold_id(line->manifold_id());
7516 children[1]->set_manifold_id(line->manifold_id());
7517
7518 // finally clear flag
7519 // indicating the need
7520 // for refinement
7521 line->clear_user_flag();
7522 }
7523 }
7524
7525
7526 //-------------------------------------
7527 // now refine marked quads
7528 //-------------------------------------
7529
7530 // here we encounter several cases:
7531
7532 // a) the quad is unrefined and shall be refined isotropically
7533
7534 // b) the quad is unrefined and shall be refined
7535 // anisotropically
7536
7537 // c) the quad is unrefined and shall be refined both
7538 // anisotropically and isotropically (this is reduced to case
7539 // b) and then case b) for the children again)
7540
7541 // d) the quad is refined anisotropically and shall be refined
7542 // isotropically (this is reduced to case b) for the
7543 // anisotropic children)
7544
7545 // e) the quad is refined isotropically and shall be refined
7546 // anisotropically (this is transformed to case c), however we
7547 // might have to renumber/rename children...)
7548
7549 // we need a loop in cases c) and d), as the anisotropic
7550 // children might have a lower index than the mother quad
7551 for (unsigned int loop = 0; loop < 2; ++loop)
7552 {
7553 // usually, only active objects can be refined
7554 // further. however, in cases d) and e) that is not true,
7555 // so we have to use 'normal' iterators here
7557 quad = triangulation.begin_quad(),
7558 endq = triangulation.end_quad();
7560 next_unused_line = triangulation.begin_raw_line();
7562 next_unused_quad = triangulation.begin_raw_quad();
7563
7564 for (; quad != endq; ++quad)
7565 {
7566 if (quad->user_index())
7567 {
7568 RefinementCase<dim - 1> aniso_quad_ref_case =
7569 face_refinement_cases[quad->user_index()];
7570 // there is one unlikely event here, where we
7571 // already have refind the face: if the face was
7572 // refined anisotropically and we want to refine
7573 // it isotropically, both children are flagged for
7574 // anisotropic refinement. however, if those
7575 // children were already flagged for anisotropic
7576 // refinement, they might already be processed and
7577 // refined.
7578 if (aniso_quad_ref_case == quad->refinement_case())
7579 continue;
7580
7581 Assert(quad->refinement_case() ==
7583 quad->refinement_case() ==
7586
7587 // this quad needs to be refined anisotropically
7588 Assert(quad->user_index() ==
7590 quad->user_index() ==
7593
7594 // make the new line interior to the quad
7596 new_line;
7597
7598 new_line =
7599 triangulation.faces->lines
7600 .template next_free_single_object<1>(triangulation);
7601 AssertIsNotUsed(new_line);
7602
7603 // first collect the
7604 // indices of the vertices:
7605 // *--1--*
7606 // | | |
7607 // | | | cut_x
7608 // | | |
7609 // *--0--*
7610 //
7611 // *-----*
7612 // | |
7613 // 0-----1 cut_y
7614 // | |
7615 // *-----*
7616 unsigned int vertex_indices[2];
7617 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
7618 {
7619 vertex_indices[0] =
7620 quad->line(2)->child(0)->vertex_index(1);
7621 vertex_indices[1] =
7622 quad->line(3)->child(0)->vertex_index(1);
7623 }
7624 else
7625 {
7626 vertex_indices[0] =
7627 quad->line(0)->child(0)->vertex_index(1);
7628 vertex_indices[1] =
7629 quad->line(1)->child(0)->vertex_index(1);
7630 }
7631
7632 new_line->set_bounding_object_indices(
7634 new_line->set_used_flag();
7635 new_line->clear_user_flag();
7636 new_line->clear_user_data();
7637 new_line->clear_children();
7638 new_line->set_boundary_id_internal(quad->boundary_id());
7639 new_line->set_manifold_id(quad->manifold_id());
7640
7641 // child 0 and 1 of a line are switched if the
7642 // line orientation is false. set up a miniature
7643 // table, indicating which child to take for line
7644 // orientations false and true. first index: child
7645 // index in standard orientation, second index:
7646 // line orientation
7647 const unsigned int index[2][2] = {
7648 {1, 0}, // child 0, line_orientation=false and true
7649 {0, 1}}; // child 1, line_orientation=false and true
7650
7651 // find some space (consecutive) for the two newly
7652 // to be created quads.
7654 new_quads[2];
7655
7656 next_unused_quad =
7657 triangulation.faces->quads
7658 .template next_free_pair_object<2>(triangulation);
7659 new_quads[0] = next_unused_quad;
7660 AssertIsNotUsed(new_quads[0]);
7661
7662 ++next_unused_quad;
7663 new_quads[1] = next_unused_quad;
7664 AssertIsNotUsed(new_quads[1]);
7665
7666 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
7667 {
7668 new_quads[0]->set_bounding_object_indices(
7669 {static_cast<int>(quad->line_index(0)),
7670 new_line->index(),
7671 quad->line(2)
7672 ->child(index[0][quad->line_orientation(2)])
7673 ->index(),
7674 quad->line(3)
7675 ->child(index[0][quad->line_orientation(3)])
7676 ->index()});
7677 new_quads[1]->set_bounding_object_indices(
7678 {new_line->index(),
7679 static_cast<int>(quad->line_index(1)),
7680 quad->line(2)
7681 ->child(index[1][quad->line_orientation(2)])
7682 ->index(),
7683 quad->line(3)
7684 ->child(index[1][quad->line_orientation(3)])
7685 ->index()});
7686 }
7687 else
7688 {
7689 new_quads[0]->set_bounding_object_indices(
7690 {quad->line(0)
7691 ->child(index[0][quad->line_orientation(0)])
7692 ->index(),
7693 quad->line(1)
7694 ->child(index[0][quad->line_orientation(1)])
7695 ->index(),
7696 static_cast<int>(quad->line_index(2)),
7697 new_line->index()});
7698 new_quads[1]->set_bounding_object_indices(
7699 {quad->line(0)
7700 ->child(index[1][quad->line_orientation(0)])
7701 ->index(),
7702 quad->line(1)
7703 ->child(index[1][quad->line_orientation(1)])
7704 ->index(),
7705 new_line->index(),
7706 static_cast<int>(quad->line_index(3))});
7707 }
7708
7709 for (const auto &new_quad : new_quads)
7710 {
7711 new_quad->set_used_flag();
7712 new_quad->clear_user_flag();
7713 new_quad->clear_user_data();
7714 new_quad->clear_children();
7715 new_quad->set_boundary_id_internal(quad->boundary_id());
7716 new_quad->set_manifold_id(quad->manifold_id());
7717 // set all line orientations to true, change
7718 // this after the loop, as we have to consider
7719 // different lines for each child
7720 for (unsigned int j = 0;
7721 j < GeometryInfo<dim>::lines_per_face;
7722 ++j)
7723 new_quad->set_line_orientation(j, true);
7724 }
7725 // now set the line orientation of children of
7726 // outer lines correctly, the lines in the
7727 // interior of the refined quad are automatically
7728 // oriented conforming to the standard
7729 new_quads[0]->set_line_orientation(
7730 0, quad->line_orientation(0));
7731 new_quads[0]->set_line_orientation(
7732 2, quad->line_orientation(2));
7733 new_quads[1]->set_line_orientation(
7734 1, quad->line_orientation(1));
7735 new_quads[1]->set_line_orientation(
7736 3, quad->line_orientation(3));
7737 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
7738 {
7739 new_quads[0]->set_line_orientation(
7740 3, quad->line_orientation(3));
7741 new_quads[1]->set_line_orientation(
7742 2, quad->line_orientation(2));
7743 }
7744 else
7745 {
7746 new_quads[0]->set_line_orientation(
7747 1, quad->line_orientation(1));
7748 new_quads[1]->set_line_orientation(
7749 0, quad->line_orientation(0));
7750 }
7751
7752 // test, whether this face is refined
7753 // isotropically already. if so, set the correct
7754 // children pointers.
7755 if (quad->refinement_case() ==
7756 RefinementCase<dim - 1>::cut_xy)
7757 {
7758 // we will put a new refinemnt level of
7759 // anisotropic refinement between the
7760 // unrefined and isotropically refined quad
7761 // ending up with the same fine quads but
7762 // introducing anisotropically refined ones as
7763 // children of the unrefined quad and mother
7764 // cells of the original fine ones.
7765
7766 // this process includes the creation of a new
7767 // middle line which we will assign as the
7768 // mother line of two of the existing inner
7769 // lines. If those inner lines are not
7770 // consecutive in memory, we won't find them
7771 // later on, so we have to create new ones
7772 // instead and replace all occurrences of the
7773 // old ones with those new ones. As this is
7774 // kind of ugly, we hope we don't have to do
7775 // it often...
7777 old_child[2];
7778 if (aniso_quad_ref_case ==
7780 {
7781 old_child[0] = quad->child(0)->line(1);
7782 old_child[1] = quad->child(2)->line(1);
7783 }
7784 else
7785 {
7786 Assert(aniso_quad_ref_case ==
7789
7790 old_child[0] = quad->child(0)->line(3);
7791 old_child[1] = quad->child(1)->line(3);
7792 }
7793
7794 if (old_child[0]->index() + 1 != old_child[1]->index())
7795 {
7796 // this is exactly the ugly case we talked
7797 // about. so, no complaining, lets get
7798 // two new lines and copy all info
7799 typename Triangulation<dim,
7800 spacedim>::raw_line_iterator
7801 new_child[2];
7802
7803 new_child[0] = new_child[1] =
7804 triangulation.faces->lines
7805 .template next_free_pair_object<1>(
7807 ++new_child[1];
7808
7809 new_child[0]->set_used_flag();
7810 new_child[1]->set_used_flag();
7811
7812 const int old_index_0 = old_child[0]->index(),
7813 old_index_1 = old_child[1]->index(),
7814 new_index_0 = new_child[0]->index(),
7815 new_index_1 = new_child[1]->index();
7816
7817 // loop over all quads and replace the old
7818 // lines
7819 for (unsigned int q = 0;
7820 q < triangulation.faces->quads.n_objects();
7821 ++q)
7822 for (unsigned int l = 0;
7823 l < GeometryInfo<dim>::lines_per_face;
7824 ++l)
7825 {
7826 const int this_index =
7827 triangulation.faces->quads
7828 .get_bounding_object_indices(q)[l];
7829 if (this_index == old_index_0)
7830 triangulation.faces->quads
7831 .get_bounding_object_indices(q)[l] =
7832 new_index_0;
7833 else if (this_index == old_index_1)
7834 triangulation.faces->quads
7835 .get_bounding_object_indices(q)[l] =
7836 new_index_1;
7837 }
7838 // now we have to copy all information of
7839 // the two lines
7840 for (unsigned int i = 0; i < 2; ++i)
7841 {
7842 Assert(!old_child[i]->has_children(),
7844
7845 new_child[i]->set_bounding_object_indices(
7846 {old_child[i]->vertex_index(0),
7847 old_child[i]->vertex_index(1)});
7848 new_child[i]->set_boundary_id_internal(
7849 old_child[i]->boundary_id());
7850 new_child[i]->set_manifold_id(
7851 old_child[i]->manifold_id());
7852 new_child[i]->set_user_index(
7853 old_child[i]->user_index());
7854 if (old_child[i]->user_flag_set())
7855 new_child[i]->set_user_flag();
7856 else
7857 new_child[i]->clear_user_flag();
7858
7859 new_child[i]->clear_children();
7860
7861 old_child[i]->clear_user_flag();
7862 old_child[i]->clear_user_index();
7863 old_child[i]->clear_used_flag();
7864 }
7865 }
7866 // now that we cared about the lines, go on
7867 // with the quads themselves, where we might
7868 // encounter similar situations...
7869 if (aniso_quad_ref_case ==
7871 {
7872 new_line->set_children(
7873 0, quad->child(0)->line_index(1));
7874 Assert(new_line->child(1) ==
7875 quad->child(2)->line(1),
7877 // now evereything is quite
7878 // complicated. we have the children
7879 // numbered according to
7880 //
7881 // *---*---*
7882 // |n+2|n+3|
7883 // *---*---*
7884 // | n |n+1|
7885 // *---*---*
7886 //
7887 // from the original isotropic
7888 // refinement. we have to reorder them as
7889 //
7890 // *---*---*
7891 // |n+1|n+3|
7892 // *---*---*
7893 // | n |n+2|
7894 // *---*---*
7895 //
7896 // such that n and n+1 are consecutive
7897 // children of m and n+2 and n+3 are
7898 // consecutive children of m+1, where m
7899 // and m+1 are given as in
7900 //
7901 // *---*---*
7902 // | | |
7903 // | m |m+1|
7904 // | | |
7905 // *---*---*
7906 //
7907 // this is a bit ugly, of course: loop
7908 // over all cells on all levels and look
7909 // for faces n+1 (switch_1) and n+2
7910 // (switch_2).
7911 const typename Triangulation<dim, spacedim>::
7912 quad_iterator switch_1 = quad->child(1),
7913 switch_2 = quad->child(2);
7914 const int switch_1_index = switch_1->index();
7915 const int switch_2_index = switch_2->index();
7916 for (unsigned int l = 0;
7917 l < triangulation.levels.size();
7918 ++l)
7919 for (unsigned int h = 0;
7920 h <
7921 triangulation.levels[l]->cells.n_objects();
7922 ++h)
7923 for (const unsigned int q :
7925 {
7926 const int face_index =
7928 ->cells.get_bounding_object_indices(
7929 h)[q];
7930 if (face_index == switch_1_index)
7931 triangulation.levels[l]
7932 ->cells.get_bounding_object_indices(
7933 h)[q] = switch_2_index;
7934 else if (face_index == switch_2_index)
7935 triangulation.levels[l]
7936 ->cells.get_bounding_object_indices(
7937 h)[q] = switch_1_index;
7938 }
7939 // now we have to copy all information of
7940 // the two quads
7941 const unsigned int switch_1_lines[4] = {
7942 switch_1->line_index(0),
7943 switch_1->line_index(1),
7944 switch_1->line_index(2),
7945 switch_1->line_index(3)};
7946 const bool switch_1_line_orientations[4] = {
7947 switch_1->line_orientation(0),
7948 switch_1->line_orientation(1),
7949 switch_1->line_orientation(2),
7950 switch_1->line_orientation(3)};
7951 const types::boundary_id switch_1_boundary_id =
7952 switch_1->boundary_id();
7953 const unsigned int switch_1_user_index =
7954 switch_1->user_index();
7955 const bool switch_1_user_flag =
7956 switch_1->user_flag_set();
7957 const RefinementCase<dim - 1>
7958 switch_1_refinement_case =
7959 switch_1->refinement_case();
7960 const int switch_1_first_child_pair =
7961 (switch_1_refinement_case ?
7962 switch_1->child_index(0) :
7963 -1);
7964 const int switch_1_second_child_pair =
7965 (switch_1_refinement_case ==
7966 RefinementCase<dim - 1>::cut_xy ?
7967 switch_1->child_index(2) :
7968 -1);
7969
7970 switch_1->set_bounding_object_indices(
7971 {switch_2->line_index(0),
7972 switch_2->line_index(1),
7973 switch_2->line_index(2),
7974 switch_2->line_index(3)});
7975 switch_1->set_line_orientation(
7976 0, switch_2->line_orientation(0));
7977 switch_1->set_line_orientation(
7978 1, switch_2->line_orientation(1));
7979 switch_1->set_line_orientation(
7980 2, switch_2->line_orientation(2));
7981 switch_1->set_line_orientation(
7982 3, switch_2->line_orientation(3));
7983 switch_1->set_boundary_id_internal(
7984 switch_2->boundary_id());
7985 switch_1->set_manifold_id(switch_2->manifold_id());
7986 switch_1->set_user_index(switch_2->user_index());
7987 if (switch_2->user_flag_set())
7988 switch_1->set_user_flag();
7989 else
7990 switch_1->clear_user_flag();
7991 switch_1->clear_refinement_case();
7992 switch_1->set_refinement_case(
7993 switch_2->refinement_case());
7994 switch_1->clear_children();
7995 if (switch_2->refinement_case())
7996 switch_1->set_children(0,
7997 switch_2->child_index(0));
7998 if (switch_2->refinement_case() ==
7999 RefinementCase<dim - 1>::cut_xy)
8000 switch_1->set_children(2,
8001 switch_2->child_index(2));
8002
8003 switch_2->set_bounding_object_indices(
8004 {switch_1_lines[0],
8005 switch_1_lines[1],
8006 switch_1_lines[2],
8007 switch_1_lines[3]});
8008 switch_2->set_line_orientation(
8009 0, switch_1_line_orientations[0]);
8010 switch_2->set_line_orientation(
8011 1, switch_1_line_orientations[1]);
8012 switch_2->set_line_orientation(
8013 2, switch_1_line_orientations[2]);
8014 switch_2->set_line_orientation(
8015 3, switch_1_line_orientations[3]);
8016 switch_2->set_boundary_id_internal(
8017 switch_1_boundary_id);
8018 switch_2->set_manifold_id(switch_1->manifold_id());
8019 switch_2->set_user_index(switch_1_user_index);
8020 if (switch_1_user_flag)
8021 switch_2->set_user_flag();
8022 else
8023 switch_2->clear_user_flag();
8024 switch_2->clear_refinement_case();
8025 switch_2->set_refinement_case(
8026 switch_1_refinement_case);
8027 switch_2->clear_children();
8028 switch_2->set_children(0,
8029 switch_1_first_child_pair);
8030 switch_2->set_children(2,
8031 switch_1_second_child_pair);
8032
8033 new_quads[0]->set_refinement_case(
8035 new_quads[0]->set_children(0, quad->child_index(0));
8036 new_quads[1]->set_refinement_case(
8038 new_quads[1]->set_children(0, quad->child_index(2));
8039 }
8040 else
8041 {
8042 new_quads[0]->set_refinement_case(
8044 new_quads[0]->set_children(0, quad->child_index(0));
8045 new_quads[1]->set_refinement_case(
8047 new_quads[1]->set_children(0, quad->child_index(2));
8048 new_line->set_children(
8049 0, quad->child(0)->line_index(3));
8050 Assert(new_line->child(1) ==
8051 quad->child(1)->line(3),
8053 }
8054 quad->clear_children();
8055 }
8056
8057 // note these quads as children to the present one
8058 quad->set_children(0, new_quads[0]->index());
8059
8060 quad->set_refinement_case(aniso_quad_ref_case);
8061
8062 // finally clear flag indicating the need for
8063 // refinement
8064 quad->clear_user_data();
8065 } // if (anisotropic refinement)
8066
8067 if (quad->user_flag_set())
8068 {
8069 // this quad needs to be refined isotropically
8070
8071 // first of all: we only get here in the first run
8072 // of the loop
8073 Assert(loop == 0, ExcInternalError());
8074
8075 // find the next unused vertex. we'll need this in
8076 // any case
8077 while (triangulation.vertices_used[next_unused_vertex] ==
8078 true)
8079 ++next_unused_vertex;
8080 Assert(
8081 next_unused_vertex < triangulation.vertices.size(),
8082 ExcMessage(
8083 "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."));
8084
8085 // now: if the quad is refined anisotropically
8086 // already, set the anisotropic refinement flag
8087 // for both children. Additionally, we have to
8088 // refine the inner line, as it is an outer line
8089 // of the two (anisotropic) children
8090 const RefinementCase<dim - 1> quad_ref_case =
8091 quad->refinement_case();
8092
8093 if (quad_ref_case == RefinementCase<dim - 1>::cut_x ||
8094 quad_ref_case == RefinementCase<dim - 1>::cut_y)
8095 {
8096 // set the 'opposite' refine case for children
8097 quad->child(0)->set_user_index(
8098 RefinementCase<dim - 1>::cut_xy - quad_ref_case);
8099 quad->child(1)->set_user_index(
8100 RefinementCase<dim - 1>::cut_xy - quad_ref_case);
8101 // refine the inner line
8103 middle_line;
8104 if (quad_ref_case == RefinementCase<dim - 1>::cut_x)
8105 middle_line = quad->child(0)->line(1);
8106 else
8107 middle_line = quad->child(0)->line(3);
8108
8109 // if the face has been refined
8110 // anisotropically in the last refinement step
8111 // it might be, that it is flagged already and
8112 // that the middle line is thus refined
8113 // already. if not create children.
8114 if (!middle_line->has_children())
8115 {
8116 // set the middle vertex
8117 // appropriately. double refinement of
8118 // quads can only happen in the interior
8119 // of the domain, so we need not care
8120 // about boundary quads here
8121 triangulation.vertices[next_unused_vertex] =
8122 middle_line->center(true);
8123 triangulation.vertices_used[next_unused_vertex] =
8124 true;
8125
8126 // now search a slot for the two
8127 // child lines
8128 next_unused_line =
8129 triangulation.faces->lines
8130 .template next_free_pair_object<1>(
8132
8133 // set the child pointer of the present
8134 // line
8135 middle_line->set_children(
8136 0, next_unused_line->index());
8137
8138 // set the two new lines
8139 const typename Triangulation<dim, spacedim>::
8140 raw_line_iterator children[2] = {
8141 next_unused_line, ++next_unused_line};
8142
8143 // some tests; if any of the iterators
8144 // should be invalid, then already
8145 // dereferencing will fail
8146 AssertIsNotUsed(children[0]);
8147 AssertIsNotUsed(children[1]);
8148
8149 children[0]->set_bounding_object_indices(
8150 {middle_line->vertex_index(0),
8151 next_unused_vertex});
8152 children[1]->set_bounding_object_indices(
8153 {next_unused_vertex,
8154 middle_line->vertex_index(1)});
8155
8156 children[0]->set_used_flag();
8157 children[1]->set_used_flag();
8158 children[0]->clear_children();
8159 children[1]->clear_children();
8160 children[0]->clear_user_data();
8161 children[1]->clear_user_data();
8162 children[0]->clear_user_flag();
8163 children[1]->clear_user_flag();
8164
8165 children[0]->set_boundary_id_internal(
8166 middle_line->boundary_id());
8167 children[1]->set_boundary_id_internal(
8168 middle_line->boundary_id());
8169
8170 children[0]->set_manifold_id(
8171 middle_line->manifold_id());
8172 children[1]->set_manifold_id(
8173 middle_line->manifold_id());
8174 }
8175 // now remove the flag from the quad and go to
8176 // the next quad, the actual refinement of the
8177 // quad takes place later on in this pass of
8178 // the loop or in the next one
8179 quad->clear_user_flag();
8180 continue;
8181 } // if (several refinement cases)
8182
8183 // if we got here, we have an unrefined quad and
8184 // have to do the usual work like in an purely
8185 // isotropic refinement
8186 Assert(quad_ref_case ==
8189
8190 // set the middle vertex appropriately: it might be that
8191 // the quad itself is not at the boundary, but that one of
8192 // its lines actually is. in this case, the newly created
8193 // vertices at the centers of the lines are not
8194 // necessarily the mean values of the adjacent vertices,
8195 // so do not compute the new vertex as the mean value of
8196 // the 4 vertices of the face, but rather as a weighted
8197 // mean value of the 8 vertices which we already have (the
8198 // four old ones, and the four ones inserted as middle
8199 // points for the four lines). summing up some more points
8200 // is generally cheaper than first asking whether one of
8201 // the lines is at the boundary
8202 //
8203 // note that the exact weights are chosen such as to
8204 // minimize the distortion of the four new quads from the
8205 // optimal shape. their description uses the formulas
8206 // underlying the TransfiniteInterpolationManifold
8207 // implementation
8208 triangulation.vertices[next_unused_vertex] =
8209 quad->center(true, true);
8210 triangulation.vertices_used[next_unused_vertex] = true;
8211
8212 // now that we created the right point, make up
8213 // the four lines interior to the quad (++ takes
8214 // care of the end of the vector)
8216 new_lines[4];
8217
8218 for (unsigned int i = 0; i < 4; ++i)
8219 {
8220 if (i % 2 == 0)
8221 // search a free pair of lines for 0. and
8222 // 2. line, so that two of them end up
8223 // together, which is necessary if later on
8224 // we want to refine the quad
8225 // anisotropically and the two lines end up
8226 // as children of new line
8227 next_unused_line =
8228 triangulation.faces->lines
8229 .template next_free_pair_object<1>(triangulation);
8230
8231 new_lines[i] = next_unused_line;
8232 ++next_unused_line;
8233
8234 AssertIsNotUsed(new_lines[i]);
8235 }
8236
8237 // set the data of the four lines. first collect
8238 // the indices of the five vertices:
8239 //
8240 // *--3--*
8241 // | | |
8242 // 0--4--1
8243 // | | |
8244 // *--2--*
8245 //
8246 // the lines are numbered as follows:
8247 //
8248 // *--*--*
8249 // | 1 |
8250 // *2-*-3*
8251 // | 0 |
8252 // *--*--*
8253
8254 const unsigned int vertex_indices[5] = {
8255 quad->line(0)->child(0)->vertex_index(1),
8256 quad->line(1)->child(0)->vertex_index(1),
8257 quad->line(2)->child(0)->vertex_index(1),
8258 quad->line(3)->child(0)->vertex_index(1),
8259 next_unused_vertex};
8260
8261 new_lines[0]->set_bounding_object_indices(
8263 new_lines[1]->set_bounding_object_indices(
8265 new_lines[2]->set_bounding_object_indices(
8267 new_lines[3]->set_bounding_object_indices(
8269
8270 for (const auto &new_line : new_lines)
8271 {
8272 new_line->set_used_flag();
8273 new_line->clear_user_flag();
8274 new_line->clear_user_data();
8275 new_line->clear_children();
8276 new_line->set_boundary_id_internal(quad->boundary_id());
8277 new_line->set_manifold_id(quad->manifold_id());
8278 }
8279
8280 // now for the quads. again, first collect some
8281 // data about the indices of the lines, with the
8282 // following numbering:
8283 //
8284 // .-6-.-7-.
8285 // 1 9 3
8286 // .-10.11-.
8287 // 0 8 2
8288 // .-4-.-5-.
8289
8290 // child 0 and 1 of a line are switched if the
8291 // line orientation is false. set up a miniature
8292 // table, indicating which child to take for line
8293 // orientations false and true. first index: child
8294 // index in standard orientation, second index:
8295 // line orientation
8296 const unsigned int index[2][2] = {
8297 {1, 0}, // child 0, line_orientation=false and true
8298 {0, 1}}; // child 1, line_orientation=false and true
8299
8300 const int line_indices[12] = {
8301 quad->line(0)
8302 ->child(index[0][quad->line_orientation(0)])
8303 ->index(),
8304 quad->line(0)
8305 ->child(index[1][quad->line_orientation(0)])
8306 ->index(),
8307 quad->line(1)
8308 ->child(index[0][quad->line_orientation(1)])
8309 ->index(),
8310 quad->line(1)
8311 ->child(index[1][quad->line_orientation(1)])
8312 ->index(),
8313 quad->line(2)
8314 ->child(index[0][quad->line_orientation(2)])
8315 ->index(),
8316 quad->line(2)
8317 ->child(index[1][quad->line_orientation(2)])
8318 ->index(),
8319 quad->line(3)
8320 ->child(index[0][quad->line_orientation(3)])
8321 ->index(),
8322 quad->line(3)
8323 ->child(index[1][quad->line_orientation(3)])
8324 ->index(),
8325 new_lines[0]->index(),
8326 new_lines[1]->index(),
8327 new_lines[2]->index(),
8328 new_lines[3]->index()};
8329
8330 // find some space (consecutive)
8331 // for the first two newly to be
8332 // created quads.
8334 new_quads[4];
8335
8336 next_unused_quad =
8337 triangulation.faces->quads
8338 .template next_free_pair_object<2>(triangulation);
8339
8340 new_quads[0] = next_unused_quad;
8341 AssertIsNotUsed(new_quads[0]);
8342
8343 ++next_unused_quad;
8344 new_quads[1] = next_unused_quad;
8345 AssertIsNotUsed(new_quads[1]);
8346
8347 next_unused_quad =
8348 triangulation.faces->quads
8349 .template next_free_pair_object<2>(triangulation);
8350 new_quads[2] = next_unused_quad;
8351 AssertIsNotUsed(new_quads[2]);
8352
8353 ++next_unused_quad;
8354 new_quads[3] = next_unused_quad;
8355 AssertIsNotUsed(new_quads[3]);
8356
8357 // note these quads as children to the present one
8358 quad->set_children(0, new_quads[0]->index());
8359 quad->set_children(2, new_quads[2]->index());
8360 quad->set_refinement_case(RefinementCase<2>::cut_xy);
8361
8362 new_quads[0]->set_bounding_object_indices(
8363 {line_indices[0],
8364 line_indices[8],
8365 line_indices[4],
8366 line_indices[10]});
8367 new_quads[1]->set_bounding_object_indices(
8368 {line_indices[8],
8369 line_indices[2],
8370 line_indices[5],
8371 line_indices[11]});
8372 new_quads[2]->set_bounding_object_indices(
8373 {line_indices[1],
8374 line_indices[9],
8375 line_indices[10],
8376 line_indices[6]});
8377 new_quads[3]->set_bounding_object_indices(
8378 {line_indices[9],
8379 line_indices[3],
8380 line_indices[11],
8381 line_indices[7]});
8382 for (const auto &new_quad : new_quads)
8383 {
8384 new_quad->set_used_flag();
8385 new_quad->clear_user_flag();
8386 new_quad->clear_user_data();
8387 new_quad->clear_children();
8388 new_quad->set_boundary_id_internal(quad->boundary_id());
8389 new_quad->set_manifold_id(quad->manifold_id());
8390 // set all line orientations to true, change
8391 // this after the loop, as we have to consider
8392 // different lines for each child
8393 for (unsigned int j = 0;
8394 j < GeometryInfo<dim>::lines_per_face;
8395 ++j)
8396 new_quad->set_line_orientation(j, true);
8397 }
8398 // now set the line orientation of children of
8399 // outer lines correctly, the lines in the
8400 // interior of the refined quad are automatically
8401 // oriented conforming to the standard
8402 new_quads[0]->set_line_orientation(
8403 0, quad->line_orientation(0));
8404 new_quads[0]->set_line_orientation(
8405 2, quad->line_orientation(2));
8406 new_quads[1]->set_line_orientation(
8407 1, quad->line_orientation(1));
8408 new_quads[1]->set_line_orientation(
8409 2, quad->line_orientation(2));
8410 new_quads[2]->set_line_orientation(
8411 0, quad->line_orientation(0));
8412 new_quads[2]->set_line_orientation(
8413 3, quad->line_orientation(3));
8414 new_quads[3]->set_line_orientation(
8415 1, quad->line_orientation(1));
8416 new_quads[3]->set_line_orientation(
8417 3, quad->line_orientation(3));
8418
8419 // finally clear flag indicating the need for
8420 // refinement
8421 quad->clear_user_flag();
8422 } // if (isotropic refinement)
8423 } // for all quads
8424 } // looped two times over all quads, all quads refined now
8425
8426 //---------------------------------
8427 // Now, finally, set up the new
8428 // cells
8429 //---------------------------------
8430
8432 cells_with_distorted_children;
8433
8434 for (unsigned int level = 0; level != triangulation.levels.size() - 1;
8435 ++level)
8436 {
8437 // only active objects can be refined further; remember
8438 // that we won't operate on the finest level, so
8439 // triangulation.begin_*(level+1) is allowed
8442 endh = triangulation.begin_active_hex(level + 1);
8444 next_unused_hex = triangulation.begin_raw_hex(level + 1);
8445
8446 for (; hex != endh; ++hex)
8447 if (hex->refine_flag_set())
8448 {
8449 // this hex needs to be refined
8450
8451 // clear flag indicating the need for refinement. do
8452 // it here already, since we can't do it anymore
8453 // once the cell has children
8454 const RefinementCase<dim> ref_case = hex->refine_flag_set();
8455 hex->clear_refine_flag();
8456 hex->set_refinement_case(ref_case);
8457
8458 // depending on the refine case we might have to
8459 // create additional vertices, lines and quads
8460 // interior of the hex before the actual children
8461 // can be set up.
8462
8463 // in a first step: reserve the needed space for
8464 // lines, quads and hexes and initialize them
8465 // correctly
8466
8467 unsigned int n_new_lines = 0;
8468 unsigned int n_new_quads = 0;
8469 unsigned int n_new_hexes = 0;
8470 switch (ref_case)
8471 {
8475 n_new_lines = 0;
8476 n_new_quads = 1;
8477 n_new_hexes = 2;
8478 break;
8482 n_new_lines = 1;
8483 n_new_quads = 4;
8484 n_new_hexes = 4;
8485 break;
8487 n_new_lines = 6;
8488 n_new_quads = 12;
8489 n_new_hexes = 8;
8490 break;
8491 default:
8493 break;
8494 }
8495
8496 // find some space for the newly to be created
8497 // interior lines and initialize them.
8498 std::vector<
8500 new_lines(n_new_lines);
8501 for (unsigned int i = 0; i < n_new_lines; ++i)
8502 {
8503 new_lines[i] =
8504 triangulation.faces->lines
8505 .template next_free_single_object<1>(triangulation);
8506
8507 AssertIsNotUsed(new_lines[i]);
8508 new_lines[i]->set_used_flag();
8509 new_lines[i]->clear_user_flag();
8510 new_lines[i]->clear_user_data();
8511 new_lines[i]->clear_children();
8512 // interior line
8513 new_lines[i]->set_boundary_id_internal(
8515 // they inherit geometry description of the hex they
8516 // belong to
8517 new_lines[i]->set_manifold_id(hex->manifold_id());
8518 }
8519
8520 // find some space for the newly to be created
8521 // interior quads and initialize them.
8522 std::vector<
8524 new_quads(n_new_quads);
8525 for (unsigned int i = 0; i < n_new_quads; ++i)
8526 {
8527 new_quads[i] =
8528 triangulation.faces->quads
8529 .template next_free_single_object<2>(triangulation);
8530
8531 AssertIsNotUsed(new_quads[i]);
8532 new_quads[i]->set_used_flag();
8533 new_quads[i]->clear_user_flag();
8534 new_quads[i]->clear_user_data();
8535 new_quads[i]->clear_children();
8536 // interior quad
8537 new_quads[i]->set_boundary_id_internal(
8539 // they inherit geometry description of the hex they
8540 // belong to
8541 new_quads[i]->set_manifold_id(hex->manifold_id());
8542 // set all line orientation flags to true by
8543 // default, change this afterwards, if necessary
8544 for (unsigned int j = 0;
8545 j < GeometryInfo<dim>::lines_per_face;
8546 ++j)
8547 new_quads[i]->set_line_orientation(j, true);
8548 }
8549
8550 types::subdomain_id subdomainid = hex->subdomain_id();
8551
8552 // find some space for the newly to be created hexes
8553 // and initialize them.
8554 std::vector<
8556 new_hexes(n_new_hexes);
8557 for (unsigned int i = 0; i < n_new_hexes; ++i)
8558 {
8559 if (i % 2 == 0)
8560 next_unused_hex =
8561 triangulation.levels[level + 1]->cells.next_free_hex(
8562 triangulation, level + 1);
8563 else
8564 ++next_unused_hex;
8565
8566 new_hexes[i] = next_unused_hex;
8567
8568 AssertIsNotUsed(new_hexes[i]);
8569 new_hexes[i]->set_used_flag();
8570 new_hexes[i]->clear_user_flag();
8571 new_hexes[i]->clear_user_data();
8572 new_hexes[i]->clear_children();
8573 // inherit material
8574 // properties
8575 new_hexes[i]->set_material_id(hex->material_id());
8576 new_hexes[i]->set_manifold_id(hex->manifold_id());
8577 new_hexes[i]->set_subdomain_id(subdomainid);
8578
8579 if (i % 2)
8580 new_hexes[i]->set_parent(hex->index());
8581 // set the face_orientation flag to true for all
8582 // faces initially, as this is the default value
8583 // which is true for all faces interior to the
8584 // hex. later on go the other way round and
8585 // reset faces that are at the boundary of the
8586 // mother cube
8587 //
8588 // the same is true for the face_flip and
8589 // face_rotation flags. however, the latter two
8590 // are set to false by default as this is the
8591 // standard value
8592 for (const unsigned int f :
8594 new_hexes[i]->set_combined_face_orientation(
8595 f,
8597 }
8598 // note these hexes as children to the present cell
8599 for (unsigned int i = 0; i < n_new_hexes / 2; ++i)
8600 hex->set_children(2 * i, new_hexes[2 * i]->index());
8601
8602 // we have to take into account whether the
8603 // different faces are oriented correctly or in the
8604 // opposite direction, so store that up front
8605
8606 // face_orientation
8607 const bool f_or[6] = {hex->face_orientation(0),
8608 hex->face_orientation(1),
8609 hex->face_orientation(2),
8610 hex->face_orientation(3),
8611 hex->face_orientation(4),
8612 hex->face_orientation(5)};
8613
8614 // face_flip
8615 const bool f_fl[6] = {hex->face_flip(0),
8616 hex->face_flip(1),
8617 hex->face_flip(2),
8618 hex->face_flip(3),
8619 hex->face_flip(4),
8620 hex->face_flip(5)};
8621
8622 // face_rotation
8623 const bool f_ro[6] = {hex->face_rotation(0),
8624 hex->face_rotation(1),
8625 hex->face_rotation(2),
8626 hex->face_rotation(3),
8627 hex->face_rotation(4),
8628 hex->face_rotation(5)};
8629
8630 // combined orientation
8631 const unsigned char f_co[6] = {
8632 hex->combined_face_orientation(0),
8633 hex->combined_face_orientation(1),
8634 hex->combined_face_orientation(2),
8635 hex->combined_face_orientation(3),
8636 hex->combined_face_orientation(4),
8637 hex->combined_face_orientation(5)};
8638
8639 // little helper table, indicating, whether the
8640 // child with index 0 or with index 1 can be found
8641 // at the standard origin of an anisotropically
8642 // refined quads in real orientation index 1:
8643 // (RefineCase - 1) index 2: face_flip
8644
8645 // index 3: face rotation
8646 // note: face orientation has no influence
8647 const unsigned int child_at_origin[2][2][2] = {
8648 {{0, 0}, // RefinementCase<dim>::cut_x, face_flip=false,
8649 // face_rotation=false and true
8650 {1, 1}}, // RefinementCase<dim>::cut_x, face_flip=true,
8651 // face_rotation=false and true
8652 {{0, 1}, // RefinementCase<dim>::cut_y, face_flip=false,
8653 // face_rotation=false and true
8654 {1, 0}}}; // RefinementCase<dim>::cut_y, face_flip=true,
8655 // face_rotation=false and true
8656
8657 //-------------------------------------
8658 //
8659 // in the following we will do the same thing for
8660 // each refinement case: create a new vertex (if
8661 // needed), create new interior lines (if needed),
8662 // create new interior quads and afterwards build
8663 // the children hexes out of these and the existing
8664 // subfaces of the outer quads (which have been
8665 // created above). However, even if the steps are
8666 // quite similar, the actual work strongly depends
8667 // on the actual refinement case. therefore, we use
8668 // separate blocks of code for each of these cases,
8669 // which hopefully increases the readability to some
8670 // extend.
8671
8672 switch (ref_case)
8673 {
8675 {
8676 //----------------------------
8677 //
8678 // RefinementCase<dim>::cut_x
8679 //
8680 // the refined cube will look
8681 // like this:
8682 //
8683 // *----*----*
8684 // / / /|
8685 // / / / |
8686 // / / / |
8687 // *----*----* |
8688 // | | | |
8689 // | | | *
8690 // | | | /
8691 // | | | /
8692 // | | |/
8693 // *----*----*
8694 //
8695 // again, first collect some data about the
8696 // indices of the lines, with the following
8697 // numbering:
8698
8699 // face 2: front plane
8700 // (note: x,y exchanged)
8701 // *---*---*
8702 // | | |
8703 // | 0 |
8704 // | | |
8705 // *---*---*
8706 // m0
8707 // face 3: back plane
8708 // (note: x,y exchanged)
8709 // m1
8710 // *---*---*
8711 // | | |
8712 // | 1 |
8713 // | | |
8714 // *---*---*
8715 // face 4: bottom plane
8716 // *---*---*
8717 // / / /
8718 // / 2 /
8719 // / / /
8720 // *---*---*
8721 // m0
8722 // face 5: top plane
8723 // m1
8724 // *---*---*
8725 // / / /
8726 // / 3 /
8727 // / / /
8728 // *---*---*
8729
8730 // set up a list of line iterators first. from
8731 // this, construct lists of line_indices and
8732 // line orientations later on
8733 const typename Triangulation<dim, spacedim>::
8734 raw_line_iterator lines[4] = {
8735 hex->face(2)->child(0)->line(
8736 (hex->face(2)->refinement_case() ==
8738 1 :
8739 3), // 0
8740 hex->face(3)->child(0)->line(
8741 (hex->face(3)->refinement_case() ==
8743 1 :
8744 3), // 1
8745 hex->face(4)->child(0)->line(
8746 (hex->face(4)->refinement_case() ==
8748 1 :
8749 3), // 2
8750 hex->face(5)->child(0)->line(
8751 (hex->face(5)->refinement_case() ==
8753 1 :
8754 3) // 3
8755 };
8756
8757 unsigned int line_indices[4];
8758 for (unsigned int i = 0; i < 4; ++i)
8759 line_indices[i] = lines[i]->index();
8760
8761 // the orientation of lines for the inner quads
8762 // is quite tricky. as these lines are newly
8763 // created ones and thus have no parents, they
8764 // cannot inherit this property. set up an array
8765 // and fill it with the respective values
8766 bool line_orientation[4];
8767
8768 // the middle vertex marked as m0 above is the
8769 // start vertex for lines 0 and 2 in standard
8770 // orientation, whereas m1 is the end vertex of
8771 // lines 1 and 3 in standard orientation
8772 const unsigned int middle_vertices[2] = {
8773 hex->line(2)->child(0)->vertex_index(1),
8774 hex->line(7)->child(0)->vertex_index(1)};
8775
8776 for (unsigned int i = 0; i < 4; ++i)
8777 if (lines[i]->vertex_index(i % 2) ==
8778 middle_vertices[i % 2])
8779 line_orientation[i] = true;
8780 else
8781 {
8782 // it must be the other
8783 // way round then
8784 Assert(lines[i]->vertex_index((i + 1) % 2) ==
8785 middle_vertices[i % 2],
8787 line_orientation[i] = false;
8788 }
8789
8790 // set up the new quad, line numbering is as
8791 // indicated above
8792 new_quads[0]->set_bounding_object_indices(
8793 {line_indices[0],
8794 line_indices[1],
8795 line_indices[2],
8796 line_indices[3]});
8797
8798 new_quads[0]->set_line_orientation(
8799 0, line_orientation[0]);
8800 new_quads[0]->set_line_orientation(
8801 1, line_orientation[1]);
8802 new_quads[0]->set_line_orientation(
8803 2, line_orientation[2]);
8804 new_quads[0]->set_line_orientation(
8805 3, line_orientation[3]);
8806
8807 // the quads are numbered as follows:
8808 //
8809 // planes in the interior of the old hex:
8810 //
8811 // *
8812 // /|
8813 // / | x
8814 // / | *-------* *---------*
8815 // * | | | / /
8816 // | 0 | | | / /
8817 // | * | | / /
8818 // | / *-------*y *---------*x
8819 // | /
8820 // |/
8821 // *
8822 //
8823 // children of the faces of the old hex
8824 //
8825 // *---*---* *---*---*
8826 // /| | | / / /|
8827 // / | | | / 9 / 10/ |
8828 // / | 5 | 6 | / / / |
8829 // * | | | *---*---* |
8830 // | 1 *---*---* | | | 2 *
8831 // | / / / | | | /
8832 // | / 7 / 8 / | 3 | 4 | /
8833 // |/ / / | | |/
8834 // *---*---* *---*---*
8835 //
8836 // note that we have to take care of the
8837 // orientation of faces.
8838 const int quad_indices[11] = {
8839 new_quads[0]->index(), // 0
8840
8841 hex->face(0)->index(), // 1
8842
8843 hex->face(1)->index(), // 2
8844
8845 hex->face(2)->child_index(
8846 child_at_origin[hex->face(2)->refinement_case() -
8847 1][f_fl[2]][f_ro[2]]), // 3
8848 hex->face(2)->child_index(
8849 1 -
8850 child_at_origin[hex->face(2)->refinement_case() -
8851 1][f_fl[2]][f_ro[2]]),
8852
8853 hex->face(3)->child_index(
8854 child_at_origin[hex->face(3)->refinement_case() -
8855 1][f_fl[3]][f_ro[3]]), // 5
8856 hex->face(3)->child_index(
8857 1 -
8858 child_at_origin[hex->face(3)->refinement_case() -
8859 1][f_fl[3]][f_ro[3]]),
8860
8861 hex->face(4)->child_index(
8862 child_at_origin[hex->face(4)->refinement_case() -
8863 1][f_fl[4]][f_ro[4]]), // 7
8864 hex->face(4)->child_index(
8865 1 -
8866 child_at_origin[hex->face(4)->refinement_case() -
8867 1][f_fl[4]][f_ro[4]]),
8868
8869 hex->face(5)->child_index(
8870 child_at_origin[hex->face(5)->refinement_case() -
8871 1][f_fl[5]][f_ro[5]]), // 9
8872 hex->face(5)->child_index(
8873 1 -
8874 child_at_origin[hex->face(5)->refinement_case() -
8875 1][f_fl[5]][f_ro[5]])
8876
8877 };
8878
8879 new_hexes[0]->set_bounding_object_indices(
8880 {quad_indices[1],
8881 quad_indices[0],
8882 quad_indices[3],
8883 quad_indices[5],
8884 quad_indices[7],
8885 quad_indices[9]});
8886 new_hexes[1]->set_bounding_object_indices(
8887 {quad_indices[0],
8888 quad_indices[2],
8889 quad_indices[4],
8890 quad_indices[6],
8891 quad_indices[8],
8892 quad_indices[10]});
8893 break;
8894 }
8895
8897 {
8898 //----------------------------
8899 //
8900 // RefinementCase<dim>::cut_y
8901 //
8902 // the refined cube will look like this:
8903 //
8904 // *---------*
8905 // / /|
8906 // *---------* |
8907 // / /| |
8908 // *---------* | |
8909 // | | | |
8910 // | | | *
8911 // | | |/
8912 // | | *
8913 // | |/
8914 // *---------*
8915 //
8916 // again, first collect some data about the
8917 // indices of the lines, with the following
8918 // numbering:
8919
8920 // face 0: left plane
8921 // *
8922 // /|
8923 // * |
8924 // /| |
8925 // * | |
8926 // | 0 |
8927 // | | *
8928 // | |/
8929 // | *m0
8930 // |/
8931 // *
8932 // face 1: right plane
8933 // *
8934 // /|
8935 // m1* |
8936 // /| |
8937 // * | |
8938 // | 1 |
8939 // | | *
8940 // | |/
8941 // | *
8942 // |/
8943 // *
8944 // face 4: bottom plane
8945 // *-------*
8946 // / /
8947 // m0*---2---*
8948 // / /
8949 // *-------*
8950 // face 5: top plane
8951 // *-------*
8952 // / /
8953 // *---3---*m1
8954 // / /
8955 // *-------*
8956
8957 // set up a list of line iterators first. from
8958 // this, construct lists of line_indices and
8959 // line orientations later on
8960 const typename Triangulation<dim, spacedim>::
8961 raw_line_iterator lines[4] = {
8962 hex->face(0)->child(0)->line(
8963 (hex->face(0)->refinement_case() ==
8965 1 :
8966 3), // 0
8967 hex->face(1)->child(0)->line(
8968 (hex->face(1)->refinement_case() ==
8970 1 :
8971 3), // 1
8972 hex->face(4)->child(0)->line(
8973 (hex->face(4)->refinement_case() ==
8975 1 :
8976 3), // 2
8977 hex->face(5)->child(0)->line(
8978 (hex->face(5)->refinement_case() ==
8980 1 :
8981 3) // 3
8982 };
8983
8984 unsigned int line_indices[4];
8985 for (unsigned int i = 0; i < 4; ++i)
8986 line_indices[i] = lines[i]->index();
8987
8988 // the orientation of lines for the inner quads
8989 // is quite tricky. as these lines are newly
8990 // created ones and thus have no parents, they
8991 // cannot inherit this property. set up an array
8992 // and fill it with the respective values
8993 bool line_orientation[4];
8994
8995 // the middle vertex marked as m0 above is the
8996 // start vertex for lines 0 and 2 in standard
8997 // orientation, whereas m1 is the end vertex of
8998 // lines 1 and 3 in standard orientation
8999 const unsigned int middle_vertices[2] = {
9000 hex->line(0)->child(0)->vertex_index(1),
9001 hex->line(5)->child(0)->vertex_index(1)};
9002
9003 for (unsigned int i = 0; i < 4; ++i)
9004 if (lines[i]->vertex_index(i % 2) ==
9005 middle_vertices[i % 2])
9006 line_orientation[i] = true;
9007 else
9008 {
9009 // it must be the other way round then
9010 Assert(lines[i]->vertex_index((i + 1) % 2) ==
9011 middle_vertices[i % 2],
9013 line_orientation[i] = false;
9014 }
9015
9016 // set up the new quad, line numbering is as
9017 // indicated above
9018 new_quads[0]->set_bounding_object_indices(
9019 {line_indices[2],
9020 line_indices[3],
9021 line_indices[0],
9022 line_indices[1]});
9023
9024 new_quads[0]->set_line_orientation(
9025 0, line_orientation[2]);
9026 new_quads[0]->set_line_orientation(
9027 1, line_orientation[3]);
9028 new_quads[0]->set_line_orientation(
9029 2, line_orientation[0]);
9030 new_quads[0]->set_line_orientation(
9031 3, line_orientation[1]);
9032
9033 // the quads are numbered as follows:
9034 //
9035 // planes in the interior of the old hex:
9036 //
9037 // *
9038 // /|
9039 // / | x
9040 // / | *-------* *---------*
9041 // * | | | / /
9042 // | | | 0 | / /
9043 // | * | | / /
9044 // | / *-------*y *---------*x
9045 // | /
9046 // |/
9047 // *
9048 //
9049 // children of the faces of the old hex
9050 //
9051 // *-------* *-------*
9052 // /| | / 10 /|
9053 // * | | *-------* |
9054 // /| | 6 | / 9 /| |
9055 // * |2| | *-------* |4|
9056 // | | *-------* | | | *
9057 // |1|/ 8 / | |3|/
9058 // | *-------* | 5 | *
9059 // |/ 7 / | |/
9060 // *-------* *-------*
9061 //
9062 // note that we have to take care of the
9063 // orientation of faces.
9064 const int quad_indices[11] = {
9065 new_quads[0]->index(), // 0
9066
9067 hex->face(0)->child_index(
9068 child_at_origin[hex->face(0)->refinement_case() -
9069 1][f_fl[0]][f_ro[0]]), // 1
9070 hex->face(0)->child_index(
9071 1 -
9072 child_at_origin[hex->face(0)->refinement_case() -
9073 1][f_fl[0]][f_ro[0]]),
9074
9075 hex->face(1)->child_index(
9076 child_at_origin[hex->face(1)->refinement_case() -
9077 1][f_fl[1]][f_ro[1]]), // 3
9078 hex->face(1)->child_index(
9079 1 -
9080 child_at_origin[hex->face(1)->refinement_case() -
9081 1][f_fl[1]][f_ro[1]]),
9082
9083 hex->face(2)->index(), // 5
9084
9085 hex->face(3)->index(), // 6
9086
9087 hex->face(4)->child_index(
9088 child_at_origin[hex->face(4)->refinement_case() -
9089 1][f_fl[4]][f_ro[4]]), // 7
9090 hex->face(4)->child_index(
9091 1 -
9092 child_at_origin[hex->face(4)->refinement_case() -
9093 1][f_fl[4]][f_ro[4]]),
9094
9095 hex->face(5)->child_index(
9096 child_at_origin[hex->face(5)->refinement_case() -
9097 1][f_fl[5]][f_ro[5]]), // 9
9098 hex->face(5)->child_index(
9099 1 -
9100 child_at_origin[hex->face(5)->refinement_case() -
9101 1][f_fl[5]][f_ro[5]])
9102
9103 };
9104
9105 new_hexes[0]->set_bounding_object_indices(
9106 {quad_indices[1],
9107 quad_indices[3],
9108 quad_indices[5],
9109 quad_indices[0],
9110 quad_indices[7],
9111 quad_indices[9]});
9112 new_hexes[1]->set_bounding_object_indices(
9113 {quad_indices[2],
9114 quad_indices[4],
9115 quad_indices[0],
9116 quad_indices[6],
9117 quad_indices[8],
9118 quad_indices[10]});
9119 break;
9120 }
9121
9123 {
9124 //----------------------------
9125 //
9126 // RefinementCase<dim>::cut_z
9127 //
9128 // the refined cube will look like this:
9129 //
9130 // *---------*
9131 // / /|
9132 // / / |
9133 // / / *
9134 // *---------* /|
9135 // | | / |
9136 // | |/ *
9137 // *---------* /
9138 // | | /
9139 // | |/
9140 // *---------*
9141 //
9142 // again, first collect some data about the
9143 // indices of the lines, with the following
9144 // numbering:
9145
9146 // face 0: left plane
9147 // *
9148 // /|
9149 // / |
9150 // / *
9151 // * /|
9152 // | 0 |
9153 // |/ *
9154 // m0* /
9155 // | /
9156 // |/
9157 // *
9158 // face 1: right plane
9159 // *
9160 // /|
9161 // / |
9162 // / *m1
9163 // * /|
9164 // | 1 |
9165 // |/ *
9166 // * /
9167 // | /
9168 // |/
9169 // *
9170 // face 2: front plane
9171 // (note: x,y exchanged)
9172 // *-------*
9173 // | |
9174 // m0*---2---*
9175 // | |
9176 // *-------*
9177 // face 3: back plane
9178 // (note: x,y exchanged)
9179 // *-------*
9180 // | |
9181 // *---3---*m1
9182 // | |
9183 // *-------*
9184
9185 // set up a list of line iterators first. from
9186 // this, construct lists of line_indices and
9187 // line orientations later on
9188 const typename Triangulation<dim, spacedim>::
9189 raw_line_iterator lines[4] = {
9190 hex->face(0)->child(0)->line(
9191 (hex->face(0)->refinement_case() ==
9193 1 :
9194 3), // 0
9195 hex->face(1)->child(0)->line(
9196 (hex->face(1)->refinement_case() ==
9198 1 :
9199 3), // 1
9200 hex->face(2)->child(0)->line(
9201 (hex->face(2)->refinement_case() ==
9203 1 :
9204 3), // 2
9205 hex->face(3)->child(0)->line(
9206 (hex->face(3)->refinement_case() ==
9208 1 :
9209 3) // 3
9210 };
9211
9212 unsigned int line_indices[4];
9213 for (unsigned int i = 0; i < 4; ++i)
9214 line_indices[i] = lines[i]->index();
9215
9216 // the orientation of lines for the inner quads
9217 // is quite tricky. as these lines are newly
9218 // created ones and thus have no parents, they
9219 // cannot inherit this property. set up an array
9220 // and fill it with the respective values
9221 bool line_orientation[4];
9222
9223 // the middle vertex marked as m0 above is the
9224 // start vertex for lines 0 and 2 in standard
9225 // orientation, whereas m1 is the end vertex of
9226 // lines 1 and 3 in standard orientation
9227 const unsigned int middle_vertices[2] = {
9228 middle_vertex_index<dim, spacedim>(hex->line(8)),
9229 middle_vertex_index<dim, spacedim>(hex->line(11))};
9230
9231 for (unsigned int i = 0; i < 4; ++i)
9232 if (lines[i]->vertex_index(i % 2) ==
9233 middle_vertices[i % 2])
9234 line_orientation[i] = true;
9235 else
9236 {
9237 // it must be the other way round then
9238 Assert(lines[i]->vertex_index((i + 1) % 2) ==
9239 middle_vertices[i % 2],
9241 line_orientation[i] = false;
9242 }
9243
9244 // set up the new quad, line numbering is as
9245 // indicated above
9246 new_quads[0]->set_bounding_object_indices(
9247 {line_indices[0],
9248 line_indices[1],
9249 line_indices[2],
9250 line_indices[3]});
9251
9252 new_quads[0]->set_line_orientation(
9253 0, line_orientation[0]);
9254 new_quads[0]->set_line_orientation(
9255 1, line_orientation[1]);
9256 new_quads[0]->set_line_orientation(
9257 2, line_orientation[2]);
9258 new_quads[0]->set_line_orientation(
9259 3, line_orientation[3]);
9260
9261 // the quads are numbered as follows:
9262 //
9263 // planes in the interior of the old hex:
9264 //
9265 // *
9266 // /|
9267 // / | x
9268 // / | *-------* *---------*
9269 // * | | | / /
9270 // | | | | / 0 /
9271 // | * | | / /
9272 // | / *-------*y *---------*x
9273 // | /
9274 // |/
9275 // *
9276 //
9277 // children of the faces of the old hex
9278 //
9279 // *---*---* *-------*
9280 // /| 8 | / /|
9281 // / | | / 10 / |
9282 // / *-------* / / *
9283 // * 2/| | *-------* 4/|
9284 // | / | 7 | | 6 | / |
9285 // |/1 *-------* | |/3 *
9286 // * / / *-------* /
9287 // | / 9 / | | /
9288 // |/ / | 5 |/
9289 // *-------* *---*---*
9290 //
9291 // note that we have to take care of the
9292 // orientation of faces.
9293 const int quad_indices[11] = {
9294 new_quads[0]->index(), // 0
9295
9296 hex->face(0)->child_index(
9297 child_at_origin[hex->face(0)->refinement_case() -
9298 1][f_fl[0]][f_ro[0]]), // 1
9299 hex->face(0)->child_index(
9300 1 -
9301 child_at_origin[hex->face(0)->refinement_case() -
9302 1][f_fl[0]][f_ro[0]]),
9303
9304 hex->face(1)->child_index(
9305 child_at_origin[hex->face(1)->refinement_case() -
9306 1][f_fl[1]][f_ro[1]]), // 3
9307 hex->face(1)->child_index(
9308 1 -
9309 child_at_origin[hex->face(1)->refinement_case() -
9310 1][f_fl[1]][f_ro[1]]),
9311
9312 hex->face(2)->child_index(
9313 child_at_origin[hex->face(2)->refinement_case() -
9314 1][f_fl[2]][f_ro[2]]), // 5
9315 hex->face(2)->child_index(
9316 1 -
9317 child_at_origin[hex->face(2)->refinement_case() -
9318 1][f_fl[2]][f_ro[2]]),
9319
9320 hex->face(3)->child_index(
9321 child_at_origin[hex->face(3)->refinement_case() -
9322 1][f_fl[3]][f_ro[3]]), // 7
9323 hex->face(3)->child_index(
9324 1 -
9325 child_at_origin[hex->face(3)->refinement_case() -
9326 1][f_fl[3]][f_ro[3]]),
9327
9328 hex->face(4)->index(), // 9
9329
9330 hex->face(5)->index() // 10
9331 };
9332
9333 new_hexes[0]->set_bounding_object_indices(
9334 {quad_indices[1],
9335 quad_indices[3],
9336 quad_indices[5],
9337 quad_indices[7],
9338 quad_indices[9],
9339 quad_indices[0]});
9340 new_hexes[1]->set_bounding_object_indices(
9341 {quad_indices[2],
9342 quad_indices[4],
9343 quad_indices[6],
9344 quad_indices[8],
9345 quad_indices[0],
9346 quad_indices[10]});
9347 break;
9348 }
9349
9351 {
9352 //----------------------------
9353 //
9354 // RefinementCase<dim>::cut_xy
9355 //
9356 // the refined cube will look like this:
9357 //
9358 // *----*----*
9359 // / / /|
9360 // *----*----* |
9361 // / / /| |
9362 // *----*----* | |
9363 // | | | | |
9364 // | | | | *
9365 // | | | |/
9366 // | | | *
9367 // | | |/
9368 // *----*----*
9369 //
9370
9371 // first, create the new internal line
9372 new_lines[0]->set_bounding_object_indices(
9373 {middle_vertex_index<dim, spacedim>(hex->face(4)),
9374 middle_vertex_index<dim, spacedim>(hex->face(5))});
9375
9376 // again, first collect some data about the
9377 // indices of the lines, with the following
9378 // numbering:
9379
9380 // face 0: left plane
9381 // *
9382 // /|
9383 // * |
9384 // /| |
9385 // * | |
9386 // | 0 |
9387 // | | *
9388 // | |/
9389 // | *
9390 // |/
9391 // *
9392 // face 1: right plane
9393 // *
9394 // /|
9395 // * |
9396 // /| |
9397 // * | |
9398 // | 1 |
9399 // | | *
9400 // | |/
9401 // | *
9402 // |/
9403 // *
9404 // face 2: front plane
9405 // (note: x,y exchanged)
9406 // *---*---*
9407 // | | |
9408 // | 2 |
9409 // | | |
9410 // *-------*
9411 // face 3: back plane
9412 // (note: x,y exchanged)
9413 // *---*---*
9414 // | | |
9415 // | 3 |
9416 // | | |
9417 // *---*---*
9418 // face 4: bottom plane
9419 // *---*---*
9420 // / 5 /
9421 // *-6-*-7-*
9422 // / 4 /
9423 // *---*---*
9424 // face 5: top plane
9425 // *---*---*
9426 // / 9 /
9427 // *10-*-11*
9428 // / 8 /
9429 // *---*---*
9430 // middle planes
9431 // *-------* *---*---*
9432 // / / | | |
9433 // / / | 12 |
9434 // / / | | |
9435 // *-------* *---*---*
9436
9437 // set up a list of line iterators first. from
9438 // this, construct lists of line_indices and
9439 // line orientations later on
9440 const typename Triangulation<
9441 dim,
9442 spacedim>::raw_line_iterator lines[13] = {
9443 hex->face(0)->child(0)->line(
9444 (hex->face(0)->refinement_case() ==
9446 1 :
9447 3), // 0
9448 hex->face(1)->child(0)->line(
9449 (hex->face(1)->refinement_case() ==
9451 1 :
9452 3), // 1
9453 hex->face(2)->child(0)->line(
9454 (hex->face(2)->refinement_case() ==
9456 1 :
9457 3), // 2
9458 hex->face(3)->child(0)->line(
9459 (hex->face(3)->refinement_case() ==
9461 1 :
9462 3), // 3
9463
9464 hex->face(4)
9465 ->isotropic_child(
9467 0, f_or[4], f_fl[4], f_ro[4]))
9468 ->line(
9470 1, f_or[4], f_fl[4], f_ro[4])), // 4
9471 hex->face(4)
9472 ->isotropic_child(
9474 3, f_or[4], f_fl[4], f_ro[4]))
9475 ->line(
9477 0, f_or[4], f_fl[4], f_ro[4])), // 5
9478 hex->face(4)
9479 ->isotropic_child(
9481 0, f_or[4], f_fl[4], f_ro[4]))
9482 ->line(
9484 3, f_or[4], f_fl[4], f_ro[4])), // 6
9485 hex->face(4)
9486 ->isotropic_child(
9488 3, f_or[4], f_fl[4], f_ro[4]))
9489 ->line(
9491 2, f_or[4], f_fl[4], f_ro[4])), // 7
9492
9493 hex->face(5)
9494 ->isotropic_child(
9496 0, f_or[5], f_fl[5], f_ro[5]))
9497 ->line(
9499 1, f_or[5], f_fl[5], f_ro[5])), // 8
9500 hex->face(5)
9501 ->isotropic_child(
9503 3, f_or[5], f_fl[5], f_ro[5]))
9504 ->line(
9506 0, f_or[5], f_fl[5], f_ro[5])), // 9
9507 hex->face(5)
9508 ->isotropic_child(
9510 0, f_or[5], f_fl[5], f_ro[5]))
9511 ->line(
9513 3, f_or[5], f_fl[5], f_ro[5])), // 10
9514 hex->face(5)
9515 ->isotropic_child(
9517 3, f_or[5], f_fl[5], f_ro[5]))
9518 ->line(
9520 2, f_or[5], f_fl[5], f_ro[5])), // 11
9521
9522 new_lines[0] // 12
9523 };
9524
9525 unsigned int line_indices[13];
9526 for (unsigned int i = 0; i < 13; ++i)
9527 line_indices[i] = lines[i]->index();
9528
9529 // the orientation of lines for the inner quads
9530 // is quite tricky. as these lines are newly
9531 // created ones and thus have no parents, they
9532 // cannot inherit this property. set up an array
9533 // and fill it with the respective values
9534 bool line_orientation[13];
9535
9536 // the middle vertices of the lines of our
9537 // bottom face
9538 const unsigned int middle_vertices[4] = {
9539 hex->line(0)->child(0)->vertex_index(1),
9540 hex->line(1)->child(0)->vertex_index(1),
9541 hex->line(2)->child(0)->vertex_index(1),
9542 hex->line(3)->child(0)->vertex_index(1),
9543 };
9544
9545 // note: for lines 0 to 3 the orientation of the
9546 // line is 'true', if vertex 0 is on the bottom
9547 // face
9548 for (unsigned int i = 0; i < 4; ++i)
9549 if (lines[i]->vertex_index(0) == middle_vertices[i])
9550 line_orientation[i] = true;
9551 else
9552 {
9553 // it must be the other way round then
9554 Assert(lines[i]->vertex_index(1) ==
9555 middle_vertices[i],
9557 line_orientation[i] = false;
9558 }
9559
9560 // note: for lines 4 to 11 (inner lines of the
9561 // outer quads) the following holds: the second
9562 // vertex of the even lines in standard
9563 // orientation is the vertex in the middle of
9564 // the quad, whereas for odd lines the first
9565 // vertex is the same middle vertex.
9566 for (unsigned int i = 4; i < 12; ++i)
9567 if (lines[i]->vertex_index((i + 1) % 2) ==
9568 middle_vertex_index<dim, spacedim>(
9569 hex->face(3 + i / 4)))
9570 line_orientation[i] = true;
9571 else
9572 {
9573 // it must be the other way
9574 // round then
9575 Assert(lines[i]->vertex_index(i % 2) ==
9576 (middle_vertex_index<dim, spacedim>(
9577 hex->face(3 + i / 4))),
9579 line_orientation[i] = false;
9580 }
9581 // for the last line the line orientation is
9582 // always true, since it was just constructed
9583 // that way
9584 line_orientation[12] = true;
9585
9586 // set up the 4 quads, numbered as follows (left
9587 // quad numbering, right line numbering
9588 // extracted from above)
9589 //
9590 // * *
9591 // /| 9|
9592 // * | * |
9593 // y/| | 8| 3
9594 // * |1| * | |
9595 // | | |x | 12|
9596 // |0| * | | *
9597 // | |/ 2 |5
9598 // | * | *
9599 // |/ |4
9600 // * *
9601 //
9602 // x
9603 // *---*---* *10-*-11*
9604 // | | | | | |
9605 // | 2 | 3 | 0 12 1
9606 // | | | | | |
9607 // *---*---*y *-6-*-7-*
9608
9609 new_quads[0]->set_bounding_object_indices(
9610 {line_indices[2],
9611 line_indices[12],
9612 line_indices[4],
9613 line_indices[8]});
9614 new_quads[1]->set_bounding_object_indices(
9615 {line_indices[12],
9616 line_indices[3],
9617 line_indices[5],
9618 line_indices[9]});
9619 new_quads[2]->set_bounding_object_indices(
9620 {line_indices[6],
9621 line_indices[10],
9622 line_indices[0],
9623 line_indices[12]});
9624 new_quads[3]->set_bounding_object_indices(
9625 {line_indices[7],
9626 line_indices[11],
9627 line_indices[12],
9628 line_indices[1]});
9629
9630 new_quads[0]->set_line_orientation(
9631 0, line_orientation[2]);
9632 new_quads[0]->set_line_orientation(
9633 2, line_orientation[4]);
9634 new_quads[0]->set_line_orientation(
9635 3, line_orientation[8]);
9636
9637 new_quads[1]->set_line_orientation(
9638 1, line_orientation[3]);
9639 new_quads[1]->set_line_orientation(
9640 2, line_orientation[5]);
9641 new_quads[1]->set_line_orientation(
9642 3, line_orientation[9]);
9643
9644 new_quads[2]->set_line_orientation(
9645 0, line_orientation[6]);
9646 new_quads[2]->set_line_orientation(
9647 1, line_orientation[10]);
9648 new_quads[2]->set_line_orientation(
9649 2, line_orientation[0]);
9650
9651 new_quads[3]->set_line_orientation(
9652 0, line_orientation[7]);
9653 new_quads[3]->set_line_orientation(
9654 1, line_orientation[11]);
9655 new_quads[3]->set_line_orientation(
9656 3, line_orientation[1]);
9657
9658 // the quads are numbered as follows:
9659 //
9660 // planes in the interior of the old hex:
9661 //
9662 // *
9663 // /|
9664 // * | x
9665 // /| | *---*---* *---------*
9666 // * |1| | | | / /
9667 // | | | | 2 | 3 | / /
9668 // |0| * | | | / /
9669 // | |/ *---*---*y *---------*x
9670 // | *
9671 // |/
9672 // *
9673 //
9674 // children of the faces of the old hex
9675 //
9676 // *---*---* *---*---*
9677 // /| | | /18 / 19/|
9678 // * |10 | 11| /---/---* |
9679 // /| | | | /16 / 17/| |
9680 // * |5| | | *---*---* |7|
9681 // | | *---*---* | | | | *
9682 // |4|/14 / 15/ | | |6|/
9683 // | *---/---/ | 8 | 9 | *
9684 // |/12 / 13/ | | |/
9685 // *---*---* *---*---*
9686 //
9687 // note that we have to take care of the
9688 // orientation of faces.
9689 const int quad_indices[20] = {
9690 new_quads[0]->index(), // 0
9691 new_quads[1]->index(),
9692 new_quads[2]->index(),
9693 new_quads[3]->index(),
9694
9695 hex->face(0)->child_index(
9696 child_at_origin[hex->face(0)->refinement_case() -
9697 1][f_fl[0]][f_ro[0]]), // 4
9698 hex->face(0)->child_index(
9699 1 -
9700 child_at_origin[hex->face(0)->refinement_case() -
9701 1][f_fl[0]][f_ro[0]]),
9702
9703 hex->face(1)->child_index(
9704 child_at_origin[hex->face(1)->refinement_case() -
9705 1][f_fl[1]][f_ro[1]]), // 6
9706 hex->face(1)->child_index(
9707 1 -
9708 child_at_origin[hex->face(1)->refinement_case() -
9709 1][f_fl[1]][f_ro[1]]),
9710
9711 hex->face(2)->child_index(
9712 child_at_origin[hex->face(2)->refinement_case() -
9713 1][f_fl[2]][f_ro[2]]), // 8
9714 hex->face(2)->child_index(
9715 1 -
9716 child_at_origin[hex->face(2)->refinement_case() -
9717 1][f_fl[2]][f_ro[2]]),
9718
9719 hex->face(3)->child_index(
9720 child_at_origin[hex->face(3)->refinement_case() -
9721 1][f_fl[3]][f_ro[3]]), // 10
9722 hex->face(3)->child_index(
9723 1 -
9724 child_at_origin[hex->face(3)->refinement_case() -
9725 1][f_fl[3]][f_ro[3]]),
9726
9727 hex->face(4)->isotropic_child_index(
9729 0, f_or[4], f_fl[4], f_ro[4])), // 12
9730 hex->face(4)->isotropic_child_index(
9732 1, f_or[4], f_fl[4], f_ro[4])),
9733 hex->face(4)->isotropic_child_index(
9735 2, f_or[4], f_fl[4], f_ro[4])),
9736 hex->face(4)->isotropic_child_index(
9738 3, f_or[4], f_fl[4], f_ro[4])),
9739
9740 hex->face(5)->isotropic_child_index(
9742 0, f_or[5], f_fl[5], f_ro[5])), // 16
9743 hex->face(5)->isotropic_child_index(
9745 1, f_or[5], f_fl[5], f_ro[5])),
9746 hex->face(5)->isotropic_child_index(
9748 2, f_or[5], f_fl[5], f_ro[5])),
9749 hex->face(5)->isotropic_child_index(
9751 3, f_or[5], f_fl[5], f_ro[5]))};
9752
9753 new_hexes[0]->set_bounding_object_indices(
9754 {quad_indices[4],
9755 quad_indices[0],
9756 quad_indices[8],
9757 quad_indices[2],
9758 quad_indices[12],
9759 quad_indices[16]});
9760 new_hexes[1]->set_bounding_object_indices(
9761 {quad_indices[0],
9762 quad_indices[6],
9763 quad_indices[9],
9764 quad_indices[3],
9765 quad_indices[13],
9766 quad_indices[17]});
9767 new_hexes[2]->set_bounding_object_indices(
9768 {quad_indices[5],
9769 quad_indices[1],
9770 quad_indices[2],
9771 quad_indices[10],
9772 quad_indices[14],
9773 quad_indices[18]});
9774 new_hexes[3]->set_bounding_object_indices(
9775 {quad_indices[1],
9776 quad_indices[7],
9777 quad_indices[3],
9778 quad_indices[11],
9779 quad_indices[15],
9780 quad_indices[19]});
9781 break;
9782 }
9783
9785 {
9786 //----------------------------
9787 //
9788 // RefinementCase<dim>::cut_xz
9789 //
9790 // the refined cube will look like this:
9791 //
9792 // *----*----*
9793 // / / /|
9794 // / / / |
9795 // / / / *
9796 // *----*----* /|
9797 // | | | / |
9798 // | | |/ *
9799 // *----*----* /
9800 // | | | /
9801 // | | |/
9802 // *----*----*
9803 //
9804
9805 // first, create the new internal line
9806 new_lines[0]->set_bounding_object_indices(
9807 {middle_vertex_index<dim, spacedim>(hex->face(2)),
9808 middle_vertex_index<dim, spacedim>(hex->face(3))});
9809
9810 // again, first collect some data about the
9811 // indices of the lines, with the following
9812 // numbering:
9813
9814 // face 0: left plane
9815 // *
9816 // /|
9817 // / |
9818 // / *
9819 // * /|
9820 // | 0 |
9821 // |/ *
9822 // * /
9823 // | /
9824 // |/
9825 // *
9826 // face 1: right plane
9827 // *
9828 // /|
9829 // / |
9830 // / *
9831 // * /|
9832 // | 1 |
9833 // |/ *
9834 // * /
9835 // | /
9836 // |/
9837 // *
9838 // face 2: front plane
9839 // (note: x,y exchanged)
9840 // *---*---*
9841 // | 5 |
9842 // *-6-*-7-*
9843 // | 4 |
9844 // *---*---*
9845 // face 3: back plane
9846 // (note: x,y exchanged)
9847 // *---*---*
9848 // | 9 |
9849 // *10-*-11*
9850 // | 8 |
9851 // *---*---*
9852 // face 4: bottom plane
9853 // *---*---*
9854 // / / /
9855 // / 2 /
9856 // / / /
9857 // *---*---*
9858 // face 5: top plane
9859 // *---*---*
9860 // / / /
9861 // / 3 /
9862 // / / /
9863 // *---*---*
9864 // middle planes
9865 // *---*---* *-------*
9866 // / / / | |
9867 // / 12 / | |
9868 // / / / | |
9869 // *---*---* *-------*
9870
9871 // set up a list of line iterators first. from
9872 // this, construct lists of line_indices and
9873 // line orientations later on
9874 const typename Triangulation<
9875 dim,
9876 spacedim>::raw_line_iterator lines[13] = {
9877 hex->face(0)->child(0)->line(
9878 (hex->face(0)->refinement_case() ==
9880 1 :
9881 3), // 0
9882 hex->face(1)->child(0)->line(
9883 (hex->face(1)->refinement_case() ==
9885 1 :
9886 3), // 1
9887 hex->face(4)->child(0)->line(
9888 (hex->face(4)->refinement_case() ==
9890 1 :
9891 3), // 2
9892 hex->face(5)->child(0)->line(
9893 (hex->face(5)->refinement_case() ==
9895 1 :
9896 3), // 3
9897
9898 hex->face(2)
9899 ->isotropic_child(
9901 0, f_or[2], f_fl[2], f_ro[2]))
9902 ->line(
9904 3, f_or[2], f_fl[2], f_ro[2])), // 4
9905 hex->face(2)
9906 ->isotropic_child(
9908 3, f_or[2], f_fl[2], f_ro[2]))
9909 ->line(
9911 2, f_or[2], f_fl[2], f_ro[2])), // 5
9912 hex->face(2)
9913 ->isotropic_child(
9915 0, f_or[2], f_fl[2], f_ro[2]))
9916 ->line(
9918 1, f_or[2], f_fl[2], f_ro[2])), // 6
9919 hex->face(2)
9920 ->isotropic_child(
9922 3, f_or[2], f_fl[2], f_ro[2]))
9923 ->line(
9925 0, f_or[2], f_fl[2], f_ro[2])), // 7
9926
9927 hex->face(3)
9928 ->isotropic_child(
9930 0, f_or[3], f_fl[3], f_ro[3]))
9931 ->line(
9933 3, f_or[3], f_fl[3], f_ro[3])), // 8
9934 hex->face(3)
9935 ->isotropic_child(
9937 3, f_or[3], f_fl[3], f_ro[3]))
9938 ->line(
9940 2, f_or[3], f_fl[3], f_ro[3])), // 9
9941 hex->face(3)
9942 ->isotropic_child(
9944 0, f_or[3], f_fl[3], f_ro[3]))
9945 ->line(
9947 1, f_or[3], f_fl[3], f_ro[3])), // 10
9948 hex->face(3)
9949 ->isotropic_child(
9951 3, f_or[3], f_fl[3], f_ro[3]))
9952 ->line(
9954 0, f_or[3], f_fl[3], f_ro[3])), // 11
9955
9956 new_lines[0] // 12
9957 };
9958
9959 unsigned int line_indices[13];
9960 for (unsigned int i = 0; i < 13; ++i)
9961 line_indices[i] = lines[i]->index();
9962
9963 // the orientation of lines for the inner quads
9964 // is quite tricky. as these lines are newly
9965 // created ones and thus have no parents, they
9966 // cannot inherit this property. set up an array
9967 // and fill it with the respective values
9968 bool line_orientation[13];
9969
9970 // the middle vertices of the
9971 // lines of our front face
9972 const unsigned int middle_vertices[4] = {
9973 hex->line(8)->child(0)->vertex_index(1),
9974 hex->line(9)->child(0)->vertex_index(1),
9975 hex->line(2)->child(0)->vertex_index(1),
9976 hex->line(6)->child(0)->vertex_index(1),
9977 };
9978
9979 // note: for lines 0 to 3 the orientation of the
9980 // line is 'true', if vertex 0 is on the front
9981 for (unsigned int i = 0; i < 4; ++i)
9982 if (lines[i]->vertex_index(0) == middle_vertices[i])
9983 line_orientation[i] = true;
9984 else
9985 {
9986 // it must be the other way round then
9987 Assert(lines[i]->vertex_index(1) ==
9988 middle_vertices[i],
9990 line_orientation[i] = false;
9991 }
9992
9993 // note: for lines 4 to 11 (inner lines of the
9994 // outer quads) the following holds: the second
9995 // vertex of the even lines in standard
9996 // orientation is the vertex in the middle of
9997 // the quad, whereas for odd lines the first
9998 // vertex is the same middle vertex.
9999 for (unsigned int i = 4; i < 12; ++i)
10000 if (lines[i]->vertex_index((i + 1) % 2) ==
10001 middle_vertex_index<dim, spacedim>(
10002 hex->face(1 + i / 4)))
10003 line_orientation[i] = true;
10004 else
10005 {
10006 // it must be the other way
10007 // round then
10008 Assert(lines[i]->vertex_index(i % 2) ==
10009 (middle_vertex_index<dim, spacedim>(
10010 hex->face(1 + i / 4))),
10012 line_orientation[i] = false;
10013 }
10014 // for the last line the line orientation is
10015 // always true, since it was just constructed
10016 // that way
10017 line_orientation[12] = true;
10018
10019 // set up the 4 quads, numbered as follows (left
10020 // quad numbering, right line numbering
10021 // extracted from above), the drawings denote
10022 // middle planes
10023 //
10024 // * *
10025 // /| /|
10026 // / | 3 9
10027 // y/ * / *
10028 // * 3/| * /|
10029 // | / |x 5 12|8
10030 // |/ * |/ *
10031 // * 2/ * /
10032 // | / 4 2
10033 // |/ |/
10034 // * *
10035 //
10036 // y
10037 // *----*----* *-10-*-11-*
10038 // / / / / / /
10039 // / 0 / 1 / 0 12 1
10040 // / / / / / /
10041 // *----*----*x *--6-*--7-*
10042
10043 new_quads[0]->set_bounding_object_indices(
10044 {line_indices[0],
10045 line_indices[12],
10046 line_indices[6],
10047 line_indices[10]});
10048 new_quads[1]->set_bounding_object_indices(
10049 {line_indices[12],
10050 line_indices[1],
10051 line_indices[7],
10052 line_indices[11]});
10053 new_quads[2]->set_bounding_object_indices(
10054 {line_indices[4],
10055 line_indices[8],
10056 line_indices[2],
10057 line_indices[12]});
10058 new_quads[3]->set_bounding_object_indices(
10059 {line_indices[5],
10060 line_indices[9],
10061 line_indices[12],
10062 line_indices[3]});
10063
10064 new_quads[0]->set_line_orientation(
10065 0, line_orientation[0]);
10066 new_quads[0]->set_line_orientation(
10067 2, line_orientation[6]);
10068 new_quads[0]->set_line_orientation(
10069 3, line_orientation[10]);
10070
10071 new_quads[1]->set_line_orientation(
10072 1, line_orientation[1]);
10073 new_quads[1]->set_line_orientation(
10074 2, line_orientation[7]);
10075 new_quads[1]->set_line_orientation(
10076 3, line_orientation[11]);
10077
10078 new_quads[2]->set_line_orientation(
10079 0, line_orientation[4]);
10080 new_quads[2]->set_line_orientation(
10081 1, line_orientation[8]);
10082 new_quads[2]->set_line_orientation(
10083 2, line_orientation[2]);
10084
10085 new_quads[3]->set_line_orientation(
10086 0, line_orientation[5]);
10087 new_quads[3]->set_line_orientation(
10088 1, line_orientation[9]);
10089 new_quads[3]->set_line_orientation(
10090 3, line_orientation[3]);
10091
10092 // the quads are numbered as follows:
10093 //
10094 // planes in the interior of the old hex:
10095 //
10096 // *
10097 // /|
10098 // / | x
10099 // /3 * *-------* *----*----*
10100 // * /| | | / / /
10101 // | / | | | / 0 / 1 /
10102 // |/ * | | / / /
10103 // * 2/ *-------*y *----*----*x
10104 // | /
10105 // |/
10106 // *
10107 //
10108 // children of the faces
10109 // of the old hex
10110 // *---*---* *---*---*
10111 // /|13 | 15| / / /|
10112 // / | | | /18 / 19/ |
10113 // / *---*---* / / / *
10114 // * 5/| | | *---*---* 7/|
10115 // | / |12 | 14| | 9 | 11| / |
10116 // |/4 *---*---* | | |/6 *
10117 // * / / / *---*---* /
10118 // | /16 / 17/ | | | /
10119 // |/ / / | 8 | 10|/
10120 // *---*---* *---*---*
10121 //
10122 // note that we have to take care of the
10123 // orientation of faces.
10124 const int quad_indices[20] = {
10125 new_quads[0]->index(), // 0
10126 new_quads[1]->index(),
10127 new_quads[2]->index(),
10128 new_quads[3]->index(),
10129
10130 hex->face(0)->child_index(
10131 child_at_origin[hex->face(0)->refinement_case() -
10132 1][f_fl[0]][f_ro[0]]), // 4
10133 hex->face(0)->child_index(
10134 1 -
10135 child_at_origin[hex->face(0)->refinement_case() -
10136 1][f_fl[0]][f_ro[0]]),
10137
10138 hex->face(1)->child_index(
10139 child_at_origin[hex->face(1)->refinement_case() -
10140 1][f_fl[1]][f_ro[1]]), // 6
10141 hex->face(1)->child_index(
10142 1 -
10143 child_at_origin[hex->face(1)->refinement_case() -
10144 1][f_fl[1]][f_ro[1]]),
10145
10146 hex->face(2)->isotropic_child_index(
10148 0, f_or[2], f_fl[2], f_ro[2])), // 8
10149 hex->face(2)->isotropic_child_index(
10151 1, f_or[2], f_fl[2], f_ro[2])),
10152 hex->face(2)->isotropic_child_index(
10154 2, f_or[2], f_fl[2], f_ro[2])),
10155 hex->face(2)->isotropic_child_index(
10157 3, f_or[2], f_fl[2], f_ro[2])),
10158
10159 hex->face(3)->isotropic_child_index(
10161 0, f_or[3], f_fl[3], f_ro[3])), // 12
10162 hex->face(3)->isotropic_child_index(
10164 1, f_or[3], f_fl[3], f_ro[3])),
10165 hex->face(3)->isotropic_child_index(
10167 2, f_or[3], f_fl[3], f_ro[3])),
10168 hex->face(3)->isotropic_child_index(
10170 3, f_or[3], f_fl[3], f_ro[3])),
10171
10172 hex->face(4)->child_index(
10173 child_at_origin[hex->face(4)->refinement_case() -
10174 1][f_fl[4]][f_ro[4]]), // 16
10175 hex->face(4)->child_index(
10176 1 -
10177 child_at_origin[hex->face(4)->refinement_case() -
10178 1][f_fl[4]][f_ro[4]]),
10179
10180 hex->face(5)->child_index(
10181 child_at_origin[hex->face(5)->refinement_case() -
10182 1][f_fl[5]][f_ro[5]]), // 18
10183 hex->face(5)->child_index(
10184 1 -
10185 child_at_origin[hex->face(5)->refinement_case() -
10186 1][f_fl[5]][f_ro[5]])};
10187
10188 // due to the exchange of x and y for the front
10189 // and back face, we order the children
10190 // according to
10191 //
10192 // *---*---*
10193 // | 1 | 3 |
10194 // *---*---*
10195 // | 0 | 2 |
10196 // *---*---*
10197 new_hexes[0]->set_bounding_object_indices(
10198 {quad_indices[4],
10199 quad_indices[2],
10200 quad_indices[8],
10201 quad_indices[12],
10202 quad_indices[16],
10203 quad_indices[0]});
10204 new_hexes[1]->set_bounding_object_indices(
10205 {quad_indices[5],
10206 quad_indices[3],
10207 quad_indices[9],
10208 quad_indices[13],
10209 quad_indices[0],
10210 quad_indices[18]});
10211 new_hexes[2]->set_bounding_object_indices(
10212 {quad_indices[2],
10213 quad_indices[6],
10214 quad_indices[10],
10215 quad_indices[14],
10216 quad_indices[17],
10217 quad_indices[1]});
10218 new_hexes[3]->set_bounding_object_indices(
10219 {quad_indices[3],
10220 quad_indices[7],
10221 quad_indices[11],
10222 quad_indices[15],
10223 quad_indices[1],
10224 quad_indices[19]});
10225 break;
10226 }
10227
10229 {
10230 //----------------------------
10231 //
10232 // RefinementCase<dim>::cut_yz
10233 //
10234 // the refined cube will look like this:
10235 //
10236 // *---------*
10237 // / /|
10238 // *---------* |
10239 // / /| |
10240 // *---------* |/|
10241 // | | * |
10242 // | |/| *
10243 // *---------* |/
10244 // | | *
10245 // | |/
10246 // *---------*
10247 //
10248
10249 // first, create the new
10250 // internal line
10251 new_lines[0]->set_bounding_object_indices(
10252
10253 {middle_vertex_index<dim, spacedim>(hex->face(0)),
10254 middle_vertex_index<dim, spacedim>(hex->face(1))});
10255
10256 // again, first collect some data about the
10257 // indices of the lines, with the following
10258 // numbering: (note that face 0 and 1 each are
10259 // shown twice for better readability)
10260
10261 // face 0: left plane
10262 // * *
10263 // /| /|
10264 // * | * |
10265 // /| * /| *
10266 // * 5/| * |7|
10267 // | * | | * |
10268 // |/| * |6| *
10269 // * 4/ * |/
10270 // | * | *
10271 // |/ |/
10272 // * *
10273 // face 1: right plane
10274 // * *
10275 // /| /|
10276 // * | * |
10277 // /| * /| *
10278 // * 9/| * |11
10279 // | * | | * |
10280 // |/| * |10 *
10281 // * 8/ * |/
10282 // | * | *
10283 // |/ |/
10284 // * *
10285 // face 2: front plane
10286 // (note: x,y exchanged)
10287 // *-------*
10288 // | |
10289 // *---0---*
10290 // | |
10291 // *-------*
10292 // face 3: back plane
10293 // (note: x,y exchanged)
10294 // *-------*
10295 // | |
10296 // *---1---*
10297 // | |
10298 // *-------*
10299 // face 4: bottom plane
10300 // *-------*
10301 // / /
10302 // *---2---*
10303 // / /
10304 // *-------*
10305 // face 5: top plane
10306 // *-------*
10307 // / /
10308 // *---3---*
10309 // / /
10310 // *-------*
10311 // middle planes
10312 // *-------* *-------*
10313 // / / | |
10314 // *---12--* | |
10315 // / / | |
10316 // *-------* *-------*
10317
10318 // set up a list of line iterators first. from
10319 // this, construct lists of line_indices and
10320 // line orientations later on
10321 const typename Triangulation<
10322 dim,
10323 spacedim>::raw_line_iterator lines[13] = {
10324 hex->face(2)->child(0)->line(
10325 (hex->face(2)->refinement_case() ==
10327 1 :
10328 3), // 0
10329 hex->face(3)->child(0)->line(
10330 (hex->face(3)->refinement_case() ==
10332 1 :
10333 3), // 1
10334 hex->face(4)->child(0)->line(
10335 (hex->face(4)->refinement_case() ==
10337 1 :
10338 3), // 2
10339 hex->face(5)->child(0)->line(
10340 (hex->face(5)->refinement_case() ==
10342 1 :
10343 3), // 3
10344
10345 hex->face(0)
10346 ->isotropic_child(
10348 0, f_or[0], f_fl[0], f_ro[0]))
10349 ->line(
10351 1, f_or[0], f_fl[0], f_ro[0])), // 4
10352 hex->face(0)
10353 ->isotropic_child(
10355 3, f_or[0], f_fl[0], f_ro[0]))
10356 ->line(
10358 0, f_or[0], f_fl[0], f_ro[0])), // 5
10359 hex->face(0)
10360 ->isotropic_child(
10362 0, f_or[0], f_fl[0], f_ro[0]))
10363 ->line(
10365 3, f_or[0], f_fl[0], f_ro[0])), // 6
10366 hex->face(0)
10367 ->isotropic_child(
10369 3, f_or[0], f_fl[0], f_ro[0]))
10370 ->line(
10372 2, f_or[0], f_fl[0], f_ro[0])), // 7
10373
10374 hex->face(1)
10375 ->isotropic_child(
10377 0, f_or[1], f_fl[1], f_ro[1]))
10378 ->line(
10380 1, f_or[1], f_fl[1], f_ro[1])), // 8
10381 hex->face(1)
10382 ->isotropic_child(
10384 3, f_or[1], f_fl[1], f_ro[1]))
10385 ->line(
10387 0, f_or[1], f_fl[1], f_ro[1])), // 9
10388 hex->face(1)
10389 ->isotropic_child(
10391 0, f_or[1], f_fl[1], f_ro[1]))
10392 ->line(
10394 3, f_or[1], f_fl[1], f_ro[1])), // 10
10395 hex->face(1)
10396 ->isotropic_child(
10398 3, f_or[1], f_fl[1], f_ro[1]))
10399 ->line(
10401 2, f_or[1], f_fl[1], f_ro[1])), // 11
10402
10403 new_lines[0] // 12
10404 };
10405
10406 unsigned int line_indices[13];
10407
10408 for (unsigned int i = 0; i < 13; ++i)
10409 line_indices[i] = lines[i]->index();
10410
10411 // the orientation of lines for the inner quads
10412 // is quite tricky. as these lines are newly
10413 // created ones and thus have no parents, they
10414 // cannot inherit this property. set up an array
10415 // and fill it with the respective values
10416 bool line_orientation[13];
10417
10418 // the middle vertices of the lines of our front
10419 // face
10420 const unsigned int middle_vertices[4] = {
10421 hex->line(8)->child(0)->vertex_index(1),
10422 hex->line(10)->child(0)->vertex_index(1),
10423 hex->line(0)->child(0)->vertex_index(1),
10424 hex->line(4)->child(0)->vertex_index(1),
10425 };
10426
10427 // note: for lines 0 to 3 the orientation of the
10428 // line is 'true', if vertex 0 is on the front
10429 for (unsigned int i = 0; i < 4; ++i)
10430 if (lines[i]->vertex_index(0) == middle_vertices[i])
10431 line_orientation[i] = true;
10432 else
10433 {
10434 // it must be the other way round then
10435 Assert(lines[i]->vertex_index(1) ==
10436 middle_vertices[i],
10438 line_orientation[i] = false;
10439 }
10440
10441 // note: for lines 4 to 11 (inner lines of the
10442 // outer quads) the following holds: the second
10443 // vertex of the even lines in standard
10444 // orientation is the vertex in the middle of
10445 // the quad, whereas for odd lines the first
10446 // vertex is the same middle vertex.
10447 for (unsigned int i = 4; i < 12; ++i)
10448 if (lines[i]->vertex_index((i + 1) % 2) ==
10449 middle_vertex_index<dim, spacedim>(
10450 hex->face(i / 4 - 1)))
10451 line_orientation[i] = true;
10452 else
10453 {
10454 // it must be the other way
10455 // round then
10456 Assert(lines[i]->vertex_index(i % 2) ==
10457 (middle_vertex_index<dim, spacedim>(
10458 hex->face(i / 4 - 1))),
10460 line_orientation[i] = false;
10461 }
10462 // for the last line the line orientation is
10463 // always true, since it was just constructed
10464 // that way
10465 line_orientation[12] = true;
10466
10467 // set up the 4 quads, numbered as follows (left
10468 // quad numbering, right line numbering
10469 // extracted from above)
10470 //
10471 // x
10472 // *-------* *---3---*
10473 // | 3 | 5 9
10474 // *-------* *---12--*
10475 // | 2 | 4 8
10476 // *-------*y *---2---*
10477 //
10478 // y
10479 // *---------* *----1----*
10480 // / 1 / 7 11
10481 // *---------* *----12---*
10482 // / 0 / 6 10
10483 // *---------*x *----0----*
10484
10485 new_quads[0]->set_bounding_object_indices(
10486 {line_indices[6],
10487 line_indices[10],
10488 line_indices[0],
10489 line_indices[12]});
10490 new_quads[1]->set_bounding_object_indices(
10491 {line_indices[7],
10492 line_indices[11],
10493 line_indices[12],
10494 line_indices[1]});
10495 new_quads[2]->set_bounding_object_indices(
10496 {line_indices[2],
10497 line_indices[12],
10498 line_indices[4],
10499 line_indices[8]});
10500 new_quads[3]->set_bounding_object_indices(
10501 {line_indices[12],
10502 line_indices[3],
10503 line_indices[5],
10504 line_indices[9]});
10505
10506 new_quads[0]->set_line_orientation(
10507 0, line_orientation[6]);
10508 new_quads[0]->set_line_orientation(
10509 1, line_orientation[10]);
10510 new_quads[0]->set_line_orientation(
10511 2, line_orientation[0]);
10512
10513 new_quads[1]->set_line_orientation(
10514 0, line_orientation[7]);
10515 new_quads[1]->set_line_orientation(
10516 1, line_orientation[11]);
10517 new_quads[1]->set_line_orientation(
10518 3, line_orientation[1]);
10519
10520 new_quads[2]->set_line_orientation(
10521 0, line_orientation[2]);
10522 new_quads[2]->set_line_orientation(
10523 2, line_orientation[4]);
10524 new_quads[2]->set_line_orientation(
10525 3, line_orientation[8]);
10526
10527 new_quads[3]->set_line_orientation(
10528 1, line_orientation[3]);
10529 new_quads[3]->set_line_orientation(
10530 2, line_orientation[5]);
10531 new_quads[3]->set_line_orientation(
10532 3, line_orientation[9]);
10533
10534 // the quads are numbered as follows:
10535 //
10536 // planes in the interior of the old hex:
10537 //
10538 // *
10539 // /|
10540 // / | x
10541 // / | *-------* *---------*
10542 // * | | 3 | / 1 /
10543 // | | *-------* *---------*
10544 // | * | 2 | / 0 /
10545 // | / *-------*y *---------*x
10546 // | /
10547 // |/
10548 // *
10549 //
10550 // children of the faces
10551 // of the old hex
10552 // *-------* *-------*
10553 // /| | / 19 /|
10554 // * | 15 | *-------* |
10555 // /|7*-------* / 18 /|11
10556 // * |/| | *-------* |/|
10557 // |6* | 14 | | 10* |
10558 // |/|5*-------* | 13 |/|9*
10559 // * |/ 17 / *-------* |/
10560 // |4*-------* | |8*
10561 // |/ 16 / | 12 |/
10562 // *-------* *-------*
10563 //
10564 // note that we have to take care of the
10565 // orientation of faces.
10566 const int quad_indices[20] = {
10567 new_quads[0]->index(), // 0
10568 new_quads[1]->index(),
10569 new_quads[2]->index(),
10570 new_quads[3]->index(),
10571
10572 hex->face(0)->isotropic_child_index(
10574 0, f_or[0], f_fl[0], f_ro[0])), // 4
10575 hex->face(0)->isotropic_child_index(
10577 1, f_or[0], f_fl[0], f_ro[0])),
10578 hex->face(0)->isotropic_child_index(
10580 2, f_or[0], f_fl[0], f_ro[0])),
10581 hex->face(0)->isotropic_child_index(
10583 3, f_or[0], f_fl[0], f_ro[0])),
10584
10585 hex->face(1)->isotropic_child_index(
10587 0, f_or[1], f_fl[1], f_ro[1])), // 8
10588 hex->face(1)->isotropic_child_index(
10590 1, f_or[1], f_fl[1], f_ro[1])),
10591 hex->face(1)->isotropic_child_index(
10593 2, f_or[1], f_fl[1], f_ro[1])),
10594 hex->face(1)->isotropic_child_index(
10596 3, f_or[1], f_fl[1], f_ro[1])),
10597
10598 hex->face(2)->child_index(
10599 child_at_origin[hex->face(2)->refinement_case() -
10600 1][f_fl[2]][f_ro[2]]), // 12
10601 hex->face(2)->child_index(
10602 1 -
10603 child_at_origin[hex->face(2)->refinement_case() -
10604 1][f_fl[2]][f_ro[2]]),
10605
10606 hex->face(3)->child_index(
10607 child_at_origin[hex->face(3)->refinement_case() -
10608 1][f_fl[3]][f_ro[3]]), // 14
10609 hex->face(3)->child_index(
10610 1 -
10611 child_at_origin[hex->face(3)->refinement_case() -
10612 1][f_fl[3]][f_ro[3]]),
10613
10614 hex->face(4)->child_index(
10615 child_at_origin[hex->face(4)->refinement_case() -
10616 1][f_fl[4]][f_ro[4]]), // 16
10617 hex->face(4)->child_index(
10618 1 -
10619 child_at_origin[hex->face(4)->refinement_case() -
10620 1][f_fl[4]][f_ro[4]]),
10621
10622 hex->face(5)->child_index(
10623 child_at_origin[hex->face(5)->refinement_case() -
10624 1][f_fl[5]][f_ro[5]]), // 18
10625 hex->face(5)->child_index(
10626 1 -
10627 child_at_origin[hex->face(5)->refinement_case() -
10628 1][f_fl[5]][f_ro[5]])};
10629
10630 new_hexes[0]->set_bounding_object_indices(
10631 {quad_indices[4],
10632 quad_indices[8],
10633 quad_indices[12],
10634 quad_indices[2],
10635 quad_indices[16],
10636 quad_indices[0]});
10637 new_hexes[1]->set_bounding_object_indices(
10638 {quad_indices[5],
10639 quad_indices[9],
10640 quad_indices[2],
10641 quad_indices[14],
10642 quad_indices[17],
10643 quad_indices[1]});
10644 new_hexes[2]->set_bounding_object_indices(
10645 {quad_indices[6],
10646 quad_indices[10],
10647 quad_indices[13],
10648 quad_indices[3],
10649 quad_indices[0],
10650 quad_indices[18]});
10651 new_hexes[3]->set_bounding_object_indices(
10652 {quad_indices[7],
10653 quad_indices[11],
10654 quad_indices[3],
10655 quad_indices[15],
10656 quad_indices[1],
10657 quad_indices[19]});
10658 break;
10659 }
10660
10662 {
10663 //----------------------------
10664 //
10665 // RefinementCase<dim>::cut_xyz
10666 // isotropic refinement
10667 //
10668 // the refined cube will look
10669 // like this:
10670 //
10671 // *----*----*
10672 // / / /|
10673 // *----*----* |
10674 // / / /| *
10675 // *----*----* |/|
10676 // | | | * |
10677 // | | |/| *
10678 // *----*----* |/
10679 // | | | *
10680 // | | |/
10681 // *----*----*
10682 //
10683
10684 // find the next unused vertex and set it
10685 // appropriately
10686 while (
10687 triangulation.vertices_used[next_unused_vertex] ==
10688 true)
10689 ++next_unused_vertex;
10690 Assert(
10691 next_unused_vertex < triangulation.vertices.size(),
10692 ExcMessage(
10693 "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."));
10694 triangulation.vertices_used[next_unused_vertex] =
10695 true;
10696
10697 // the new vertex is definitely in the interior,
10698 // so we need not worry about the
10699 // boundary. However we need to worry about
10700 // Manifolds. Let the cell compute its own
10701 // center, by querying the underlying manifold
10702 // object.
10703 triangulation.vertices[next_unused_vertex] =
10704 hex->center(true, true);
10705
10706 // set the data of the six lines. first collect
10707 // the indices of the seven vertices (consider
10708 // the two planes to be crossed to form the
10709 // planes cutting the hex in two vertically and
10710 // horizontally)
10711 //
10712 // *--3--* *--5--*
10713 // / / / | | |
10714 // 0--6--1 0--6--1
10715 // / / / | | |
10716 // *--2--* *--4--*
10717 // the lines are numbered
10718 // as follows:
10719 // *--*--* *--*--*
10720 // / 1 / | 5 |
10721 // *2-*-3* *2-*-3*
10722 // / 0 / | 4 |
10723 // *--*--* *--*--*
10724 //
10725 const unsigned int vertex_indices[7] = {
10726 middle_vertex_index<dim, spacedim>(hex->face(0)),
10727 middle_vertex_index<dim, spacedim>(hex->face(1)),
10728 middle_vertex_index<dim, spacedim>(hex->face(2)),
10729 middle_vertex_index<dim, spacedim>(hex->face(3)),
10730 middle_vertex_index<dim, spacedim>(hex->face(4)),
10731 middle_vertex_index<dim, spacedim>(hex->face(5)),
10732 next_unused_vertex};
10733
10734 new_lines[0]->set_bounding_object_indices(
10736 new_lines[1]->set_bounding_object_indices(
10738 new_lines[2]->set_bounding_object_indices(
10740 new_lines[3]->set_bounding_object_indices(
10742 new_lines[4]->set_bounding_object_indices(
10744 new_lines[5]->set_bounding_object_indices(
10746
10747 // again, first collect some data about the
10748 // indices of the lines, with the following
10749 // numbering: (note that face 0 and 1 each are
10750 // shown twice for better readability)
10751
10752 // face 0: left plane
10753 // * *
10754 // /| /|
10755 // * | * |
10756 // /| * /| *
10757 // * 1/| * |3|
10758 // | * | | * |
10759 // |/| * |2| *
10760 // * 0/ * |/
10761 // | * | *
10762 // |/ |/
10763 // * *
10764 // face 1: right plane
10765 // * *
10766 // /| /|
10767 // * | * |
10768 // /| * /| *
10769 // * 5/| * |7|
10770 // | * | | * |
10771 // |/| * |6| *
10772 // * 4/ * |/
10773 // | * | *
10774 // |/ |/
10775 // * *
10776 // face 2: front plane
10777 // (note: x,y exchanged)
10778 // *---*---*
10779 // | 11 |
10780 // *-8-*-9-*
10781 // | 10 |
10782 // *---*---*
10783 // face 3: back plane
10784 // (note: x,y exchanged)
10785 // *---*---*
10786 // | 15 |
10787 // *12-*-13*
10788 // | 14 |
10789 // *---*---*
10790 // face 4: bottom plane
10791 // *---*---*
10792 // / 17 /
10793 // *18-*-19*
10794 // / 16 /
10795 // *---*---*
10796 // face 5: top plane
10797 // *---*---*
10798 // / 21 /
10799 // *22-*-23*
10800 // / 20 /
10801 // *---*---*
10802 // middle planes
10803 // *---*---* *---*---*
10804 // / 25 / | 29 |
10805 // *26-*-27* *26-*-27*
10806 // / 24 / | 28 |
10807 // *---*---* *---*---*
10808
10809 // set up a list of line iterators first. from
10810 // this, construct lists of line_indices and
10811 // line orientations later on
10812 const typename Triangulation<
10813 dim,
10814 spacedim>::raw_line_iterator lines[30] = {
10815 hex->face(0)
10816 ->isotropic_child(
10818 0, f_or[0], f_fl[0], f_ro[0]))
10819 ->line(
10821 1, f_or[0], f_fl[0], f_ro[0])), // 0
10822 hex->face(0)
10823 ->isotropic_child(
10825 3, f_or[0], f_fl[0], f_ro[0]))
10826 ->line(
10828 0, f_or[0], f_fl[0], f_ro[0])), // 1
10829 hex->face(0)
10830 ->isotropic_child(
10832 0, f_or[0], f_fl[0], f_ro[0]))
10833 ->line(
10835 3, f_or[0], f_fl[0], f_ro[0])), // 2
10836 hex->face(0)
10837 ->isotropic_child(
10839 3, f_or[0], f_fl[0], f_ro[0]))
10840 ->line(
10842 2, f_or[0], f_fl[0], f_ro[0])), // 3
10843
10844 hex->face(1)
10845 ->isotropic_child(
10847 0, f_or[1], f_fl[1], f_ro[1]))
10848 ->line(
10850 1, f_or[1], f_fl[1], f_ro[1])), // 4
10851 hex->face(1)
10852 ->isotropic_child(
10854 3, f_or[1], f_fl[1], f_ro[1]))
10855 ->line(
10857 0, f_or[1], f_fl[1], f_ro[1])), // 5
10858 hex->face(1)
10859 ->isotropic_child(
10861 0, f_or[1], f_fl[1], f_ro[1]))
10862 ->line(
10864 3, f_or[1], f_fl[1], f_ro[1])), // 6
10865 hex->face(1)
10866 ->isotropic_child(
10868 3, f_or[1], f_fl[1], f_ro[1]))
10869 ->line(
10871 2, f_or[1], f_fl[1], f_ro[1])), // 7
10872
10873 hex->face(2)
10874 ->isotropic_child(
10876 0, f_or[2], f_fl[2], f_ro[2]))
10877 ->line(
10879 1, f_or[2], f_fl[2], f_ro[2])), // 8
10880 hex->face(2)
10881 ->isotropic_child(
10883 3, f_or[2], f_fl[2], f_ro[2]))
10884 ->line(
10886 0, f_or[2], f_fl[2], f_ro[2])), // 9
10887 hex->face(2)
10888 ->isotropic_child(
10890 0, f_or[2], f_fl[2], f_ro[2]))
10891 ->line(
10893 3, f_or[2], f_fl[2], f_ro[2])), // 10
10894 hex->face(2)
10895 ->isotropic_child(
10897 3, f_or[2], f_fl[2], f_ro[2]))
10898 ->line(
10900 2, f_or[2], f_fl[2], f_ro[2])), // 11
10901
10902 hex->face(3)
10903 ->isotropic_child(
10905 0, f_or[3], f_fl[3], f_ro[3]))
10906 ->line(
10908 1, f_or[3], f_fl[3], f_ro[3])), // 12
10909 hex->face(3)
10910 ->isotropic_child(
10912 3, f_or[3], f_fl[3], f_ro[3]))
10913 ->line(
10915 0, f_or[3], f_fl[3], f_ro[3])), // 13
10916 hex->face(3)
10917 ->isotropic_child(
10919 0, f_or[3], f_fl[3], f_ro[3]))
10920 ->line(
10922 3, f_or[3], f_fl[3], f_ro[3])), // 14
10923 hex->face(3)
10924 ->isotropic_child(
10926 3, f_or[3], f_fl[3], f_ro[3]))
10927 ->line(
10929 2, f_or[3], f_fl[3], f_ro[3])), // 15
10930
10931 hex->face(4)
10932 ->isotropic_child(
10934 0, f_or[4], f_fl[4], f_ro[4]))
10935 ->line(
10937 1, f_or[4], f_fl[4], f_ro[4])), // 16
10938 hex->face(4)
10939 ->isotropic_child(
10941 3, f_or[4], f_fl[4], f_ro[4]))
10942 ->line(
10944 0, f_or[4], f_fl[4], f_ro[4])), // 17
10945 hex->face(4)
10946 ->isotropic_child(
10948 0, f_or[4], f_fl[4], f_ro[4]))
10949 ->line(
10951 3, f_or[4], f_fl[4], f_ro[4])), // 18
10952 hex->face(4)
10953 ->isotropic_child(
10955 3, f_or[4], f_fl[4], f_ro[4]))
10956 ->line(
10958 2, f_or[4], f_fl[4], f_ro[4])), // 19
10959
10960 hex->face(5)
10961 ->isotropic_child(
10963 0, f_or[5], f_fl[5], f_ro[5]))
10964 ->line(
10966 1, f_or[5], f_fl[5], f_ro[5])), // 20
10967 hex->face(5)
10968 ->isotropic_child(
10970 3, f_or[5], f_fl[5], f_ro[5]))
10971 ->line(
10973 0, f_or[5], f_fl[5], f_ro[5])), // 21
10974 hex->face(5)
10975 ->isotropic_child(
10977 0, f_or[5], f_fl[5], f_ro[5]))
10978 ->line(
10980 3, f_or[5], f_fl[5], f_ro[5])), // 22
10981 hex->face(5)
10982 ->isotropic_child(
10984 3, f_or[5], f_fl[5], f_ro[5]))
10985 ->line(
10987 2, f_or[5], f_fl[5], f_ro[5])), // 23
10988
10989 new_lines[0], // 24
10990 new_lines[1], // 25
10991 new_lines[2], // 26
10992 new_lines[3], // 27
10993 new_lines[4], // 28
10994 new_lines[5] // 29
10995 };
10996
10997 unsigned int line_indices[30];
10998 for (unsigned int i = 0; i < 30; ++i)
10999 line_indices[i] = lines[i]->index();
11000
11001 // the orientation of lines for the inner quads
11002 // is quite tricky. as these lines are newly
11003 // created ones and thus have no parents, they
11004 // cannot inherit this property. set up an array
11005 // and fill it with the respective values
11006 bool line_orientation[30];
11007
11008 // note: for the first 24 lines (inner lines of
11009 // the outer quads) the following holds: the
11010 // second vertex of the even lines in standard
11011 // orientation is the vertex in the middle of
11012 // the quad, whereas for odd lines the first
11013 // vertex is the same middle vertex.
11014 for (unsigned int i = 0; i < 24; ++i)
11015 if (lines[i]->vertex_index((i + 1) % 2) ==
11016 vertex_indices[i / 4])
11017 line_orientation[i] = true;
11018 else
11019 {
11020 // it must be the other way
11021 // round then
11022 Assert(lines[i]->vertex_index(i % 2) ==
11023 vertex_indices[i / 4],
11025 line_orientation[i] = false;
11026 }
11027 // for the last 6 lines the line orientation is
11028 // always true, since they were just constructed
11029 // that way
11030 for (unsigned int i = 24; i < 30; ++i)
11031 line_orientation[i] = true;
11032
11033 // set up the 12 quads, numbered as follows
11034 // (left quad numbering, right line numbering
11035 // extracted from above)
11036 //
11037 // * *
11038 // /| 21|
11039 // * | * 15
11040 // y/|3* 20| *
11041 // * |/| * |/|
11042 // |2* |x 11 * 14
11043 // |/|1* |/| *
11044 // * |/ * |17
11045 // |0* 10 *
11046 // |/ |16
11047 // * *
11048 //
11049 // x
11050 // *---*---* *22-*-23*
11051 // | 5 | 7 | 1 29 5
11052 // *---*---* *26-*-27*
11053 // | 4 | 6 | 0 28 4
11054 // *---*---*y *18-*-19*
11055 //
11056 // y
11057 // *----*----* *-12-*-13-*
11058 // / 10 / 11 / 3 25 7
11059 // *----*----* *-26-*-27-*
11060 // / 8 / 9 / 2 24 6
11061 // *----*----*x *--8-*--9-*
11062
11063 new_quads[0]->set_bounding_object_indices(
11064 {line_indices[10],
11065 line_indices[28],
11066 line_indices[16],
11067 line_indices[24]});
11068 new_quads[1]->set_bounding_object_indices(
11069 {line_indices[28],
11070 line_indices[14],
11071 line_indices[17],
11072 line_indices[25]});
11073 new_quads[2]->set_bounding_object_indices(
11074 {line_indices[11],
11075 line_indices[29],
11076 line_indices[24],
11077 line_indices[20]});
11078 new_quads[3]->set_bounding_object_indices(
11079 {line_indices[29],
11080 line_indices[15],
11081 line_indices[25],
11082 line_indices[21]});
11083 new_quads[4]->set_bounding_object_indices(
11084 {line_indices[18],
11085 line_indices[26],
11086 line_indices[0],
11087 line_indices[28]});
11088 new_quads[5]->set_bounding_object_indices(
11089 {line_indices[26],
11090 line_indices[22],
11091 line_indices[1],
11092 line_indices[29]});
11093 new_quads[6]->set_bounding_object_indices(
11094 {line_indices[19],
11095 line_indices[27],
11096 line_indices[28],
11097 line_indices[4]});
11098 new_quads[7]->set_bounding_object_indices(
11099 {line_indices[27],
11100 line_indices[23],
11101 line_indices[29],
11102 line_indices[5]});
11103 new_quads[8]->set_bounding_object_indices(
11104 {line_indices[2],
11105 line_indices[24],
11106 line_indices[8],
11107 line_indices[26]});
11108 new_quads[9]->set_bounding_object_indices(
11109 {line_indices[24],
11110 line_indices[6],
11111 line_indices[9],
11112 line_indices[27]});
11113 new_quads[10]->set_bounding_object_indices(
11114 {line_indices[3],
11115 line_indices[25],
11116 line_indices[26],
11117 line_indices[12]});
11118 new_quads[11]->set_bounding_object_indices(
11119 {line_indices[25],
11120 line_indices[7],
11121 line_indices[27],
11122 line_indices[13]});
11123
11124 // now reset the line_orientation flags of outer
11125 // lines as they cannot be set in a loop (at
11126 // least not easily)
11127 new_quads[0]->set_line_orientation(
11128 0, line_orientation[10]);
11129 new_quads[0]->set_line_orientation(
11130 2, line_orientation[16]);
11131
11132 new_quads[1]->set_line_orientation(
11133 1, line_orientation[14]);
11134 new_quads[1]->set_line_orientation(
11135 2, line_orientation[17]);
11136
11137 new_quads[2]->set_line_orientation(
11138 0, line_orientation[11]);
11139 new_quads[2]->set_line_orientation(
11140 3, line_orientation[20]);
11141
11142 new_quads[3]->set_line_orientation(
11143 1, line_orientation[15]);
11144 new_quads[3]->set_line_orientation(
11145 3, line_orientation[21]);
11146
11147 new_quads[4]->set_line_orientation(
11148 0, line_orientation[18]);
11149 new_quads[4]->set_line_orientation(
11150 2, line_orientation[0]);
11151
11152 new_quads[5]->set_line_orientation(
11153 1, line_orientation[22]);
11154 new_quads[5]->set_line_orientation(
11155 2, line_orientation[1]);
11156
11157 new_quads[6]->set_line_orientation(
11158 0, line_orientation[19]);
11159 new_quads[6]->set_line_orientation(
11160 3, line_orientation[4]);
11161
11162 new_quads[7]->set_line_orientation(
11163 1, line_orientation[23]);
11164 new_quads[7]->set_line_orientation(
11165 3, line_orientation[5]);
11166
11167 new_quads[8]->set_line_orientation(
11168 0, line_orientation[2]);
11169 new_quads[8]->set_line_orientation(
11170 2, line_orientation[8]);
11171
11172 new_quads[9]->set_line_orientation(
11173 1, line_orientation[6]);
11174 new_quads[9]->set_line_orientation(
11175 2, line_orientation[9]);
11176
11177 new_quads[10]->set_line_orientation(
11178 0, line_orientation[3]);
11179 new_quads[10]->set_line_orientation(
11180 3, line_orientation[12]);
11181
11182 new_quads[11]->set_line_orientation(
11183 1, line_orientation[7]);
11184 new_quads[11]->set_line_orientation(
11185 3, line_orientation[13]);
11186
11187 //-------------------------------
11188 // create the eight new hexes
11189 //
11190 // again first collect some data. here, we need
11191 // the indices of a whole lotta quads.
11192
11193 // the quads are numbered as follows:
11194 //
11195 // planes in the interior of the old hex:
11196 //
11197 // *
11198 // /|
11199 // * |
11200 // /|3* *---*---* *----*----*
11201 // * |/| | 5 | 7 | / 10 / 11 /
11202 // |2* | *---*---* *----*----*
11203 // |/|1* | 4 | 6 | / 8 / 9 /
11204 // * |/ *---*---*y *----*----*x
11205 // |0*
11206 // |/
11207 // *
11208 //
11209 // children of the faces
11210 // of the old hex
11211 // *-------* *-------*
11212 // /|25 27| /34 35/|
11213 // 15| | / /19
11214 // / | | /32 33/ |
11215 // * |24 26| *-------*18 |
11216 // 1413*-------* |21 23| 17*
11217 // | /30 31/ | | /
11218 // 12/ / | |16
11219 // |/28 29/ |20 22|/
11220 // *-------* *-------*
11221 //
11222 // note that we have to
11223 // take care of the
11224 // orientation of
11225 // faces.
11226 const int quad_indices[36] = {
11227 new_quads[0]->index(), // 0
11228 new_quads[1]->index(),
11229 new_quads[2]->index(),
11230 new_quads[3]->index(),
11231 new_quads[4]->index(),
11232 new_quads[5]->index(),
11233 new_quads[6]->index(),
11234 new_quads[7]->index(),
11235 new_quads[8]->index(),
11236 new_quads[9]->index(),
11237 new_quads[10]->index(),
11238 new_quads[11]->index(), // 11
11239
11240 hex->face(0)->isotropic_child_index(
11242 0, f_or[0], f_fl[0], f_ro[0])), // 12
11243 hex->face(0)->isotropic_child_index(
11245 1, f_or[0], f_fl[0], f_ro[0])),
11246 hex->face(0)->isotropic_child_index(
11248 2, f_or[0], f_fl[0], f_ro[0])),
11249 hex->face(0)->isotropic_child_index(
11251 3, f_or[0], f_fl[0], f_ro[0])),
11252
11253 hex->face(1)->isotropic_child_index(
11255 0, f_or[1], f_fl[1], f_ro[1])), // 16
11256 hex->face(1)->isotropic_child_index(
11258 1, f_or[1], f_fl[1], f_ro[1])),
11259 hex->face(1)->isotropic_child_index(
11261 2, f_or[1], f_fl[1], f_ro[1])),
11262 hex->face(1)->isotropic_child_index(
11264 3, f_or[1], f_fl[1], f_ro[1])),
11265
11266 hex->face(2)->isotropic_child_index(
11268 0, f_or[2], f_fl[2], f_ro[2])), // 20
11269 hex->face(2)->isotropic_child_index(
11271 1, f_or[2], f_fl[2], f_ro[2])),
11272 hex->face(2)->isotropic_child_index(
11274 2, f_or[2], f_fl[2], f_ro[2])),
11275 hex->face(2)->isotropic_child_index(
11277 3, f_or[2], f_fl[2], f_ro[2])),
11278
11279 hex->face(3)->isotropic_child_index(
11281 0, f_or[3], f_fl[3], f_ro[3])), // 24
11282 hex->face(3)->isotropic_child_index(
11284 1, f_or[3], f_fl[3], f_ro[3])),
11285 hex->face(3)->isotropic_child_index(
11287 2, f_or[3], f_fl[3], f_ro[3])),
11288 hex->face(3)->isotropic_child_index(
11290 3, f_or[3], f_fl[3], f_ro[3])),
11291
11292 hex->face(4)->isotropic_child_index(
11294 0, f_or[4], f_fl[4], f_ro[4])), // 28
11295 hex->face(4)->isotropic_child_index(
11297 1, f_or[4], f_fl[4], f_ro[4])),
11298 hex->face(4)->isotropic_child_index(
11300 2, f_or[4], f_fl[4], f_ro[4])),
11301 hex->face(4)->isotropic_child_index(
11303 3, f_or[4], f_fl[4], f_ro[4])),
11304
11305 hex->face(5)->isotropic_child_index(
11307 0, f_or[5], f_fl[5], f_ro[5])), // 32
11308 hex->face(5)->isotropic_child_index(
11310 1, f_or[5], f_fl[5], f_ro[5])),
11311 hex->face(5)->isotropic_child_index(
11313 2, f_or[5], f_fl[5], f_ro[5])),
11314 hex->face(5)->isotropic_child_index(
11316 3, f_or[5], f_fl[5], f_ro[5]))};
11317
11318 // bottom children
11319 new_hexes[0]->set_bounding_object_indices(
11320 {quad_indices[12],
11321 quad_indices[0],
11322 quad_indices[20],
11323 quad_indices[4],
11324 quad_indices[28],
11325 quad_indices[8]});
11326 new_hexes[1]->set_bounding_object_indices(
11327 {quad_indices[0],
11328 quad_indices[16],
11329 quad_indices[22],
11330 quad_indices[6],
11331 quad_indices[29],
11332 quad_indices[9]});
11333 new_hexes[2]->set_bounding_object_indices(
11334 {quad_indices[13],
11335 quad_indices[1],
11336 quad_indices[4],
11337 quad_indices[24],
11338 quad_indices[30],
11339 quad_indices[10]});
11340 new_hexes[3]->set_bounding_object_indices(
11341 {quad_indices[1],
11342 quad_indices[17],
11343 quad_indices[6],
11344 quad_indices[26],
11345 quad_indices[31],
11346 quad_indices[11]});
11347
11348 // top children
11349 new_hexes[4]->set_bounding_object_indices(
11350 {quad_indices[14],
11351 quad_indices[2],
11352 quad_indices[21],
11353 quad_indices[5],
11354 quad_indices[8],
11355 quad_indices[32]});
11356 new_hexes[5]->set_bounding_object_indices(
11357 {quad_indices[2],
11358 quad_indices[18],
11359 quad_indices[23],
11360 quad_indices[7],
11361 quad_indices[9],
11362 quad_indices[33]});
11363 new_hexes[6]->set_bounding_object_indices(
11364 {quad_indices[15],
11365 quad_indices[3],
11366 quad_indices[5],
11367 quad_indices[25],
11368 quad_indices[10],
11369 quad_indices[34]});
11370 new_hexes[7]->set_bounding_object_indices(
11371 {quad_indices[3],
11372 quad_indices[19],
11373 quad_indices[7],
11374 quad_indices[27],
11375 quad_indices[11],
11376 quad_indices[35]});
11377 break;
11378 }
11379 default:
11380 // all refinement cases have been treated, there
11381 // only remains
11382 // RefinementCase<dim>::no_refinement as
11383 // untreated enumeration value. However, in that
11384 // case we should have aborted much
11385 // earlier. thus we should never get here
11387 break;
11388 } // switch (ref_case)
11389
11390 // and set face orientation flags. note that new
11391 // faces in the interior of the mother cell always
11392 // have a correctly oriented face, but the ones on
11393 // the outer faces will inherit this flag
11394 //
11395 // the flag have been set to true for all faces
11396 // initially, now go the other way round and reset
11397 // faces that are at the boundary of the mother cube
11398 //
11399 // the same is true for the face_flip and
11400 // face_rotation flags. however, the latter two are
11401 // set to false by default as this is the standard
11402 // value
11403
11404 // loop over all faces and all (relevant) subfaces
11405 // of that in order to set the correct values for
11406 // face_orientation, face_flip and face_rotation,
11407 // which are inherited from the corresponding face
11408 // of the mother cube
11409 for (const unsigned int f : GeometryInfo<dim>::face_indices())
11410 for (unsigned int s = 0;
11413 ref_case, f)),
11414 1U);
11415 ++s)
11416 {
11417 const unsigned int current_child =
11419 ref_case,
11420 f,
11421 s,
11422 f_or[f],
11423 f_fl[f],
11424 f_ro[f],
11426 ref_case, f, f_or[f], f_fl[f], f_ro[f]));
11427 new_hexes[current_child]->set_combined_face_orientation(
11428 f, f_co[f]);
11429 }
11430
11431 // now see if we have created cells that are
11432 // distorted and if so add them to our list
11433 if (check_for_distorted_cells &&
11434 has_distorted_children<dim, spacedim>(hex))
11435 cells_with_distorted_children.distorted_cells.push_back(
11436 hex);
11437
11438 // note that the refinement flag was already cleared
11439 // at the beginning of this loop
11440
11441 // inform all listeners that cell refinement is done
11442 triangulation.signals.post_refinement_on_cell(hex);
11443 }
11444 }
11445
11446 // clear user data on quads. we used some of this data to
11447 // indicate anisotropic refinemnt cases on faces. all data
11448 // should be cleared by now, but the information whether we
11449 // used indices or pointers is still present. reset it now to
11450 // enable the user to use whichever they like later on.
11451 triangulation.faces->quads.clear_user_data();
11452
11453 // return the list with distorted children
11454 return cells_with_distorted_children;
11455 }
11456
11457
11470 template <int spacedim>
11471 static void
11474
11475
11476
11477 template <int dim, int spacedim>
11478 static void
11481 {
11482 // If the codimension is one, we cannot perform this check
11483 // yet.
11484 if (spacedim > dim)
11485 return;
11486
11487 for (const auto &cell : triangulation.cell_iterators())
11488 if (cell->at_boundary() && cell->refine_flag_set() &&
11489 cell->refine_flag_set() !=
11491 {
11492 // The cell is at the boundary and it is flagged for
11493 // anisotropic refinement. Therefore, we have a closer
11494 // look
11495 const RefinementCase<dim> ref_case = cell->refine_flag_set();
11496 for (const unsigned int face_no :
11498 if (cell->face(face_no)->at_boundary())
11499 {
11500 // this is the critical face at the boundary.
11502 face_no) !=
11504 {
11505 // up to now, we do not want to refine this
11506 // cell along the face under consideration
11507 // here.
11508 const typename Triangulation<dim,
11509 spacedim>::face_iterator
11510 face = cell->face(face_no);
11511 // the new point on the boundary would be this
11512 // one.
11513 const Point<spacedim> new_bound = face->center(true);
11514 // to check it, transform to the unit cell
11515 // with a linear mapping
11516 const Point<dim> new_unit =
11517 cell->reference_cell()
11518 .template get_default_linear_mapping<dim,
11519 spacedim>()
11520 .transform_real_to_unit_cell(cell, new_bound);
11521
11522 // Now, we have to calculate the distance from
11523 // the face in the unit cell.
11524
11525 // take the correct coordinate direction (0
11526 // for faces 0 and 1, 1 for faces 2 and 3, 2
11527 // for faces 4 and 5) and subtract the correct
11528 // boundary value of the face (0 for faces 0,
11529 // 2, and 4; 1 for faces 1, 3 and 5)
11530 const double dist =
11531 std::fabs(new_unit[face_no / 2] - face_no % 2);
11532
11533 // compare this with the empirical value
11534 // allowed. if it is too big, flag the face
11535 // for isotropic refinement
11536 const double allowed = 0.25;
11537
11538 if (dist > allowed)
11539 cell->flag_for_face_refinement(face_no);
11540 } // if flagged for anistropic refinement
11541 } // if (cell->face(face)->at_boundary())
11542 } // for all cells
11543 }
11544
11545
11558 template <int dim, int spacedim>
11559 static void
11561 {
11562 Assert(dim < 3,
11563 ExcMessage("Wrong function called -- there should "
11564 "be a specialization."));
11565 }
11566
11567
11568 template <int spacedim>
11569 static void
11572 {
11573 const unsigned int dim = 3;
11574 using raw_line_iterator =
11576
11577 // variable to store whether the mesh was changed in the
11578 // present loop and in the whole process
11579 bool mesh_changed = false;
11580
11581 do
11582 {
11583 mesh_changed = false;
11584
11585 // for this following, we need to know which cells are
11586 // going to be coarsened, if we had to make a
11587 // decision. the following function sets these flags:
11588 triangulation.fix_coarsen_flags();
11589
11590 // first clear flags on lines, since we need them to determine
11591 // which lines will be refined
11592 triangulation.clear_user_flags_line();
11593
11594 // flag those lines that are refined and will not be
11595 // coarsened and those that will be refined
11596 for (const auto &cell : triangulation.cell_iterators())
11597 if (cell->refine_flag_set())
11598 {
11599 const std::array<unsigned int, 12> line_indices =
11600 TriaAccessorImplementation::Implementation::
11601 get_line_indices_of_cell(*cell);
11602 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11604 cell->refine_flag_set(), l) ==
11606 {
11607 raw_line_iterator line(&triangulation,
11608 0,
11609 line_indices[l]);
11610 // flag a line, that will be refined
11611 line->set_user_flag();
11612 }
11613 }
11614 else if (cell->has_children() &&
11615 !cell->child(0)->coarsen_flag_set())
11616 {
11617 const std::array<unsigned int, 12> line_indices =
11618 TriaAccessorImplementation::Implementation::
11619 get_line_indices_of_cell(*cell);
11620 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11622 cell->refinement_case(), l) ==
11624 {
11625 raw_line_iterator line(&triangulation,
11626 0,
11627 line_indices[l]);
11628 // flag a line, that is refined and will stay so
11629 line->set_user_flag();
11630 }
11631 }
11632 else if (cell->has_children() &&
11633 cell->child(0)->coarsen_flag_set())
11634 cell->set_user_flag();
11635
11636
11637 // now check whether there are cells with lines that are
11638 // more than once refined or that will be more than once
11639 // refined. The first thing should never be the case, in
11640 // the second case we flag the cell for refinement
11642 cell = triangulation.last_active();
11643 cell != triangulation.end();
11644 --cell)
11645 {
11646 const std::array<unsigned int, 12> line_indices =
11647 TriaAccessorImplementation::Implementation::
11648 get_line_indices_of_cell(*cell);
11649 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11650 {
11651 raw_line_iterator line(&triangulation, 0, line_indices[l]);
11652 if (line->has_children())
11653 {
11654 // if this line is refined, its children should
11655 // not have further children
11656 //
11657 // however, if any of the children is flagged
11658 // for further refinement, we need to refine
11659 // this cell also (at least, if the cell is not
11660 // already flagged)
11661 bool offending_line_found = false;
11662
11663 for (unsigned int c = 0; c < 2; ++c)
11664 {
11665 Assert(line->child(c)->has_children() == false,
11667
11668 if (line->child(c)->user_flag_set() &&
11670 cell->refine_flag_set(), l) ==
11672 {
11673 // tag this cell for refinement
11674 cell->clear_coarsen_flag();
11675 // if anisotropic coarsening is allowed:
11676 // extend the refine_flag in the needed
11677 // direction, else set refine_flag
11678 // (isotropic)
11679 if (triangulation.smooth_grid &
11681 allow_anisotropic_smoothing)
11682 cell->flag_for_line_refinement(l);
11683 else
11684 cell->set_refine_flag();
11685
11686 for (unsigned int k = 0; k < cell->n_lines();
11687 ++k)
11689 cell->refine_flag_set(), l) ==
11691 // flag a line, that will be refined
11692 raw_line_iterator(&triangulation,
11693 0,
11694 line_indices[k])
11695 ->set_user_flag();
11696
11697 // note that we have changed the grid
11698 offending_line_found = true;
11699
11700 // it may save us several loop
11701 // iterations if we flag all lines of
11702 // this cell now (and not at the outset
11703 // of the next iteration) for refinement
11704 for (unsigned int k = 0; k < cell->n_lines();
11705 ++k)
11706 {
11707 const auto line =
11708 raw_line_iterator(&triangulation,
11709 0,
11710 line_indices[k]);
11711 if (!line->has_children() &&
11713 line_refinement_case(
11714 cell->refine_flag_set(), k) !=
11716 line->set_user_flag();
11717 }
11718
11719 break;
11720 }
11721 }
11722
11723 if (offending_line_found)
11724 {
11725 mesh_changed = true;
11726 break;
11727 }
11728 }
11729 }
11730 }
11731
11732
11733 // there is another thing here: if any of the lines will
11734 // be refined, then we may not coarsen the present cell
11735 // similarly, if any of the lines *is* already refined, we
11736 // may not coarsen the current cell. however, there's a
11737 // catch: if the line is refined, but the cell behind it
11738 // is going to be coarsened, then the situation
11739 // changes. if we forget this second condition, the
11740 // refine_and_coarsen_3d test will start to fail. note
11741 // that to know which cells are going to be coarsened, the
11742 // call for fix_coarsen_flags above is necessary
11744 triangulation.last();
11745 cell != triangulation.end();
11746 --cell)
11747 if (cell->user_flag_set())
11748 {
11749 const std::array<unsigned int, 12> line_indices =
11750 TriaAccessorImplementation::Implementation::
11751 get_line_indices_of_cell(*cell);
11752 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11753 {
11754 raw_line_iterator line(&triangulation,
11755 0,
11756 line_indices[l]);
11757 if (line->has_children() &&
11758 (line->child(0)->user_flag_set() ||
11759 line->child(1)->user_flag_set()))
11760 {
11761 for (unsigned int c = 0; c < cell->n_children(); ++c)
11762 cell->child(c)->clear_coarsen_flag();
11763 cell->clear_user_flag();
11764 for (unsigned int k = 0; k < cell->n_lines(); ++k)
11766 cell->refinement_case(), k) ==
11768 // flag a line, that is refined and will
11769 // stay so
11770 raw_line_iterator(&triangulation,
11771 0,
11772 line_indices[k])
11773 ->set_user_flag();
11774 mesh_changed = true;
11775 break;
11776 }
11777 }
11778 }
11779 }
11780 while (mesh_changed == true);
11781 }
11782
11783
11784
11791 template <int dim, int spacedim>
11792 static bool
11795 {
11796 // in 1d, coarsening is always allowed since we don't enforce
11797 // the 2:1 constraint there
11798 if (dim == 1)
11799 return true;
11800
11801 const RefinementCase<dim> ref_case = cell->refinement_case();
11802 for (const unsigned int n : GeometryInfo<dim>::face_indices())
11803 {
11804 // if the cell is not refined along that face, coarsening
11805 // will not change anything, so do nothing. the same
11806 // applies, if the face is at the boundary
11807 const RefinementCase<dim - 1> face_ref_case =
11808 GeometryInfo<dim>::face_refinement_case(cell->refinement_case(),
11809 n);
11810
11811 const unsigned int n_subfaces =
11812 GeometryInfo<dim - 1>::n_children(face_ref_case);
11813
11814 if (n_subfaces == 0 || cell->at_boundary(n))
11815 continue;
11816 for (unsigned int c = 0; c < n_subfaces; ++c)
11817 {
11819 child = cell->child(
11821
11823 child_neighbor = child->neighbor(n);
11824 if (!child->neighbor_is_coarser(n))
11825 {
11826 // in 2d, if the child's neighbor is coarser, then it has
11827 // no children. however, in 3d it might be
11828 // otherwise. consider for example, that our face might be
11829 // refined with cut_x, but the neighbor is refined with
11830 // cut_xy at that face. then the neighbor pointers of the
11831 // children of our cell will point to the common neighbor
11832 // cell, not to its children. what we really want to know
11833 // in the following is, whether the neighbor cell is
11834 // refined twice with reference to our cell. that only
11835 // has to be asked, if the child's neighbor is not a
11836 // coarser one. we check whether some of the children on
11837 // the neighbor are not flagged for coarsening, in that
11838 // case we may not coarsen. it is enough to check the
11839 // first child because we have already fixed the coarsen
11840 // flags on finer levels
11841 if (child_neighbor->has_children() &&
11842 !(child_neighbor->child(0)->is_active() &&
11843 child_neighbor->child(0)->coarsen_flag_set()))
11844 return false;
11845
11846 // the same applies, if the neighbors children are not
11847 // refined but will be after refinement
11848 if (child_neighbor->refine_flag_set())
11849 return false;
11850 }
11851 }
11852 }
11853 return true;
11854 }
11855 };
11856
11857
11862 {
11863 template <int spacedim>
11864 static void
11867
11868 template <int dim, int spacedim>
11870 {
11871 std::vector<std::pair<unsigned int, unsigned int>> adjacent_cells(
11872 2 * triangulation.n_raw_faces(),
11873 {numbers::invalid_unsigned_int, numbers::invalid_unsigned_int});
11874
11875 const auto set_entry = [&](const auto &face_index, const auto &cell) {
11876 const std::pair<unsigned int, unsigned int> cell_pair = {
11877 cell->level(), cell->index()};
11878 unsigned int index;
11879
11880 if (adjacent_cells[2 * face_index].first ==
11882 adjacent_cells[2 * face_index].second ==
11884 {
11885 index = 2 * face_index + 0;
11886 }
11887 else
11888 {
11889 Assert(((adjacent_cells[2 * face_index + 1].first ==
11891 (adjacent_cells[2 * face_index + 1].second ==
11894 index = 2 * face_index + 1;
11895 }
11896
11897 adjacent_cells[index] = cell_pair;
11898 };
11899
11900 const auto get_entry =
11901 [&](const auto &face_index,
11902 const auto &cell) -> TriaIterator<CellAccessor<dim, spacedim>> {
11903 auto test = adjacent_cells[2 * face_index];
11904
11905 if (test == std::pair<unsigned int, unsigned int>(cell->level(),
11906 cell->index()))
11907 test = adjacent_cells[2 * face_index + 1];
11908
11909 if ((test.first != numbers::invalid_unsigned_int) &&
11910 (test.second != numbers::invalid_unsigned_int))
11912 test.first,
11913 test.second);
11914 else
11916 };
11917
11918 for (const auto &cell : triangulation.cell_iterators())
11919 for (const auto &face : cell->face_iterators())
11920 {
11921 set_entry(face->index(), cell);
11922
11923 if (cell->is_active() && face->has_children())
11924 for (unsigned int c = 0; c < face->n_children(); ++c)
11925 set_entry(face->child(c)->index(), cell);
11926 }
11927
11928 for (const auto &cell : triangulation.cell_iterators())
11929 for (auto f : cell->face_indices())
11930 cell->set_neighbor(f, get_entry(cell->face(f)->index(), cell));
11931 }
11932
11933 template <int dim, int spacedim>
11934 static void
11936 Triangulation<dim, spacedim> & /*triangulation*/,
11938 std::vector<unsigned int> & /*line_cell_count*/,
11939 std::vector<unsigned int> & /*quad_cell_count*/)
11940 {
11942 }
11943
11944 template <int dim, int spacedim>
11947 const bool check_for_distorted_cells)
11948 {
11949 return Implementation::execute_refinement_isotropic(
11950 triangulation, check_for_distorted_cells);
11951 }
11952
11953 template <int dim, int spacedim>
11954 static void
11956 Triangulation<dim, spacedim> & /*triangulation*/)
11957 {
11958 // nothing to do since anisotropy is not supported
11959 }
11960
11961 template <int dim, int spacedim>
11962 static void
11965 {
11966 Implementation::prepare_refinement_dim_dependent(triangulation);
11967 }
11968
11969 template <int dim, int spacedim>
11970 static bool
11973 {
11975
11976 return false;
11977 }
11978 };
11979
11980
11981 template <int dim, int spacedim>
11984 {
11985 static const FlatManifold<dim, spacedim> flat_manifold;
11986 return flat_manifold;
11987 }
11988 } // namespace TriangulationImplementation
11989} // namespace internal
11990
11991#ifndef DOXYGEN
11992
11993template <int dim, int spacedim>
11996
11997
11998
11999template <int dim, int spacedim>
12002 const MeshSmoothing smooth_grid,
12003 const bool check_for_distorted_cells)
12004 : cell_attached_data({0, 0, {}, {}})
12005 , smooth_grid(smooth_grid)
12006 , anisotropic_refinement(false)
12007 , check_for_distorted_cells(check_for_distorted_cells)
12008{
12009 if (dim == 1)
12010 {
12011 vertex_to_boundary_id_map_1d =
12012 std::make_unique<std::map<unsigned int, types::boundary_id>>();
12013 vertex_to_manifold_id_map_1d =
12014 std::make_unique<std::map<unsigned int, types::manifold_id>>();
12015 }
12016
12017 // connect the any_change signal to the other top level signals
12018 signals.create.connect(signals.any_change);
12019 signals.post_refinement.connect(signals.any_change);
12020 signals.clear.connect(signals.any_change);
12021 signals.mesh_movement.connect(signals.any_change);
12022}
12023
12024
12025
12026template <int dim, int spacedim>
12029 Triangulation<dim, spacedim> &&tria) noexcept
12030 : EnableObserverPointer(std::move(tria))
12031 , smooth_grid(tria.smooth_grid)
12032 , reference_cells(std::move(tria.reference_cells))
12033 , periodic_face_pairs_level_0(std::move(tria.periodic_face_pairs_level_0))
12034 , periodic_face_map(std::move(tria.periodic_face_map))
12035 , levels(std::move(tria.levels))
12036 , faces(std::move(tria.faces))
12037 , vertices(std::move(tria.vertices))
12038 , vertices_used(std::move(tria.vertices_used))
12039 , manifolds(std::move(tria.manifolds))
12040 , anisotropic_refinement(tria.anisotropic_refinement)
12041 , check_for_distorted_cells(tria.check_for_distorted_cells)
12042 , number_cache(std::move(tria.number_cache))
12043 , vertex_to_boundary_id_map_1d(std::move(tria.vertex_to_boundary_id_map_1d))
12044 , vertex_to_manifold_id_map_1d(std::move(tria.vertex_to_manifold_id_map_1d))
12045{
12047
12048 if (tria.policy)
12049 this->policy = tria.policy->clone();
12050}
12051
12052
12053template <int dim, int spacedim>
12056 Triangulation<dim, spacedim> &&tria) noexcept
12057{
12058 EnableObserverPointer::operator=(std::move(tria));
12059
12060 smooth_grid = tria.smooth_grid;
12061 reference_cells = std::move(tria.reference_cells);
12062 periodic_face_pairs_level_0 = std::move(tria.periodic_face_pairs_level_0);
12063 periodic_face_map = std::move(tria.periodic_face_map);
12064 levels = std::move(tria.levels);
12065 faces = std::move(tria.faces);
12066 vertices = std::move(tria.vertices);
12067 vertices_used = std::move(tria.vertices_used);
12068 manifolds = std::move(tria.manifolds);
12069 anisotropic_refinement = tria.anisotropic_refinement;
12070 number_cache = tria.number_cache;
12071 vertex_to_boundary_id_map_1d = std::move(tria.vertex_to_boundary_id_map_1d);
12072 vertex_to_manifold_id_map_1d = std::move(tria.vertex_to_manifold_id_map_1d);
12073
12075
12076 if (tria.policy)
12077 this->policy = tria.policy->clone();
12078
12079 return *this;
12080}
12081
12082
12083
12084template <int dim, int spacedim>
12087{
12088 // notify listeners that the triangulation is going down...
12089 try
12090 {
12091 signals.clear();
12092 }
12093 catch (...)
12094 {}
12095
12096 levels.clear();
12097
12098 // the vertex_to_boundary_id_map_1d field should be unused except in
12099 // 1d. double check this here, as destruction is a good place to
12100 // ensure that what we've done over the course of the lifetime of
12101 // this object makes sense
12102 AssertNothrow((dim == 1) || (vertex_to_boundary_id_map_1d == nullptr),
12104
12105 // the vertex_to_manifold_id_map_1d field should be also unused
12106 // except in 1d. check this as well
12107 AssertNothrow((dim == 1) || (vertex_to_manifold_id_map_1d == nullptr),
12109}
12110
12111
12112
12113template <int dim, int spacedim>
12116{
12117 // notify listeners that the triangulation is going down...
12118 signals.clear();
12119
12120 // ...and then actually clear all content of it
12121 clear_despite_subscriptions();
12122 periodic_face_pairs_level_0.clear();
12123 periodic_face_map.clear();
12124 reference_cells.clear();
12125
12126 cell_attached_data = {0, 0, {}, {}};
12127 data_serializer.clear();
12128}
12129
12130template <int dim, int spacedim>
12133{
12134 return MPI_COMM_SELF;
12135}
12136
12137
12138
12139template <int dim, int spacedim>
12142{
12143 return get_mpi_communicator();
12144}
12145
12146
12147
12148template <int dim, int spacedim>
12150std::weak_ptr<const Utilities::MPI::Partitioner> Triangulation<dim, spacedim>::
12152{
12153 return number_cache.active_cell_index_partitioner;
12154}
12155
12156
12157
12158template <int dim, int spacedim>
12160std::weak_ptr<const Utilities::MPI::Partitioner> Triangulation<dim, spacedim>::
12161 global_level_cell_index_partitioner(const unsigned int level) const
12162{
12163 AssertIndexRange(level, this->n_levels());
12164
12165 return number_cache.level_cell_index_partitioners[level];
12166}
12167
12168
12169
12170template <int dim, int spacedim>
12173 const MeshSmoothing mesh_smoothing)
12174{
12175 smooth_grid = mesh_smoothing;
12176}
12177
12178
12179
12180template <int dim, int spacedim>
12184{
12185 return smooth_grid;
12186}
12187
12188
12189
12190template <int dim, int spacedim>
12193 const types::manifold_id m_number,
12194 const Manifold<dim, spacedim> &manifold_object)
12195{
12197
12198 manifolds[m_number] = manifold_object.clone();
12199}
12200
12201
12202
12203template <int dim, int spacedim>
12206 const types::manifold_id m_number)
12207{
12209
12210 // delete the entry located at number.
12211 manifolds[m_number] =
12213 spacedim>()
12214 .clone();
12215}
12216
12217
12218template <int dim, int spacedim>
12221{
12222 for (auto &m : manifolds)
12223 m.second = internal::TriangulationImplementation::
12224 get_default_flat_manifold<dim, spacedim>()
12225 .clone();
12226}
12227
12228
12229template <int dim, int spacedim>
12232 const types::manifold_id m_number)
12233{
12234 Assert(
12235 n_cells() > 0,
12236 ExcMessage(
12237 "Error: set_all_manifold_ids() can not be called on an empty Triangulation."));
12238
12239 for (const auto &cell : this->active_cell_iterators())
12240 cell->set_all_manifold_ids(m_number);
12241}
12242
12243
12244template <int dim, int spacedim>
12247 const types::manifold_id m_number)
12248{
12249 Assert(
12250 n_cells() > 0,
12251 ExcMessage(
12252 "Error: set_all_manifold_ids_on_boundary() can not be called on an empty Triangulation."));
12253
12254 for (const auto &cell : this->active_cell_iterators())
12255 for (auto f : GeometryInfo<dim>::face_indices())
12256 if (cell->face(f)->at_boundary())
12257 cell->face(f)->set_all_manifold_ids(m_number);
12258}
12259
12260
12261template <int dim, int spacedim>
12264 const types::boundary_id b_id,
12265 const types::manifold_id m_number)
12266{
12267 Assert(
12268 n_cells() > 0,
12269 ExcMessage(
12270 "Error: set_all_manifold_ids_on_boundary() can not be called on an empty Triangulation."));
12271
12272 [[maybe_unused]] bool boundary_found = false;
12273
12274 for (const auto &cell : this->active_cell_iterators())
12275 {
12276 // loop on faces
12277 for (auto f : GeometryInfo<dim>::face_indices())
12278 if (cell->face(f)->at_boundary() &&
12279 cell->face(f)->boundary_id() == b_id)
12280 {
12281 boundary_found = true;
12282 cell->face(f)->set_manifold_id(m_number);
12283 }
12284
12285 // loop on edges if dim >= 3
12286 if (dim >= 3)
12287 for (unsigned int e = 0; e < GeometryInfo<dim>::lines_per_cell; ++e)
12288 if (cell->line(e)->at_boundary() &&
12289 cell->line(e)->boundary_id() == b_id)
12290 {
12291 boundary_found = true;
12292 cell->line(e)->set_manifold_id(m_number);
12293 }
12294 }
12295
12296 Assert(boundary_found, ExcBoundaryIdNotFound(b_id));
12297}
12298
12299
12300
12301template <int dim, int spacedim>
12304 const types::manifold_id m_number) const
12305{
12306 // check if flat manifold has been queried
12307 if (m_number == numbers::flat_manifold_id)
12308 return internal::TriangulationImplementation::
12309 get_default_flat_manifold<dim, spacedim>();
12310
12311 // look, if there is a manifold stored at
12312 // manifold_id number.
12313 const auto it = manifolds.find(m_number);
12314
12315 if (it != manifolds.end())
12316 {
12317 // if we have found an entry, return it
12318 return *(it->second);
12319 }
12320
12321 Assert(
12322 false,
12323 ExcMessage(
12324 "No manifold of the manifold id " + std::to_string(m_number) +
12325 " has been attached to the triangulation. "
12326 "Please attach the right manifold with Triangulation::set_manifold()."));
12327
12328 return internal::TriangulationImplementation::
12329 get_default_flat_manifold<dim, spacedim>(); // never reached
12330}
12331
12332
12333
12334template <int dim, int spacedim>
12336std::vector<types::boundary_id> Triangulation<dim, spacedim>::get_boundary_ids()
12337 const
12338{
12339 std::set<types::boundary_id> boundary_ids;
12340 for (const auto &cell : active_cell_iterators())
12341 if (cell->is_locally_owned())
12342 for (const auto &face : cell->face_indices())
12343 if (cell->at_boundary(face))
12344 boundary_ids.insert(cell->face(face)->boundary_id());
12345
12346 return {boundary_ids.begin(), boundary_ids.end()};
12347}
12348
12349
12350
12351template <int dim, int spacedim>
12353std::vector<types::manifold_id> Triangulation<dim, spacedim>::get_manifold_ids()
12354 const
12355{
12356 std::set<types::manifold_id> m_ids;
12357 for (const auto &cell : active_cell_iterators())
12358 if (cell->is_locally_owned())
12359 {
12360 m_ids.insert(cell->manifold_id());
12361 for (const auto &face : cell->face_iterators())
12362 m_ids.insert(face->manifold_id());
12363 if (dim == 3)
12364 {
12365 const auto line_indices = internal::TriaAccessorImplementation::
12366 Implementation::get_line_indices_of_cell(*cell);
12367 for (unsigned int l = 0; l < cell->n_lines(); ++l)
12368 {
12369 raw_line_iterator line(this, 0, line_indices[l]);
12370 m_ids.insert(line->manifold_id());
12371 }
12372 }
12373 }
12374 return {m_ids.begin(), m_ids.end()};
12375}
12376
12377#endif
12378/*-----------------------------------------------------------------*/
12379
12380#ifndef DOXYGEN
12381
12382template <int dim, int spacedim>
12385 const Triangulation<dim, spacedim> &other_tria)
12386{
12387 Assert((vertices.empty()) && (levels.empty()) && (faces == nullptr),
12388 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
12389 Assert((other_tria.levels.size() != 0) && (other_tria.vertices.size() != 0) &&
12390 (dim == 1 || other_tria.faces != nullptr),
12391 ExcMessage(
12392 "When calling Triangulation::copy_triangulation(), "
12393 "the target triangulation must be empty but the source "
12394 "triangulation (the argument to this function) must contain "
12395 "something. Here, it seems like the source does not "
12396 "contain anything at all."));
12397
12398
12399 // copy normal elements
12400 vertices = other_tria.vertices;
12401 vertices_used = other_tria.vertices_used;
12402 anisotropic_refinement = other_tria.anisotropic_refinement;
12403 smooth_grid = other_tria.smooth_grid;
12404 reference_cells = other_tria.reference_cells;
12405
12406 if (dim > 1)
12407 faces = std::make_unique<internal::TriangulationImplementation::TriaFaces>(
12408 *other_tria.faces);
12409
12410 for (const auto &p : other_tria.manifolds)
12411 set_manifold(p.first, *p.second);
12412
12413
12414 levels.reserve(other_tria.levels.size());
12415 for (unsigned int level = 0; level < other_tria.levels.size(); ++level)
12416 levels.push_back(
12417 std::make_unique<internal::TriangulationImplementation::TriaLevel>(
12418 *other_tria.levels[level]));
12419
12420 number_cache = other_tria.number_cache;
12421
12422 if (dim == 1)
12423 {
12424 vertex_to_boundary_id_map_1d =
12425 std::make_unique<std::map<unsigned int, types::boundary_id>>(
12426 *other_tria.vertex_to_boundary_id_map_1d);
12427
12428 vertex_to_manifold_id_map_1d =
12429 std::make_unique<std::map<unsigned int, types::manifold_id>>(
12430 *other_tria.vertex_to_manifold_id_map_1d);
12431 }
12432
12433 if (other_tria.policy)
12434 this->policy = other_tria.policy->clone();
12435
12436 // periodic faces
12437 this->periodic_face_pairs_level_0.reserve(
12438 other_tria.periodic_face_pairs_level_0.size());
12439
12440 for (const auto &other_entry : other_tria.periodic_face_pairs_level_0)
12441 {
12442 auto entry = other_entry;
12443 entry.cell[0] =
12444 cell_iterator(this, entry.cell[0]->level(), entry.cell[0]->index());
12445 entry.cell[1] =
12446 cell_iterator(this, entry.cell[1]->level(), entry.cell[1]->index());
12447 periodic_face_pairs_level_0.emplace_back(entry);
12448 }
12449
12450 for (auto [first_cell_, second_cell_and_orientation] :
12451 other_tria.periodic_face_map)
12452 {
12453 auto first_cell = first_cell_; // make copy since key is const
12454 first_cell.first = cell_iterator(this,
12455 first_cell.first->level(),
12456 first_cell.first->index());
12457 second_cell_and_orientation.first.first =
12458 cell_iterator(this,
12459 second_cell_and_orientation.first.first->level(),
12460 second_cell_and_orientation.first.first->index());
12461
12462 this->periodic_face_map[first_cell] = second_cell_and_orientation;
12463 }
12464
12465 // inform those who are listening on other_tria of the copy operation
12466 other_tria.signals.copy(*this);
12467 // also inform all listeners of the current triangulation that the
12468 // triangulation has been created
12469 signals.create();
12470
12471 // note that we need not copy the
12472 // subscriptor!
12473}
12474
12475
12476
12477template <int dim, int spacedim>
12480{
12481 this->update_reference_cells();
12482
12483 if (this->all_reference_cells_are_hyper_cube())
12484 {
12485 this->policy =
12487 dim,
12488 spacedim,
12490 }
12491 else
12492 {
12493 this->policy =
12495 dim,
12496 spacedim,
12498 }
12499}
12500
12501
12502
12503template <int dim, int spacedim>
12506 const std::vector<Point<spacedim>> &v,
12507 const std::vector<CellData<dim>> &cells,
12508 const SubCellData &subcelldata)
12509{
12510 Assert((vertices.empty()) && (levels.empty()) && (faces == nullptr),
12511 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
12512 // check that no forbidden arrays
12513 // are used
12514 Assert(subcelldata.check_consistency(dim), ExcInternalError());
12515
12516 // try to create a triangulation; if this fails, we still want to
12517 // throw an exception but if we just do so we'll get into trouble
12518 // because sometimes other objects are already attached to it:
12519 try
12520 {
12522 create_triangulation(v, cells, subcelldata, *this);
12523 }
12524 catch (...)
12525 {
12526 clear_despite_subscriptions();
12527 throw;
12528 }
12529
12530 reset_policy();
12531
12532 // update our counts of the various elements of a triangulation, and set
12533 // active_cell_indices of all cells
12534 reset_cell_vertex_indices_cache();
12536 *this, levels.size(), number_cache);
12537 reset_active_cell_indices();
12538 reset_global_cell_indices();
12539
12540 // now verify that there are indeed no distorted cells. as per the
12541 // documentation of this class, we first collect all distorted cells
12542 // and then throw an exception if there are any
12543 if (check_for_distorted_cells)
12544 {
12545 DistortedCellList distorted_cells = collect_distorted_coarse_cells(*this);
12546 // throw the array (and fill the various location fields) if
12547 // there are distorted cells. otherwise, just fall off the end
12548 // of the function
12549 AssertThrow(distorted_cells.distorted_cells.empty(), distorted_cells);
12550 }
12551
12552
12553 /*
12554 When the triangulation is a manifold (dim < spacedim) and made of
12555 quadrilaterals, the normal field provided from the map class depends on
12556 the order of the vertices. It may happen that this normal field is
12557 discontinuous. The following code takes care that this is not the case by
12558 setting the cell direction flag on those cell that produce the wrong
12559 orientation.
12560
12561 To determine if 2 neighbors have the same or opposite orientation we use
12562 a truth table. Its entries are indexed by the local indices of the
12563 common face. For example if two elements share a face, and this face is
12564 face 0 for element 0 and face 1 for element 1, then table(0,1) will tell
12565 whether the orientation are the same (true) or opposite (false).
12566
12567 Even though there may be a combinatorial/graph theory argument to get this
12568 table in any dimension, I tested by hand all the different possible cases
12569 in 1D and 2D to generate the table.
12570
12571 Assuming that a surface respects the standard orientation for 2d meshes,
12572 the truth tables are symmetric and their true values are the following
12573
12574 - 1D curves: (0,1)
12575 - 2D surface: (0,1),(0,2),(1,3),(2,3)
12576
12577 We store this data using an n_faces x n_faces full matrix, which is
12578 actually much bigger than the minimal data required, but it makes the code
12579 more readable.
12580
12581 */
12582 if ((dim == spacedim - 1) && all_reference_cells_are_hyper_cube())
12583 {
12586 switch (dim)
12587 {
12588 case 1:
12589 {
12590 const bool values[][2] = {{false, true}, {true, false}};
12591 for (const unsigned int i : GeometryInfo<dim>::face_indices())
12592 for (const unsigned int j : GeometryInfo<dim>::face_indices())
12593 correct(i, j) = values[i][j];
12594 break;
12595 }
12596 case 2:
12597 {
12598 const bool values[][4] = {{false, true, true, false},
12599 {true, false, false, true},
12600 {true, false, false, true},
12601 {false, true, true, false}};
12602 for (const unsigned int i : GeometryInfo<dim>::face_indices())
12603 for (const unsigned int j : GeometryInfo<dim>::face_indices())
12604 correct(i, j) = (values[i][j]);
12605 break;
12606 }
12607 default:
12609 }
12610
12611
12612 std::list<active_cell_iterator> this_round, next_round;
12613 active_cell_iterator neighbor;
12614
12615 // Start with the first cell and (arbitrarily) decide that its
12616 // direction flag should be 'true':
12617 this_round.push_back(begin_active());
12618 begin_active()->set_direction_flag(true);
12619 begin_active()->set_user_flag();
12620
12621 while (this_round.size() > 0)
12622 {
12623 for (const auto &cell : this_round)
12624 {
12625 for (const unsigned int i : cell->face_indices())
12626 {
12627 if (cell->face(i)->at_boundary() == false)
12628 {
12629 // Consider the i'th neighbor of a cell for
12630 // which we have already set the direction:
12631 neighbor = cell->neighbor(i);
12632
12633 const unsigned int nb_of_nb =
12634 cell->neighbor_of_neighbor(i);
12635
12636 // If we already saw this neighboring cell,
12637 // check that everything is fine:
12638 if (neighbor->user_flag_set())
12639 {
12640 Assert(
12641 !(correct(i, nb_of_nb) ^
12642 (neighbor->direction_flag() ==
12643 cell->direction_flag())),
12644 ExcMessage(
12645 "The triangulation you are trying to create is not orientable."));
12646 }
12647 else
12648 {
12649 // We had not seen this cell yet. Set its
12650 // orientation flag (if necessary), mark it
12651 // as treated via the user flag, and push it
12652 // onto the list of cells to start work from
12653 // the next time around:
12654 if (correct(i, nb_of_nb) ^
12655 (neighbor->direction_flag() ==
12656 cell->direction_flag()))
12657 neighbor->set_direction_flag(
12658 !neighbor->direction_flag());
12659 neighbor->set_user_flag();
12660 next_round.push_back(neighbor);
12661 }
12662 }
12663 }
12664 }
12665
12666 // Before we quit let's check that if the triangulation is
12667 // disconnected that we still get all cells by starting
12668 // again from the first cell we haven't treated yet -- that
12669 // is, the first cell of the next disconnected component we
12670 // had not yet touched.
12671 if (next_round.empty())
12672 for (const auto &cell : this->active_cell_iterators())
12673 if (cell->user_flag_set() == false)
12674 {
12675 next_round.push_back(cell);
12676 cell->set_direction_flag(true);
12677 cell->set_user_flag();
12678 break;
12679 }
12680
12681 // Go on to the next round:
12682 next_round.swap(this_round);
12683 next_round.clear();
12684 }
12685 clear_user_flags();
12686 }
12687
12688 this->update_cell_relations();
12689
12690 // inform all listeners that the triangulation has been created
12691 signals.create();
12692}
12693
12694
12695
12696template <int dim, int spacedim>
12700{
12701 // 1) create coarse grid
12703 construction_data.coarse_cells,
12704 SubCellData());
12705
12706 // create a copy of cell_infos such that we can sort them
12707 auto cell_infos = construction_data.cell_infos;
12708
12709 // sort cell_infos on each level separately
12710 for (auto &cell_info : cell_infos)
12711 std::sort(
12712 cell_info.begin(),
12713 cell_info.end(),
12716 const CellId a_id(a.id);
12717 const CellId b_id(b.id);
12718
12719 const auto a_coarse_cell_index =
12720 this->coarse_cell_id_to_coarse_cell_index(a_id.get_coarse_cell_id());
12721 const auto b_coarse_cell_index =
12722 this->coarse_cell_id_to_coarse_cell_index(b_id.get_coarse_cell_id());
12723
12724 // according to their coarse-cell index and if that is
12725 // same according to their cell id (the result is that
12726 // cells on each level are sorted according to their
12727 // index on that level - what we need in the following
12728 // operations)
12729 if (a_coarse_cell_index != b_coarse_cell_index)
12730 return a_coarse_cell_index < b_coarse_cell_index;
12731 else
12732 return a_id < b_id;
12733 });
12734
12735 // 2) create all levels via a sequence of refinements. note that
12736 // we must make sure that we actually have cells on this level,
12737 // which is not clear in a parallel context for some processes
12738 for (unsigned int level = 0;
12739 level < cell_infos.size() && !cell_infos[level].empty();
12740 ++level)
12741 {
12742 // a) set manifold ids here (because new vertices have to be
12743 // positioned correctly during each refinement step)
12744 {
12745 auto cell = this->begin(level);
12746 auto cell_info = cell_infos[level].begin();
12747 for (; cell_info != cell_infos[level].end(); ++cell_info)
12748 {
12749 while (cell_info->id != cell->id().template to_binary<dim>())
12750 ++cell;
12751 if (dim == 2)
12752 for (const auto face : cell->face_indices())
12753 cell->face(face)->set_manifold_id(
12754 cell_info->manifold_line_ids[face]);
12755 else if (dim == 3)
12756 {
12757 for (const auto face : cell->face_indices())
12758 cell->face(face)->set_manifold_id(
12759 cell_info->manifold_quad_ids[face]);
12760
12761 const auto line_indices = internal::TriaAccessorImplementation::
12762 Implementation::get_line_indices_of_cell(*cell);
12763 for (unsigned int l = 0; l < cell->n_lines(); ++l)
12764 {
12765 raw_line_iterator line(this, 0, line_indices[l]);
12766 line->set_manifold_id(cell_info->manifold_line_ids[l]);
12767 }
12768 }
12769
12770 cell->set_manifold_id(cell_info->manifold_id);
12771 }
12772 }
12773
12774 // b) perform refinement on all levels but on the finest
12775 if (level + 1 != cell_infos.size())
12776 {
12777 // find cells that should have children and mark them for
12778 // refinement
12779 auto coarse_cell = this->begin(level);
12780 auto fine_cell_info = cell_infos[level + 1].begin();
12781
12782 // loop over all cells on the next level
12783 for (; fine_cell_info != cell_infos[level + 1].end();
12784 ++fine_cell_info)
12785 {
12786 // find the parent of that cell
12787 while (
12788 !coarse_cell->id().is_parent_of(CellId(fine_cell_info->id)))
12789 ++coarse_cell;
12790
12791 // set parent for refinement
12792 coarse_cell->set_refine_flag();
12793 }
12794
12795 // execute refinement
12796 ::Triangulation<dim,
12797 spacedim>::execute_coarsening_and_refinement();
12798 }
12799 }
12800
12801 // 3) set boundary ids
12802 for (unsigned int level = 0;
12803 level < cell_infos.size() && !cell_infos[level].empty();
12804 ++level)
12805 {
12806 auto cell = this->begin(level);
12807 auto cell_info = cell_infos[level].begin();
12808 for (; cell_info != cell_infos[level].end(); ++cell_info)
12809 {
12810 // find cell that has the correct cell
12811 while (cell_info->id != cell->id().template to_binary<dim>())
12812 ++cell;
12813
12814 // boundary ids
12815 for (auto pair : cell_info->boundary_ids)
12816 if (cell->face(pair.first)->at_boundary())
12817 cell->face(pair.first)->set_boundary_id(pair.second);
12818 }
12819 }
12820
12821 // inform all listeners that the triangulation has been created
12822 signals.create();
12823}
12824
12825
12826template <int dim, int spacedim>
12829{
12830 AssertThrow(dim + 1 == spacedim,
12831 ExcMessage(
12832 "This function can only be called if dim == spacedim-1."));
12833 for (const auto &cell : this->active_cell_iterators())
12834 cell->set_direction_flag(!cell->direction_flag());
12835}
12836
12837
12838
12839template <int dim, int spacedim>
12842{
12843 Assert(n_cells() > 0,
12844 ExcMessage("Error: An empty Triangulation can not be refined."));
12845
12846 for (const auto &cell : this->active_cell_iterators())
12847 {
12848 cell->clear_coarsen_flag();
12849 cell->set_refine_flag();
12850 cell->set_refine_choice();
12851 }
12852}
12853
12854
12855
12856template <int dim, int spacedim>
12858void Triangulation<dim, spacedim>::refine_global(const unsigned int times)
12859{
12860 Assert(n_cells() > 0,
12861 ExcMessage("Error: An empty Triangulation can not be refined."));
12862
12863 for (unsigned int i = 0; i < times; ++i)
12864 {
12865 set_all_refine_flags();
12866 execute_coarsening_and_refinement();
12867 }
12868}
12869
12870
12871
12872template <int dim, int spacedim>
12874void Triangulation<dim, spacedim>::coarsen_global(const unsigned int times)
12875{
12876 for (unsigned int i = 0; i < times; ++i)
12877 {
12878 for (const auto &cell : this->active_cell_iterators())
12879 {
12880 cell->clear_refine_flag();
12881 cell->set_coarsen_flag();
12882 }
12883 execute_coarsening_and_refinement();
12884 }
12885}
12886
12887
12888#endif
12889/*-------------------- refine/coarsen flags -------------------------*/
12890
12891#ifndef DOXYGEN
12892
12893template <int dim, int spacedim>
12895void Triangulation<dim, spacedim>::save_refine_flags(std::vector<bool> &v) const
12896{
12897 v.resize(dim * n_active_cells(), false);
12898 std::vector<bool>::iterator i = v.begin();
12899
12900 for (const auto &cell : this->active_cell_iterators())
12901 for (unsigned int j = 0; j < dim; ++j, ++i)
12902 if (cell->refine_flag_set() & (1 << j))
12903 *i = true;
12904
12905 Assert(i == v.end(), ExcInternalError());
12906}
12907
12908
12909
12910template <int dim, int spacedim>
12912void Triangulation<dim, spacedim>::save_refine_flags(std::ostream &out) const
12913{
12914 std::vector<bool> v;
12915 save_refine_flags(v);
12916 write_bool_vector(mn_tria_refine_flags_begin,
12917 v,
12919 out);
12920}
12921
12922
12923
12924template <int dim, int spacedim>
12927{
12928 std::vector<bool> v;
12929 read_bool_vector(mn_tria_refine_flags_begin, v, mn_tria_refine_flags_end, in);
12930 load_refine_flags(v);
12931}
12932
12933
12934
12935template <int dim, int spacedim>
12937void Triangulation<dim, spacedim>::load_refine_flags(const std::vector<bool> &v)
12938{
12939 AssertThrow(v.size() == dim * n_active_cells(), ExcGridReadError());
12940
12941 std::vector<bool>::const_iterator i = v.begin();
12942 for (const auto &cell : this->active_cell_iterators())
12943 {
12944 unsigned int ref_case = 0;
12945
12946 for (unsigned int j = 0; j < dim; ++j, ++i)
12947 if (*i == true)
12948 ref_case += 1 << j;
12950 ExcGridReadError());
12951 if (ref_case > 0)
12952 cell->set_refine_flag(RefinementCase<dim>(ref_case));
12953 else
12954 cell->clear_refine_flag();
12955 }
12956
12957 Assert(i == v.end(), ExcInternalError());
12958}
12959
12960
12961
12962template <int dim, int spacedim>
12965 std::vector<bool> &v) const
12966{
12967 v.resize(n_active_cells(), false);
12968 std::vector<bool>::iterator i = v.begin();
12969 for (const auto &cell : this->active_cell_iterators())
12970 {
12971 *i = cell->coarsen_flag_set();
12972 ++i;
12973 }
12974
12975 Assert(i == v.end(), ExcInternalError());
12976}
12977
12978
12979
12980template <int dim, int spacedim>
12982void Triangulation<dim, spacedim>::save_coarsen_flags(std::ostream &out) const
12983{
12984 std::vector<bool> v;
12985 save_coarsen_flags(v);
12986 write_bool_vector(mn_tria_coarsen_flags_begin,
12987 v,
12989 out);
12990}
12991
12992
12993
12994template <int dim, int spacedim>
12997{
12998 std::vector<bool> v;
12999 read_bool_vector(mn_tria_coarsen_flags_begin,
13000 v,
13002 in);
13003 load_coarsen_flags(v);
13004}
13005
13006
13007
13008template <int dim, int spacedim>
13011 const std::vector<bool> &v)
13012{
13013 Assert(v.size() == n_active_cells(), ExcGridReadError());
13014
13015 std::vector<bool>::const_iterator i = v.begin();
13016 for (const auto &cell : this->active_cell_iterators())
13017 {
13018 if (*i == true)
13019 cell->set_coarsen_flag();
13020 else
13021 cell->clear_coarsen_flag();
13022 ++i;
13023 }
13024
13025 Assert(i == v.end(), ExcInternalError());
13026}
13027
13028
13029template <int dim, int spacedim>
13032{
13033 return anisotropic_refinement;
13034}
13035
13036
13037#endif
13038
13039namespace internal
13040{
13041 namespace
13042 {
13043 std::vector<std::vector<bool>>
13044 extract_raw_coarsen_flags(
13045 const std::vector<std::unique_ptr<
13047 {
13048 std::vector<std::vector<bool>> coarsen_flags(levels.size());
13049 for (unsigned int level = 0; level < levels.size(); ++level)
13050 coarsen_flags[level] = levels[level]->coarsen_flags;
13051 return coarsen_flags;
13052 }
13053
13054 std::vector<std::vector<std::uint8_t>>
13055 extract_raw_refine_flags(
13056 const std::vector<std::unique_ptr<
13058 {
13059 std::vector<std::vector<std::uint8_t>> refine_flags(levels.size());
13060 for (unsigned int level = 0; level < levels.size(); ++level)
13061 refine_flags[level] = levels[level]->refine_flags;
13062 return refine_flags;
13063 }
13064 } // namespace
13065} // namespace internal
13066
13067
13068/*-------------------- user data/flags -------------------------*/
13069
13070
13071namespace
13072{
13073 // clear user data of cells
13074 void
13075 clear_user_data(std::vector<std::unique_ptr<
13077 {
13078 for (auto &level : levels)
13079 level->cells.clear_user_data();
13080 }
13081
13082
13083 // clear user data of faces
13084 void
13086 {
13087 if (faces->dim == 2)
13088 {
13089 faces->lines.clear_user_data();
13090 }
13091
13092
13093 if (faces->dim == 3)
13094 {
13095 faces->lines.clear_user_data();
13096 faces->quads.clear_user_data();
13097 }
13098 }
13099} // namespace
13100
13101#ifndef DOXYGEN
13102
13103template <int dim, int spacedim>
13106{
13107 // let functions in anonymous namespace do their work
13108 ::clear_user_data(levels);
13109 if (dim > 1)
13110 ::clear_user_data(faces.get());
13111}
13112
13113
13114
13115namespace
13116{
13117 void
13118 clear_user_flags_line(
13119 unsigned int dim,
13120 std::vector<
13121 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
13122 &levels,
13124 {
13125 if (dim == 1)
13126 {
13127 for (const auto &level : levels)
13128 level->cells.clear_user_flags();
13129 }
13130 else if (dim == 2 || dim == 3)
13131 {
13132 faces->lines.clear_user_flags();
13133 }
13134 else
13135 {
13137 }
13138 }
13139} // namespace
13140
13141
13142template <int dim, int spacedim>
13145{
13146 ::clear_user_flags_line(dim, levels, faces.get());
13147}
13148
13149
13150
13151namespace
13152{
13153 void
13154 clear_user_flags_quad(
13155 unsigned int dim,
13156 std::vector<
13157 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
13158 &levels,
13160 {
13161 if (dim == 1)
13162 {
13163 // nothing to do in 1d
13164 }
13165 else if (dim == 2)
13166 {
13167 for (const auto &level : levels)
13168 level->cells.clear_user_flags();
13169 }
13170 else if (dim == 3)
13171 {
13172 faces->quads.clear_user_flags();
13173 }
13174 else
13175 {
13177 }
13178 }
13179} // namespace
13180
13181
13182template <int dim, int spacedim>
13185{
13186 ::clear_user_flags_quad(dim, levels, faces.get());
13187}
13188
13189
13190
13191namespace
13192{
13193 void
13194 clear_user_flags_hex(
13195 unsigned int dim,
13196 std::vector<
13197 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
13198 &levels,
13200 {
13201 if (dim == 1)
13202 {
13203 // nothing to do in 1d
13204 }
13205 else if (dim == 2)
13206 {
13207 // nothing to do in 2d
13208 }
13209 else if (dim == 3)
13210 {
13211 for (const auto &level : levels)
13212 level->cells.clear_user_flags();
13213 }
13214 else
13215 {
13217 }
13218 }
13219} // namespace
13220
13221
13222template <int dim, int spacedim>
13225{
13226 ::clear_user_flags_hex(dim, levels, faces.get());
13227}
13228
13229
13230
13231template <int dim, int spacedim>
13234{
13235 clear_user_flags_line();
13236 clear_user_flags_quad();
13237 clear_user_flags_hex();
13238}
13239
13240
13241
13242template <int dim, int spacedim>
13244void Triangulation<dim, spacedim>::save_user_flags(std::ostream &out) const
13245{
13246 save_user_flags_line(out);
13247
13248 if (dim >= 2)
13249 save_user_flags_quad(out);
13250
13251 if (dim >= 3)
13252 save_user_flags_hex(out);
13253
13254 if (dim >= 4)
13256}
13257
13258
13259
13260template <int dim, int spacedim>
13262void Triangulation<dim, spacedim>::save_user_flags(std::vector<bool> &v) const
13263{
13264 // clear vector and append
13265 // all the stuff later on
13266 v.clear();
13267
13268 std::vector<bool> tmp;
13269
13270 save_user_flags_line(tmp);
13271 v.insert(v.end(), tmp.begin(), tmp.end());
13272
13273 if (dim >= 2)
13274 {
13275 save_user_flags_quad(tmp);
13276 v.insert(v.end(), tmp.begin(), tmp.end());
13277 }
13278
13279 if (dim >= 3)
13280 {
13281 save_user_flags_hex(tmp);
13282 v.insert(v.end(), tmp.begin(), tmp.end());
13283 }
13284
13285 if (dim >= 4)
13287}
13288
13289
13290
13291template <int dim, int spacedim>
13294{
13295 load_user_flags_line(in);
13296
13297 if (dim >= 2)
13298 load_user_flags_quad(in);
13299
13300 if (dim >= 3)
13301 load_user_flags_hex(in);
13302
13303 if (dim >= 4)
13305}
13306
13307
13308
13309template <int dim, int spacedim>
13311void Triangulation<dim, spacedim>::load_user_flags(const std::vector<bool> &v)
13312{
13313 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
13314 std::vector<bool> tmp;
13315
13316 // first extract the flags
13317 // belonging to lines
13318 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
13319 // and set the lines
13320 load_user_flags_line(tmp);
13321
13322 if (dim >= 2)
13323 {
13324 tmp.clear();
13325 tmp.insert(tmp.end(),
13326 v.begin() + n_lines(),
13327 v.begin() + n_lines() + n_quads());
13328 load_user_flags_quad(tmp);
13329 }
13330
13331 if (dim >= 3)
13332 {
13333 tmp.clear();
13334 tmp.insert(tmp.end(),
13335 v.begin() + n_lines() + n_quads(),
13336 v.begin() + n_lines() + n_quads() + n_hexs());
13337 load_user_flags_hex(tmp);
13338 }
13339
13340 if (dim >= 4)
13342}
13343
13344
13345
13346template <int dim, int spacedim>
13349 std::vector<bool> &v) const
13350{
13351 v.resize(n_lines(), false);
13352 std::vector<bool>::iterator i = v.begin();
13353 line_iterator line = begin_line(), endl = end_line();
13354 for (; line != endl; ++line, ++i)
13355 *i = line->user_flag_set();
13356
13357 Assert(i == v.end(), ExcInternalError());
13358}
13359
13360
13361
13362template <int dim, int spacedim>
13364void Triangulation<dim, spacedim>::save_user_flags_line(std::ostream &out) const
13365{
13366 std::vector<bool> v;
13367 save_user_flags_line(v);
13368 write_bool_vector(mn_tria_line_user_flags_begin,
13369 v,
13371 out);
13372}
13373
13374
13375
13376template <int dim, int spacedim>
13379{
13380 std::vector<bool> v;
13381 read_bool_vector(mn_tria_line_user_flags_begin,
13382 v,
13384 in);
13385 load_user_flags_line(v);
13386}
13387
13388
13389
13390template <int dim, int spacedim>
13393 const std::vector<bool> &v)
13394{
13395 Assert(v.size() == n_lines(), ExcGridReadError());
13396
13397 line_iterator line = begin_line(), endl = end_line();
13398 std::vector<bool>::const_iterator i = v.begin();
13399 for (; line != endl; ++line, ++i)
13400 if (*i == true)
13401 line->set_user_flag();
13402 else
13403 line->clear_user_flag();
13404
13405 Assert(i == v.end(), ExcInternalError());
13406}
13407
13408#endif
13409
13410namespace
13411{
13412 template <typename Iterator>
13413 bool
13414 get_user_flag(const Iterator &i)
13415 {
13416 return i->user_flag_set();
13417 }
13418
13419
13420
13421 template <int structdim, int dim, int spacedim>
13422 bool
13424 {
13426 return false;
13427 }
13428
13429
13430
13431 template <typename Iterator>
13432 void
13433 set_user_flag(const Iterator &i)
13434 {
13435 i->set_user_flag();
13436 }
13437
13438
13439
13440 template <int structdim, int dim, int spacedim>
13441 void
13443 {
13445 }
13446
13447
13448
13449 template <typename Iterator>
13450 void
13451 clear_user_flag(const Iterator &i)
13452 {
13453 i->clear_user_flag();
13454 }
13455
13456
13457
13458 template <int structdim, int dim, int spacedim>
13459 void
13460 clear_user_flag(
13462 {
13464 }
13465} // namespace
13466
13467#ifndef DOXYGEN
13468
13469template <int dim, int spacedim>
13472 std::vector<bool> &v) const
13473{
13474 v.resize(n_quads(), false);
13475
13476 if (dim >= 2)
13477 {
13478 std::vector<bool>::iterator i = v.begin();
13479 quad_iterator quad = begin_quad(), endq = end_quad();
13480 for (; quad != endq; ++quad, ++i)
13481 *i = get_user_flag(quad);
13482
13483 Assert(i == v.end(), ExcInternalError());
13484 }
13485}
13486
13487
13488
13489template <int dim, int spacedim>
13491void Triangulation<dim, spacedim>::save_user_flags_quad(std::ostream &out) const
13492{
13493 std::vector<bool> v;
13494 save_user_flags_quad(v);
13495 write_bool_vector(mn_tria_quad_user_flags_begin,
13496 v,
13498 out);
13499}
13500
13501
13502
13503template <int dim, int spacedim>
13506{
13507 std::vector<bool> v;
13508 read_bool_vector(mn_tria_quad_user_flags_begin,
13509 v,
13511 in);
13512 load_user_flags_quad(v);
13513}
13514
13515
13516
13517template <int dim, int spacedim>
13520 const std::vector<bool> &v)
13521{
13522 Assert(v.size() == n_quads(), ExcGridReadError());
13523
13524 if (dim >= 2)
13525 {
13526 quad_iterator quad = begin_quad(), endq = end_quad();
13527 std::vector<bool>::const_iterator i = v.begin();
13528 for (; quad != endq; ++quad, ++i)
13529 if (*i == true)
13530 set_user_flag(quad);
13531 else
13532 clear_user_flag(quad);
13533
13534 Assert(i == v.end(), ExcInternalError());
13535 }
13536}
13537
13538
13539
13540template <int dim, int spacedim>
13543 std::vector<bool> &v) const
13544{
13545 v.resize(n_hexs(), false);
13546
13547 if (dim >= 3)
13548 {
13549 std::vector<bool>::iterator i = v.begin();
13550 hex_iterator hex = begin_hex(), endh = end_hex();
13551 for (; hex != endh; ++hex, ++i)
13552 *i = get_user_flag(hex);
13553
13554 Assert(i == v.end(), ExcInternalError());
13555 }
13556}
13557
13558
13559
13560template <int dim, int spacedim>
13562void Triangulation<dim, spacedim>::save_user_flags_hex(std::ostream &out) const
13563{
13564 std::vector<bool> v;
13565 save_user_flags_hex(v);
13566 write_bool_vector(mn_tria_hex_user_flags_begin,
13567 v,
13569 out);
13570}
13571
13572
13573
13574template <int dim, int spacedim>
13577{
13578 std::vector<bool> v;
13579 read_bool_vector(mn_tria_hex_user_flags_begin,
13580 v,
13582 in);
13583 load_user_flags_hex(v);
13584}
13585
13586
13587
13588template <int dim, int spacedim>
13591 const std::vector<bool> &v)
13592{
13593 Assert(v.size() == n_hexs(), ExcGridReadError());
13594
13595 if (dim >= 3)
13596 {
13597 hex_iterator hex = begin_hex(), endh = end_hex();
13598 std::vector<bool>::const_iterator i = v.begin();
13599 for (; hex != endh; ++hex, ++i)
13600 if (*i == true)
13601 set_user_flag(hex);
13602 else
13603 clear_user_flag(hex);
13604
13605 Assert(i == v.end(), ExcInternalError());
13606 }
13607}
13608
13609
13610
13611template <int dim, int spacedim>
13614 std::vector<unsigned int> &v) const
13615{
13616 // clear vector and append all the
13617 // stuff later on
13618 v.clear();
13619
13620 std::vector<unsigned int> tmp;
13621
13622 save_user_indices_line(tmp);
13623 v.insert(v.end(), tmp.begin(), tmp.end());
13624
13625 if (dim >= 2)
13626 {
13627 save_user_indices_quad(tmp);
13628 v.insert(v.end(), tmp.begin(), tmp.end());
13629 }
13630
13631 if (dim >= 3)
13632 {
13633 save_user_indices_hex(tmp);
13634 v.insert(v.end(), tmp.begin(), tmp.end());
13635 }
13636
13637 if (dim >= 4)
13639}
13640
13641
13642
13643template <int dim, int spacedim>
13646 const std::vector<unsigned int> &v)
13647{
13648 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
13649 std::vector<unsigned int> tmp;
13650
13651 // first extract the indices
13652 // belonging to lines
13653 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
13654 // and set the lines
13655 load_user_indices_line(tmp);
13656
13657 if (dim >= 2)
13658 {
13659 tmp.clear();
13660 tmp.insert(tmp.end(),
13661 v.begin() + n_lines(),
13662 v.begin() + n_lines() + n_quads());
13663 load_user_indices_quad(tmp);
13664 }
13665
13666 if (dim >= 3)
13667 {
13668 tmp.clear();
13669 tmp.insert(tmp.end(),
13670 v.begin() + n_lines() + n_quads(),
13671 v.begin() + n_lines() + n_quads() + n_hexs());
13672 load_user_indices_hex(tmp);
13673 }
13674
13675 if (dim >= 4)
13677}
13678
13679
13680
13681template <int dim, int spacedim>
13683void Triangulation<dim, spacedim>::save(const std::string &file_basename) const
13684{
13685 // Save triangulation information.
13686 {
13687 std::ofstream ofs_tria(file_basename + "_triangulation.data");
13688 AssertThrow(ofs_tria.fail() == false, ExcIO());
13689
13690 boost::archive::text_oarchive oa(ofs_tria, boost::archive::no_header);
13691 save(oa,
13693 }
13694
13695 // Save attached data.
13696 {
13697 std::ofstream ofs_info(file_basename + ".info");
13698 ofs_info
13699 << "version nproc n_attached_fixed_size_objs n_attached_variable_size_objs n_active_cells"
13700 << std::endl
13702 << " " << 1 << " " << this->cell_attached_data.pack_callbacks_fixed.size()
13703 << " " << this->cell_attached_data.pack_callbacks_variable.size() << " "
13704 << this->n_global_active_cells() << std::endl;
13705 }
13706
13707 this->save_attached_data(0, this->n_global_active_cells(), file_basename);
13708}
13709
13710
13711
13712template <int dim, int spacedim>
13714void Triangulation<dim, spacedim>::load(const std::string &file_basename)
13715{
13716 // Load triangulation information.
13717 {
13718 std::ifstream ifs_tria(file_basename + "_triangulation.data");
13719 AssertThrow(ifs_tria.fail() == false, ExcIO());
13720
13721 boost::archive::text_iarchive ia(ifs_tria, boost::archive::no_header);
13722 load(ia,
13724 }
13725
13726 // Load attached data.
13727 unsigned int version, numcpus, attached_count_fixed, attached_count_variable,
13728 n_global_active_cells;
13729 {
13730 std::ifstream ifs_info(std::string(file_basename) + ".info");
13731 AssertThrow(ifs_info.fail() == false, ExcIO());
13732 std::string firstline;
13733 std::getline(ifs_info, firstline);
13734 ifs_info >> version >> numcpus >> attached_count_fixed >>
13735 attached_count_variable >> n_global_active_cells;
13736 }
13737
13738 AssertThrow(numcpus == 1,
13739 ExcMessage("Incompatible number of CPUs found in .info file."));
13740
13741 const auto expected_version =
13743 spacedim>::version_number;
13744 AssertThrow(version == expected_version,
13745 ExcMessage(
13746 "The information saved in the file you are trying "
13747 "to read the triangulation from was written with an "
13748 "incompatible file format version and cannot be read."));
13749 Assert(this->n_global_active_cells() == n_global_active_cells,
13750 ExcMessage("The number of cells of the triangulation differs "
13751 "from the number of cells written into the .info file."));
13752
13753 // Clear all of the callback data, as explained in the documentation of
13754 // register_data_attach().
13755 this->cell_attached_data.n_attached_data_sets = 0;
13756 this->cell_attached_data.n_attached_deserialize =
13757 attached_count_fixed + attached_count_variable;
13758
13759 this->load_attached_data(0,
13760 this->n_global_active_cells(),
13761 this->n_active_cells(),
13762 file_basename,
13763 attached_count_fixed,
13764 attached_count_variable);
13765
13766 this->update_cell_relations();
13767}
13768
13769#endif
13770namespace
13771{
13772 template <typename Iterator>
13773 unsigned int
13774 get_user_index(const Iterator &i)
13775 {
13776 return i->user_index();
13777 }
13778
13779
13780
13781 template <int structdim, int dim, int spacedim>
13782 unsigned int
13783 get_user_index(
13785 {
13788 }
13789
13790
13791
13792 template <typename Iterator>
13793 void
13794 set_user_index(const Iterator &i, const unsigned int x)
13795 {
13796 i->set_user_index(x);
13797 }
13798
13799
13800
13801 template <int structdim, int dim, int spacedim>
13802 void
13803 set_user_index(
13805 const unsigned int)
13806 {
13808 }
13809} // namespace
13810
13811#ifndef DOXYGEN
13812
13813template <int dim, int spacedim>
13816 std::vector<unsigned int> &v) const
13817{
13818 v.resize(n_lines(), 0);
13819 std::vector<unsigned int>::iterator i = v.begin();
13820 line_iterator line = begin_line(), endl = end_line();
13821 for (; line != endl; ++line, ++i)
13822 *i = line->user_index();
13823}
13824
13825
13826
13827template <int dim, int spacedim>
13830 const std::vector<unsigned int> &v)
13831{
13832 Assert(v.size() == n_lines(), ExcGridReadError());
13833
13834 line_iterator line = begin_line(), endl = end_line();
13835 std::vector<unsigned int>::const_iterator i = v.begin();
13836 for (; line != endl; ++line, ++i)
13837 line->set_user_index(*i);
13838}
13839
13840
13841template <int dim, int spacedim>
13844 std::vector<unsigned int> &v) const
13845{
13846 v.resize(n_quads(), 0);
13847
13848 if (dim >= 2)
13849 {
13850 std::vector<unsigned int>::iterator i = v.begin();
13851 quad_iterator quad = begin_quad(), endq = end_quad();
13852 for (; quad != endq; ++quad, ++i)
13853 *i = get_user_index(quad);
13854 }
13855}
13856
13857
13858
13859template <int dim, int spacedim>
13862 const std::vector<unsigned int> &v)
13863{
13864 Assert(v.size() == n_quads(), ExcGridReadError());
13865
13866 if (dim >= 2)
13867 {
13868 quad_iterator quad = begin_quad(), endq = end_quad();
13869 std::vector<unsigned int>::const_iterator i = v.begin();
13870 for (; quad != endq; ++quad, ++i)
13871 set_user_index(quad, *i);
13872 }
13873}
13874
13875
13876template <int dim, int spacedim>
13879 std::vector<unsigned int> &v) const
13880{
13881 v.resize(n_hexs(), 0);
13882
13883 if (dim >= 3)
13884 {
13885 std::vector<unsigned int>::iterator i = v.begin();
13886 hex_iterator hex = begin_hex(), endh = end_hex();
13887 for (; hex != endh; ++hex, ++i)
13888 *i = get_user_index(hex);
13889 }
13890}
13891
13892
13893
13894template <int dim, int spacedim>
13897 const std::vector<unsigned int> &v)
13898{
13899 Assert(v.size() == n_hexs(), ExcGridReadError());
13900
13901 if (dim >= 3)
13902 {
13903 hex_iterator hex = begin_hex(), endh = end_hex();
13904 std::vector<unsigned int>::const_iterator i = v.begin();
13905 for (; hex != endh; ++hex, ++i)
13906 set_user_index(hex, *i);
13907 }
13908}
13909
13910#endif
13911
13912
13913//---------------- user pointers ----------------------------------------//
13914
13915
13916namespace
13917{
13918 template <typename Iterator>
13919 void *
13920 get_user_pointer(const Iterator &i)
13921 {
13922 return i->user_pointer();
13923 }
13924
13925
13926
13927 template <int structdim, int dim, int spacedim>
13928 void *
13929 get_user_pointer(
13931 {
13933 return nullptr;
13934 }
13935
13936
13937
13938 template <typename Iterator>
13939 void
13940 set_user_pointer(const Iterator &i, void *x)
13941 {
13942 i->set_user_pointer(x);
13943 }
13944
13945
13946
13947 template <int structdim, int dim, int spacedim>
13948 void
13949 set_user_pointer(
13951 void *)
13952 {
13954 }
13955} // namespace
13956
13957#ifndef DOXYGEN
13958
13959template <int dim, int spacedim>
13962 std::vector<void *> &v) const
13963{
13964 // clear vector and append all the
13965 // stuff later on
13966 v.clear();
13967
13968 std::vector<void *> tmp;
13969
13970 save_user_pointers_line(tmp);
13971 v.insert(v.end(), tmp.begin(), tmp.end());
13972
13973 if (dim >= 2)
13974 {
13975 save_user_pointers_quad(tmp);
13976 v.insert(v.end(), tmp.begin(), tmp.end());
13977 }
13978
13979 if (dim >= 3)
13980 {
13981 save_user_pointers_hex(tmp);
13982 v.insert(v.end(), tmp.begin(), tmp.end());
13983 }
13984
13985 if (dim >= 4)
13987}
13988
13989
13990
13991template <int dim, int spacedim>
13994 const std::vector<void *> &v)
13995{
13996 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
13997 std::vector<void *> tmp;
13998
13999 // first extract the pointers
14000 // belonging to lines
14001 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
14002 // and set the lines
14003 load_user_pointers_line(tmp);
14004
14005 if (dim >= 2)
14006 {
14007 tmp.clear();
14008 tmp.insert(tmp.end(),
14009 v.begin() + n_lines(),
14010 v.begin() + n_lines() + n_quads());
14011 load_user_pointers_quad(tmp);
14012 }
14013
14014 if (dim >= 3)
14015 {
14016 tmp.clear();
14017 tmp.insert(tmp.end(),
14018 v.begin() + n_lines() + n_quads(),
14019 v.begin() + n_lines() + n_quads() + n_hexs());
14020 load_user_pointers_hex(tmp);
14021 }
14022
14023 if (dim >= 4)
14025}
14026
14027
14028
14029template <int dim, int spacedim>
14032 std::vector<void *> &v) const
14033{
14034 v.resize(n_lines(), nullptr);
14035 std::vector<void *>::iterator i = v.begin();
14036 line_iterator line = begin_line(), endl = end_line();
14037 for (; line != endl; ++line, ++i)
14038 *i = line->user_pointer();
14039}
14040
14041
14042
14043template <int dim, int spacedim>
14046 const std::vector<void *> &v)
14047{
14048 Assert(v.size() == n_lines(), ExcGridReadError());
14049
14050 line_iterator line = begin_line(), endl = end_line();
14051 std::vector<void *>::const_iterator i = v.begin();
14052 for (; line != endl; ++line, ++i)
14053 line->set_user_pointer(*i);
14054}
14055
14056
14057
14058template <int dim, int spacedim>
14061 std::vector<void *> &v) const
14062{
14063 v.resize(n_quads(), nullptr);
14064
14065 if (dim >= 2)
14066 {
14067 std::vector<void *>::iterator i = v.begin();
14068 quad_iterator quad = begin_quad(), endq = end_quad();
14069 for (; quad != endq; ++quad, ++i)
14070 *i = get_user_pointer(quad);
14071 }
14072}
14073
14074
14075
14076template <int dim, int spacedim>
14079 const std::vector<void *> &v)
14080{
14081 Assert(v.size() == n_quads(), ExcGridReadError());
14082
14083 if (dim >= 2)
14084 {
14085 quad_iterator quad = begin_quad(), endq = end_quad();
14086 std::vector<void *>::const_iterator i = v.begin();
14087 for (; quad != endq; ++quad, ++i)
14088 set_user_pointer(quad, *i);
14089 }
14090}
14091
14092
14093template <int dim, int spacedim>
14096 std::vector<void *> &v) const
14097{
14098 v.resize(n_hexs(), nullptr);
14099
14100 if (dim >= 3)
14101 {
14102 std::vector<void *>::iterator i = v.begin();
14103 hex_iterator hex = begin_hex(), endh = end_hex();
14104 for (; hex != endh; ++hex, ++i)
14105 *i = get_user_pointer(hex);
14106 }
14107}
14108
14109
14110
14111template <int dim, int spacedim>
14114 const std::vector<void *> &v)
14115{
14116 Assert(v.size() == n_hexs(), ExcGridReadError());
14117
14118 if (dim >= 3)
14119 {
14120 hex_iterator hex = begin_hex(), endh = end_hex();
14121 std::vector<void *>::const_iterator i = v.begin();
14122 for (; hex != endh; ++hex, ++i)
14123 set_user_pointer(hex, *i);
14124 }
14125}
14126
14127#endif
14128
14129/*------------------------ Cell iterator functions ------------------------*/
14130
14131#ifndef DOXYGEN
14132
14133template <int dim, int spacedim>
14136 Triangulation<dim, spacedim>::begin_raw(const unsigned int level) const
14137{
14138 switch (dim)
14139 {
14140 case 1:
14141 return begin_raw_line(level);
14142 case 2:
14143 return begin_raw_quad(level);
14144 case 3:
14145 return begin_raw_hex(level);
14146 default:
14148 return raw_cell_iterator();
14149 }
14150}
14151
14152
14153
14154template <int dim, int spacedim>
14157 Triangulation<dim, spacedim>::begin(const unsigned int level) const
14158{
14159 switch (dim)
14160 {
14161 case 1:
14162 return begin_line(level);
14163 case 2:
14164 return begin_quad(level);
14165 case 3:
14166 return begin_hex(level);
14167 default:
14168 Assert(false, ExcImpossibleInDim(dim));
14169 return cell_iterator();
14170 }
14171}
14172
14173
14174
14175template <int dim, int spacedim>
14178 Triangulation<dim, spacedim>::begin_active(const unsigned int level) const
14179{
14180 switch (dim)
14181 {
14182 case 1:
14183 return begin_active_line(level);
14184 case 2:
14185 return begin_active_quad(level);
14186 case 3:
14187 return begin_active_hex(level);
14188 default:
14190 return active_cell_iterator();
14191 }
14192}
14193
14194
14195
14196template <int dim, int spacedim>
14200{
14201 const unsigned int level = levels.size() - 1;
14202 if (levels[level]->cells.n_objects() == 0)
14203 return end(level);
14204
14205 // find the last raw iterator on
14206 // this level
14207 raw_cell_iterator ri(const_cast<Triangulation<dim, spacedim> *>(this),
14208 level,
14209 levels[level]->cells.n_objects() - 1);
14210
14211 // then move to the last used one
14212 if (ri->used() == true)
14213 return ri;
14214 while ((--ri).state() == IteratorState::valid)
14215 if (ri->used() == true)
14216 return ri;
14217 return ri;
14218}
14219
14220
14221
14222template <int dim, int spacedim>
14226{
14227 // get the last used cell
14228 cell_iterator cell = last();
14229
14230 if (cell != end())
14231 {
14232 // then move to the last active one
14233 if (cell->is_active() == true)
14234 return cell;
14235 while ((--cell).state() == IteratorState::valid)
14236 if (cell->is_active() == true)
14237 return cell;
14238 }
14239 return cell;
14240}
14241
14242
14243
14244template <int dim, int spacedim>
14248 const CellId &cell_id) const
14249{
14250 Assert(
14251 this->contains_cell(cell_id),
14252 ExcMessage(
14253 "CellId is invalid for this triangulation.\n"
14254 "Either the provided CellId does not correspond to a cell in this "
14255 "triangulation object, or, in case you are using a parallel "
14256 "triangulation, may correspond to an artificial cell that is less "
14257 "refined on this processor. In the case of "
14258 "parallel::fullydistributed::Triangulation, the corresponding coarse "
14259 "cell might not be accessible by the current process."));
14260
14261 cell_iterator cell(
14262 this, 0, coarse_cell_id_to_coarse_cell_index(cell_id.get_coarse_cell_id()));
14263
14264 for (const auto &child_index : cell_id.get_child_indices())
14265 cell = cell->child(static_cast<unsigned int>(child_index));
14266
14267 return cell;
14268}
14269
14270
14271
14272template <int dim, int spacedim>
14274bool Triangulation<dim, spacedim>::contains_cell(const CellId &cell_id) const
14275{
14276 const auto coarse_cell_index =
14277 coarse_cell_id_to_coarse_cell_index(cell_id.get_coarse_cell_id());
14278
14279 if (coarse_cell_index == numbers::invalid_unsigned_int)
14280 return false;
14281
14282 cell_iterator cell(this, 0, coarse_cell_index);
14283
14284 for (const auto &child_index : cell_id.get_child_indices())
14285 {
14286 if (cell->has_children() == false)
14287 return false;
14288 cell = cell->child(static_cast<unsigned int>(child_index));
14289 }
14290
14291 return true;
14292}
14293
14294
14295
14296template <int dim, int spacedim>
14300{
14301 return cell_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14302 -1,
14303 -1);
14304}
14305
14306
14307
14308template <int dim, int spacedim>
14311 Triangulation<dim, spacedim>::end_raw(const unsigned int level) const
14312{
14313 // This function may be called on parallel triangulations on levels
14314 // that exist globally, but not on the local portion of the
14315 // triangulation. In that case, just return the end iterator.
14316 //
14317 // We need to use levels.size() instead of n_levels() because the
14318 // latter function uses the cache, but we need to be able to call
14319 // this function at a time when the cache is not currently up to
14320 // date.
14321 if (level >= levels.size())
14322 {
14323 Assert(level < n_global_levels(),
14324 ExcInvalidLevel(level, n_global_levels()));
14325 return end();
14326 }
14327
14328 // Query whether the given level is valid for the local portion of the
14329 // triangulation.
14330 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14331 if (level < levels.size() - 1)
14332 return begin_raw(level + 1);
14333 else
14334 return end();
14335}
14336
14337
14338template <int dim, int spacedim>
14341 Triangulation<dim, spacedim>::end(const unsigned int level) const
14342{
14343 // This function may be called on parallel triangulations on levels
14344 // that exist globally, but not on the local portion of the
14345 // triangulation. In that case, just return the end iterator.
14346 //
14347 // We need to use levels.size() instead of n_levels() because the
14348 // latter function uses the cache, but we need to be able to call
14349 // this function at a time when the cache is not currently up to
14350 // date.
14351 if (level >= levels.size())
14352 {
14353 Assert(level < n_global_levels(),
14354 ExcInvalidLevel(level, n_global_levels()));
14355 return end();
14356 }
14357
14358 // Query whether the given level is valid for the local portion of the
14359 // triangulation.
14360 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14361 if (level < levels.size() - 1)
14362 return begin(level + 1);
14363 else
14364 return end();
14365}
14366
14367
14368template <int dim, int spacedim>
14371 Triangulation<dim, spacedim>::end_active(const unsigned int level) const
14372{
14373 // This function may be called on parallel triangulations on levels
14374 // that exist globally, but not on the local portion of the
14375 // triangulation. In that case, just return the end iterator.
14376 //
14377 // We need to use levels.size() instead of n_levels() because the
14378 // latter function uses the cache, but we need to be able to call
14379 // this function at a time when the cache is not currently up to
14380 // date.
14381 if (level >= levels.size())
14382 {
14383 Assert(level < n_global_levels(),
14384 ExcInvalidLevel(level, n_global_levels()));
14385 return end();
14386 }
14387
14388 // Query whether the given level is valid for the local portion of the
14389 // triangulation.
14390 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14391 return (level >= levels.size() - 1 ? active_cell_iterator(end()) :
14392 begin_active(level + 1));
14393}
14394
14395
14396
14397template <int dim, int spacedim>
14401 const
14402{
14404 begin(), end());
14405}
14406
14407
14408template <int dim, int spacedim>
14411 active_cell_iterator> Triangulation<dim, spacedim>::
14413{
14414 return IteratorRange<
14416 end());
14417}
14418
14419
14420
14421template <int dim, int spacedim>
14424 cell_iterator> Triangulation<dim, spacedim>::
14425 cell_iterators_on_level(const unsigned int level) const
14426{
14428 begin(level), end(level));
14429}
14430
14431
14432
14433template <int dim, int spacedim>
14436 active_cell_iterator> Triangulation<dim, spacedim>::
14437 active_cell_iterators_on_level(const unsigned int level) const
14438{
14439 return IteratorRange<
14441 begin_active(level), end_active(level));
14442}
14443#endif
14444
14445/*------------------------ Face iterator functions ------------------------*/
14446
14447#ifndef DOXYGEN
14448
14449template <int dim, int spacedim>
14453{
14454 switch (dim)
14455 {
14456 case 1:
14457 Assert(false, ExcImpossibleInDim(1));
14458 return raw_face_iterator();
14459 case 2:
14460 return begin_line();
14461 case 3:
14462 return begin_quad();
14463 default:
14465 return face_iterator();
14466 }
14467}
14468
14469
14470
14471template <int dim, int spacedim>
14475{
14476 switch (dim)
14477 {
14478 case 1:
14479 Assert(false, ExcImpossibleInDim(1));
14480 return raw_face_iterator();
14481 case 2:
14482 return begin_active_line();
14483 case 3:
14484 return begin_active_quad();
14485 default:
14487 return active_face_iterator();
14488 }
14489}
14490
14491
14492
14493template <int dim, int spacedim>
14497{
14498 switch (dim)
14499 {
14500 case 1:
14501 Assert(false, ExcImpossibleInDim(1));
14502 return raw_face_iterator();
14503 case 2:
14504 return end_line();
14505 case 3:
14506 return end_quad();
14507 default:
14509 return raw_face_iterator();
14510 }
14511}
14512
14513
14514
14515template <int dim, int spacedim>
14518 active_face_iterator> Triangulation<dim, spacedim>::
14520{
14521 return IteratorRange<
14523 begin_active_face(), end_face());
14524}
14525
14526/*------------------------ Vertex iterator functions ------------------------*/
14527
14528
14529template <int dim, int spacedim>
14533{
14534 vertex_iterator i =
14535 raw_vertex_iterator(const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
14536 if (i.state() != IteratorState::valid)
14537 return i;
14538 // This loop will end because every triangulation has used vertices.
14539 while (i->used() == false)
14540 if ((++i).state() != IteratorState::valid)
14541 return i;
14542 return i;
14543}
14544
14545
14546
14547template <int dim, int spacedim>
14551{
14552 // every vertex is active
14553 return begin_vertex();
14554}
14555
14556
14557
14558template <int dim, int spacedim>
14562{
14563 return raw_vertex_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14564 -1,
14566}
14567
14568#endif
14569
14570
14571/*------------------------ Line iterator functions ------------------------*/
14572
14573#ifndef DOXYGEN
14574
14575template <int dim, int spacedim>
14578 Triangulation<dim, spacedim>::begin_raw_line(const unsigned int level) const
14579{
14580 // This function may be called on parallel triangulations on levels
14581 // that exist globally, but not on the local portion of the
14582 // triangulation. In that case, just return the end iterator.
14583 //
14584 // We need to use levels.size() instead of n_levels() because the
14585 // latter function uses the cache, but we need to be able to call
14586 // this function at a time when the cache is not currently up to
14587 // date.
14588 if (level >= levels.size())
14589 {
14590 Assert(level < n_global_levels(),
14591 ExcInvalidLevel(level, n_global_levels()));
14592 return end_line();
14593 }
14594
14595 switch (dim)
14596 {
14597 case 1:
14598 // Query whether the given level is valid for the local portion of the
14599 // triangulation.
14600 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14601
14602 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
14603 return end_line();
14604
14605 return raw_line_iterator(
14606 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
14607
14608 default:
14609 Assert(level == 0, ExcFacesHaveNoLevel());
14610 return raw_line_iterator(
14611 const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
14612 }
14613}
14614
14615
14616template <int dim, int spacedim>
14619 Triangulation<dim, spacedim>::begin_line(const unsigned int level) const
14620{
14621 // level is checked in begin_raw
14622 raw_line_iterator ri = begin_raw_line(level);
14623 if (ri.state() != IteratorState::valid)
14624 return ri;
14625 while (ri->used() == false)
14626 if ((++ri).state() != IteratorState::valid)
14627 return ri;
14628 return ri;
14629}
14630
14631
14632
14633template <int dim, int spacedim>
14637 const unsigned int level) const
14638{
14639 // level is checked in begin_raw
14640 line_iterator i = begin_line(level);
14641 if (i.state() != IteratorState::valid)
14642 return i;
14643 while (i->has_children())
14644 if ((++i).state() != IteratorState::valid)
14645 return i;
14646 return i;
14647}
14648
14649
14650
14651template <int dim, int spacedim>
14655{
14656 return raw_line_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14657 -1,
14658 -1);
14659}
14660
14661#endif
14662
14663/*------------------------ Quad iterator functions ------------------------*/
14664
14665#ifndef DOXYGEN
14666
14667template <int dim, int spacedim>
14670 Triangulation<dim, spacedim>::begin_raw_quad(const unsigned int level) const
14671{
14672 // This function may be called on parallel triangulations on levels
14673 // that exist globally, but not on the local portion of the
14674 // triangulation. In that case, just return the end iterator.
14675 //
14676 // We need to use levels.size() instead of n_levels() because the
14677 // latter function uses the cache, but we need to be able to call
14678 // this function at a time when the cache is not currently up to
14679 // date.
14680 if (level >= levels.size())
14681 {
14682 Assert(level < n_global_levels(),
14683 ExcInvalidLevel(level, n_global_levels()));
14684 return end_quad();
14685 }
14686
14687 switch (dim)
14688 {
14689 case 1:
14690 Assert(false, ExcImpossibleInDim(1));
14691 return raw_hex_iterator();
14692 case 2:
14693 {
14694 // Query whether the given level is valid for the local portion of the
14695 // triangulation.
14696 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14697
14698 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
14699 return end_quad();
14700
14701 return raw_quad_iterator(
14702 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
14703 }
14704
14705 case 3:
14706 {
14707 Assert(level == 0, ExcFacesHaveNoLevel());
14708
14709 return raw_quad_iterator(
14710 const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
14711 }
14712
14713
14714 default:
14716 return raw_hex_iterator();
14717 }
14718}
14719
14720
14721
14722template <int dim, int spacedim>
14725 Triangulation<dim, spacedim>::begin_quad(const unsigned int level) const
14726{
14727 // level is checked in begin_raw
14728 raw_quad_iterator ri = begin_raw_quad(level);
14729 if (ri.state() != IteratorState::valid)
14730 return ri;
14731 while (ri->used() == false)
14732 if ((++ri).state() != IteratorState::valid)
14733 return ri;
14734 return ri;
14735}
14736
14737
14738
14739template <int dim, int spacedim>
14743 const unsigned int level) const
14744{
14745 // level is checked in begin_raw
14746 quad_iterator i = begin_quad(level);
14747 if (i.state() != IteratorState::valid)
14748 return i;
14749 while (i->has_children())
14750 if ((++i).state() != IteratorState::valid)
14751 return i;
14752 return i;
14753}
14754
14755
14756
14757template <int dim, int spacedim>
14761{
14762 return raw_quad_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14763 -1,
14764 -1);
14765}
14766
14767#endif
14768
14769/*------------------------ Hex iterator functions ------------------------*/
14770
14771#ifndef DOXYGEN
14772
14773template <int dim, int spacedim>
14776 Triangulation<dim, spacedim>::begin_raw_hex(const unsigned int level) const
14777{
14778 // This function may be called on parallel triangulations on levels
14779 // that exist globally, but not on the local portion of the
14780 // triangulation. In that case, just return the end iterator.
14781 //
14782 // We need to use levels.size() instead of n_levels() because the
14783 // latter function uses the cache, but we need to be able to call
14784 // this function at a time when the cache is not currently up to
14785 // date.
14786 if (level >= levels.size())
14787 {
14788 Assert(level < n_global_levels(),
14789 ExcInvalidLevel(level, n_global_levels()));
14790 return end_hex();
14791 }
14792
14793 switch (dim)
14794 {
14795 case 1:
14796 case 2:
14797 Assert(false, ExcImpossibleInDim(1));
14798 return raw_hex_iterator();
14799 case 3:
14800 {
14801 // Query whether the given level is valid for the local portion of the
14802 // triangulation.
14803 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14804
14805 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
14806 return end_hex();
14807
14808 return raw_hex_iterator(
14809 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
14810 }
14811
14812 default:
14814 return raw_hex_iterator();
14815 }
14816}
14817
14818
14819
14820template <int dim, int spacedim>
14823 Triangulation<dim, spacedim>::begin_hex(const unsigned int level) const
14824{
14825 // level is checked in begin_raw
14826 raw_hex_iterator ri = begin_raw_hex(level);
14827 if (ri.state() != IteratorState::valid)
14828 return ri;
14829 while (ri->used() == false)
14830 if ((++ri).state() != IteratorState::valid)
14831 return ri;
14832 return ri;
14833}
14834
14835
14836
14837template <int dim, int spacedim>
14841{
14842 // level is checked in begin_raw
14843 hex_iterator i = begin_hex(level);
14844 if (i.state() != IteratorState::valid)
14845 return i;
14846 while (i->has_children())
14847 if ((++i).state() != IteratorState::valid)
14848 return i;
14849 return i;
14850}
14851
14852
14853
14854template <int dim, int spacedim>
14858{
14859 return raw_hex_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14860 -1,
14861 -1);
14862}
14863
14864#endif
14865
14866// -------------------------------- number of cells etc ---------------
14867
14868
14869namespace internal
14870{
14871 namespace TriangulationImplementation
14872 {
14873 inline unsigned int
14875 {
14876 return c.n_lines;
14877 }
14878
14879
14880 inline unsigned int
14883 {
14884 return c.n_active_lines;
14885 }
14886
14887
14888 inline unsigned int
14890 {
14891 return c.n_quads;
14892 }
14893
14894
14895 inline unsigned int
14898 {
14899 return c.n_active_quads;
14900 }
14901
14902
14903 inline unsigned int
14905 {
14906 return c.n_hexes;
14907 }
14908
14909
14910 inline unsigned int
14913 {
14914 return c.n_active_hexes;
14915 }
14916 } // namespace TriangulationImplementation
14917} // namespace internal
14918
14919#ifndef DOXYGEN
14920
14921template <int dim, int spacedim>
14923unsigned int Triangulation<dim, spacedim>::n_cells() const
14924{
14926}
14927
14928
14929template <int dim, int spacedim>
14932{
14934}
14935
14936template <int dim, int spacedim>
14940{
14941 return n_active_cells();
14942}
14943
14944template <int dim, int spacedim>
14948{
14949 return n_cells(0);
14950}
14951
14952template <int dim, int spacedim>
14954unsigned int Triangulation<dim, spacedim>::n_faces() const
14955{
14956 switch (dim)
14957 {
14958 case 1:
14959 return n_used_vertices();
14960 case 2:
14961 return n_lines();
14962 case 3:
14963 return n_quads();
14964 default:
14966 }
14967 return 0;
14968}
14969
14970
14971template <int dim, int spacedim>
14974{
14975 switch (dim)
14976 {
14977 case 1:
14978 return n_vertices();
14979 case 2:
14980 return n_raw_lines();
14981 case 3:
14982 return n_raw_quads();
14983 default:
14985 }
14986 return 0;
14987}
14988
14989
14990template <int dim, int spacedim>
14993{
14994 switch (dim)
14995 {
14996 case 1:
14997 return n_used_vertices();
14998 case 2:
14999 return n_active_lines();
15000 case 3:
15001 return n_active_quads();
15002 default:
15004 }
15005 return 0;
15006}
15007
15008
15009template <int dim, int spacedim>
15012 const unsigned int level) const
15013{
15014 switch (dim)
15015 {
15016 case 1:
15017 return n_raw_lines(level);
15018 case 2:
15019 return n_raw_quads(level);
15020 case 3:
15021 return n_raw_hexs(level);
15022 default:
15024 }
15025 return 0;
15026}
15027
15028
15029
15030template <int dim, int spacedim>
15033 const unsigned int level) const
15034{
15035 switch (dim)
15036 {
15037 case 1:
15038 return n_lines(level);
15039 case 2:
15040 return n_quads(level);
15041 case 3:
15042 return n_hexs(level);
15043 default:
15045 }
15046 return 0;
15047}
15048
15049
15050
15051template <int dim, int spacedim>
15054 const unsigned int level) const
15055{
15056 switch (dim)
15057 {
15058 case 1:
15059 return n_active_lines(level);
15060 case 2:
15061 return n_active_quads(level);
15062 case 3:
15063 return n_active_hexs(level);
15064 default:
15066 }
15067 return 0;
15068}
15069
15070
15071template <int dim, int spacedim>
15074{
15075 if (anisotropic_refinement == false)
15076 {
15077 for (unsigned int lvl = 0; lvl < n_global_levels() - 1; ++lvl)
15078 if (n_active_cells(lvl) != 0)
15079 return true;
15080 }
15081 else
15082 {
15083 for (const auto &cell : active_cell_iterators())
15084 for (const auto &i : cell->face_indices())
15085 if (cell->face(i)->has_children())
15086 return true;
15087 }
15088 return false;
15089}
15090
15091
15092template <int dim, int spacedim>
15094unsigned int Triangulation<dim, spacedim>::n_lines() const
15095{
15096 return number_cache.n_lines;
15097}
15098
15099
15100
15101template <int dim, int spacedim>
15104 const unsigned int level) const
15105{
15106 if (dim == 1)
15107 {
15108 AssertIndexRange(level, n_levels());
15109 return levels[level]->cells.n_objects();
15110 }
15111
15112 Assert(false, ExcFacesHaveNoLevel());
15113 return 0;
15114}
15115
15116
15117template <int dim, int spacedim>
15120{
15121 if (dim == 1)
15122 {
15124 return 0;
15125 }
15126
15127 return faces->lines.n_objects();
15128}
15129
15130
15131template <int dim, int spacedim>
15134 const unsigned int level) const
15135{
15136 AssertIndexRange(level, number_cache.n_lines_level.size());
15137 Assert(dim == 1, ExcFacesHaveNoLevel());
15138 return number_cache.n_lines_level[level];
15139}
15140
15141
15142template <int dim, int spacedim>
15145{
15146 return number_cache.n_active_lines;
15147}
15148
15149
15150template <int dim, int spacedim>
15153 const unsigned int level) const
15154{
15155 AssertIndexRange(level, number_cache.n_lines_level.size());
15156 Assert(dim == 1, ExcFacesHaveNoLevel());
15157
15158 return number_cache.n_active_lines_level[level];
15159}
15160#endif
15161
15162template <>
15163unsigned int
15165{
15166 return 0;
15167}
15168
15169
15170template <>
15171unsigned int
15172Triangulation<1, 1>::n_quads(const unsigned int) const
15173{
15174 return 0;
15175}
15176
15177
15178template <>
15179unsigned int
15180Triangulation<1, 1>::n_raw_quads(const unsigned int) const
15181{
15182 return 0;
15183}
15184
15185
15186template <>
15187unsigned int
15188Triangulation<1, 1>::n_raw_hexs(const unsigned int) const
15189{
15190 return 0;
15191}
15192
15193
15194template <>
15195unsigned int
15197{
15198 return 0;
15199}
15200
15201
15202template <>
15203unsigned int
15205{
15206 return 0;
15207}
15208
15209
15210
15211template <>
15212unsigned int
15214{
15215 return 0;
15216}
15217
15218
15219template <>
15220unsigned int
15221Triangulation<1, 2>::n_quads(const unsigned int) const
15222{
15223 return 0;
15224}
15225
15226
15227template <>
15228unsigned int
15229Triangulation<1, 2>::n_raw_quads(const unsigned int) const
15230{
15231 return 0;
15232}
15233
15234
15235template <>
15236unsigned int
15237Triangulation<1, 2>::n_raw_hexs(const unsigned int) const
15238{
15239 return 0;
15240}
15241
15242
15243template <>
15244unsigned int
15246{
15247 return 0;
15248}
15249
15250
15251template <>
15252unsigned int
15254{
15255 return 0;
15256}
15257
15258
15259template <>
15260unsigned int
15262{
15263 return 0;
15264}
15265
15266
15267template <>
15268unsigned int
15269Triangulation<1, 3>::n_quads(const unsigned int) const
15270{
15271 return 0;
15272}
15273
15274
15275template <>
15276unsigned int
15277Triangulation<1, 3>::n_raw_quads(const unsigned int) const
15278{
15279 return 0;
15280}
15281
15282
15283template <>
15284unsigned int
15285Triangulation<1, 3>::n_raw_hexs(const unsigned int) const
15286{
15287 return 0;
15288}
15289
15290
15291template <>
15292unsigned int
15294{
15295 return 0;
15296}
15297
15298
15299template <>
15300unsigned int
15302{
15303 return 0;
15304}
15305
15306#ifndef DOXYGEN
15307
15308template <int dim, int spacedim>
15310unsigned int Triangulation<dim, spacedim>::n_quads() const
15311{
15312 return number_cache.n_quads;
15313}
15314
15315
15316template <int dim, int spacedim>
15319 const unsigned int level) const
15320{
15321 Assert(dim == 2, ExcFacesHaveNoLevel());
15322 AssertIndexRange(level, number_cache.n_quads_level.size());
15323 return number_cache.n_quads_level[level];
15324}
15325
15326#endif
15327
15328template <>
15329unsigned int
15331{
15332 AssertIndexRange(level, n_levels());
15333 return levels[level]->cells.n_objects();
15334}
15335
15336
15337
15338template <>
15339unsigned int
15341{
15342 AssertIndexRange(level, n_levels());
15343 return levels[level]->cells.n_objects();
15344}
15345
15346
15347template <>
15348unsigned int
15349Triangulation<3, 3>::n_raw_quads(const unsigned int) const
15350{
15351 Assert(false, ExcFacesHaveNoLevel());
15352 return 0;
15353}
15354
15355#ifndef DOXYGEN
15356
15357template <int dim, int spacedim>
15360{
15362 return 0;
15363}
15364
15365#endif
15366
15367template <>
15368unsigned int
15370{
15371 return faces->quads.n_objects();
15372}
15373
15374#ifndef DOXYGEN
15375
15376template <int dim, int spacedim>
15379{
15380 return number_cache.n_active_quads;
15381}
15382
15383
15384template <int dim, int spacedim>
15387 const unsigned int level) const
15388{
15389 AssertIndexRange(level, number_cache.n_quads_level.size());
15390 Assert(dim == 2, ExcFacesHaveNoLevel());
15391
15392 return number_cache.n_active_quads_level[level];
15393}
15394
15395
15396template <int dim, int spacedim>
15398unsigned int Triangulation<dim, spacedim>::n_hexs() const
15399{
15400 return 0;
15401}
15402
15403
15404
15405template <int dim, int spacedim>
15407unsigned int Triangulation<dim, spacedim>::n_hexs(const unsigned int) const
15408{
15409 return 0;
15410}
15411
15412
15413
15414template <int dim, int spacedim>
15416unsigned int Triangulation<dim, spacedim>::n_raw_hexs(const unsigned int) const
15417{
15418 return 0;
15419}
15420
15421
15422template <int dim, int spacedim>
15425{
15426 return 0;
15427}
15428
15429
15430
15431template <int dim, int spacedim>
15434 const unsigned int) const
15435{
15436 return 0;
15437}
15438
15439#endif
15440
15441template <>
15442unsigned int
15444{
15445 return number_cache.n_hexes;
15446}
15447
15448
15449
15450template <>
15451unsigned int
15452Triangulation<3, 3>::n_hexs(const unsigned int level) const
15453{
15454 AssertIndexRange(level, number_cache.n_hexes_level.size());
15455
15456 return number_cache.n_hexes_level[level];
15457}
15458
15459
15460
15461template <>
15462unsigned int
15464{
15465 AssertIndexRange(level, n_levels());
15466 return levels[level]->cells.n_objects();
15467}
15468
15469
15470template <>
15471unsigned int
15473{
15474 return number_cache.n_active_hexes;
15475}
15476
15477
15478
15479template <>
15480unsigned int
15482{
15483 AssertIndexRange(level, number_cache.n_hexes_level.size());
15484
15485 return number_cache.n_active_hexes_level[level];
15486}
15487
15488#ifndef DOXYGEN
15489
15490template <int dim, int spacedim>
15493{
15494 return std::count(vertices_used.begin(), vertices_used.end(), true);
15495}
15496
15497
15498
15499template <int dim, int spacedim>
15501const std::vector<bool> &Triangulation<dim, spacedim>::get_used_vertices() const
15502{
15503 return vertices_used;
15504}
15505
15506#endif
15507
15508template <>
15509unsigned int
15511{
15512 return 2;
15513}
15514
15515
15516
15517template <>
15518unsigned int
15520{
15521 return 2;
15522}
15523
15524
15525template <>
15526unsigned int
15528{
15529 return 2;
15530}
15531
15532#ifndef DOXYGEN
15533
15534template <int dim, int spacedim>
15537{
15538 cell_iterator cell = begin(0),
15539 endc = (n_levels() > 1 ? begin(1) : cell_iterator(end()));
15540 // store the largest index of the
15541 // vertices used on level 0
15542 unsigned int max_vertex_index = 0;
15543 for (; cell != endc; ++cell)
15544 for (const unsigned int vertex : GeometryInfo<dim>::vertex_indices())
15545 if (cell->vertex_index(vertex) > max_vertex_index)
15546 max_vertex_index = cell->vertex_index(vertex);
15547
15548 // store the number of times a cell
15549 // touches a vertex. An unsigned
15550 // int should suffice, even for
15551 // larger dimensions
15552 std::vector<unsigned short int> usage_count(max_vertex_index + 1, 0);
15553 // touch a vertex's usage count
15554 // every time we find an adjacent
15555 // element
15556 for (cell = begin(); cell != endc; ++cell)
15557 for (const unsigned int vertex : GeometryInfo<dim>::vertex_indices())
15558 ++usage_count[cell->vertex_index(vertex)];
15559
15561 static_cast<unsigned int>(
15562 *std::max_element(usage_count.begin(), usage_count.end())));
15563}
15564
15565
15566
15567template <int dim, int spacedim>
15571{
15573}
15574
15575
15576
15577template <int dim, int spacedim>
15580{
15581 return *this;
15582}
15583
15584
15585
15586template <int dim, int spacedim>
15590{
15591 return *this;
15592}
15593
15594
15595
15596template <int dim, int spacedim>
15600 &periodicity_vector)
15601{
15602 periodic_face_pairs_level_0.insert(periodic_face_pairs_level_0.end(),
15603 periodicity_vector.begin(),
15604 periodicity_vector.end());
15605
15606 // Now initialize periodic_face_map
15607 update_periodic_face_map();
15608}
15609
15610
15611
15612template <int dim, int spacedim>
15614const typename std::map<
15615 std::pair<typename Triangulation<dim, spacedim>::cell_iterator, unsigned int>,
15616 std::pair<std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
15617 unsigned int>,
15618 unsigned char>>
15620{
15621 return periodic_face_map;
15622}
15623
15624
15625template <int dim, int spacedim>
15628{
15629 // We only update the cell relations here for serial triangulations.
15630 // For other triangulations, this is done at other stages of
15631 // mesh creation and mesh refinement.
15633 this))
15634 return;
15635
15636 this->local_cell_relations.clear();
15637 this->local_cell_relations.reserve(this->n_active_cells());
15638
15639 for (const auto &cell : this->active_cell_iterators())
15640 this->local_cell_relations.emplace_back(
15641 cell, ::CellStatus::cell_will_persist);
15642}
15643
15644
15645
15646template <int dim, int spacedim>
15649{
15651 this))
15652 return;
15653
15654 std::vector<CellId> active_cell_old;
15655
15656 // pack data before triangulation gets updated
15657 if (this->cell_attached_data.n_attached_data_sets > 0)
15658 {
15659 // store old active cells to determine cell status after
15660 // coarsening/refinement
15661 active_cell_old.reserve(this->n_active_cells());
15662
15663 for (const auto &cell : this->active_cell_iterators())
15664 {
15665 const bool children_will_be_coarsened =
15666 (cell->level() > 0) && (cell->coarsen_flag_set());
15667
15668 if (children_will_be_coarsened == false)
15669 active_cell_old.emplace_back(cell->id());
15670 else
15671 {
15672 if (cell->parent()->child(0) == cell)
15673 active_cell_old.emplace_back(cell->parent()->id());
15674 }
15675 }
15676
15677 // update cell relations
15678 this->local_cell_relations.clear();
15679 this->local_cell_relations.reserve(this->n_global_active_cells());
15680
15681 std::vector<
15682 std::pair<unsigned int,
15684 cell_relation_t>>
15685 local_cell_relations_tmp;
15686
15687 for (const auto &cell : this->active_cell_iterators())
15688 {
15689 if (std::find(active_cell_old.begin(),
15690 active_cell_old.end(),
15691 cell->id()) != active_cell_old.end())
15692 {
15693 const unsigned int index =
15694 std::distance(active_cell_old.begin(),
15695 std::find(active_cell_old.begin(),
15696 active_cell_old.end(),
15697 cell->id()));
15698
15699 ::CellStatus status =
15700 cell->refine_flag_set() ?
15703
15704 local_cell_relations_tmp.emplace_back(
15705 index,
15707 cell_relation_t{cell, status});
15708 }
15709 else if (cell->level() > 0 &&
15710 std::find(active_cell_old.begin(),
15711 active_cell_old.end(),
15712 cell->parent()->id()) != active_cell_old.end())
15713 {
15714 const unsigned int index =
15715 std::distance(active_cell_old.begin(),
15716 std::find(active_cell_old.begin(),
15717 active_cell_old.end(),
15718 cell->parent()->id()));
15719
15720 ::CellStatus status;
15721
15722 if (cell->parent()->child_iterator_to_index(cell) == 0)
15724 else
15726
15727 local_cell_relations_tmp.emplace_back(
15728 index,
15730 cell_relation_t{cell->parent(), status});
15731 }
15732 else
15733 {
15735 }
15736 }
15737
15738 std::stable_sort(local_cell_relations_tmp.begin(),
15739 local_cell_relations_tmp.end(),
15740 [](const auto &a, const auto &b) {
15741 return a.first < b.first;
15742 });
15743
15744 for (const auto &tmp : local_cell_relations_tmp)
15745 this->local_cell_relations.emplace_back(tmp.second);
15746
15747 // pack data
15748 this->data_serializer.pack_data(
15749 this->local_cell_relations,
15750 this->cell_attached_data.pack_callbacks_fixed,
15751 this->cell_attached_data.pack_callbacks_variable,
15752 this->get_mpi_communicator());
15753
15754 // dummy copy of data
15755 this->data_serializer.dest_data_fixed =
15756 this->data_serializer.src_data_fixed;
15757 this->data_serializer.dest_data_variable =
15758 this->data_serializer.src_data_variable;
15759 this->data_serializer.dest_sizes_variable =
15760 this->data_serializer.src_sizes_variable;
15761 }
15762}
15763
15764
15765
15766template <int dim, int spacedim>
15769{
15771 this))
15772 return;
15773
15774 // transfer data after triangulation got updated
15775 if (this->cell_attached_data.n_attached_data_sets > 0)
15776 {
15777 std::vector<typename internal::CellAttachedDataSerializer<dim, spacedim>::
15778 cell_relation_t>
15779 temp;
15780
15781 for (const auto &cell : local_cell_relations)
15782 {
15783 if (cell.first->has_children())
15784 {
15787
15788 temp.emplace_back(cell.first->child(0),
15790 }
15791 else
15792 temp.push_back(cell);
15793 }
15794
15795 this->local_cell_relations = temp;
15796 }
15797}
15798
15799
15800
15801template <int dim, int spacedim>
15804{
15805 // Call our version of prepare_coarsening_and_refinement() even if a derived
15806 // class like parallel::distributed::Triangulation overrides it. Their
15807 // function will be called in their execute_coarsening_and_refinement()
15808 // function. Even in a distributed computation our job here is to reconstruct
15809 // the local part of the mesh and as such checking our flags is enough.
15811
15812 // verify a case with which we have had
15813 // some difficulty in the past (see the
15814 // deal.II/coarsening_* tests)
15815 if (smooth_grid & limit_level_difference_at_vertices)
15816 Assert(satisfies_level1_at_vertex_rule(*this) == true, ExcInternalError());
15817
15818 // Inform all listeners about beginning of refinement.
15819 signals.pre_refinement();
15820
15821 this->pack_data_serial();
15822
15823 execute_coarsening();
15824
15825 const DistortedCellList cells_with_distorted_children = execute_refinement();
15826
15827 // We need to update the cell relations in order to be able to
15828 // deserialize data. Later on, update_cell_relations is called to mark all
15829 // active cells with the cell_will_persist status.
15830 this->unpack_data_serial();
15831
15832 reset_cell_vertex_indices_cache();
15833
15834 // verify a case with which we have had
15835 // some difficulty in the past (see the
15836 // deal.II/coarsening_* tests)
15837 if (smooth_grid & limit_level_difference_at_vertices)
15838 Assert(satisfies_level1_at_vertex_rule(*this) == true, ExcInternalError());
15839
15840 // finally build up neighbor connectivity information, and set
15841 // active cell indices
15842 this->policy->update_neighbors(*this);
15843 reset_active_cell_indices();
15844
15845 reset_global_cell_indices(); // TODO: better place?
15846
15847 // Inform all listeners about end of refinement.
15848 signals.post_refinement();
15849
15850 AssertThrow(cells_with_distorted_children.distorted_cells.empty(),
15851 cells_with_distorted_children);
15852
15853 update_periodic_face_map();
15854
15855 if (this->cell_attached_data.n_attached_data_sets == 0)
15856 this->update_cell_relations();
15857
15858# ifdef DEBUG
15859
15860 // In debug mode, we want to check for some consistency of the
15861 // result of this function. Because there are multiple exit
15862 // paths, put this check into a ScopeExit object that is
15863 // executed on each of the exit paths.
15864 //
15865 // Specifically, check on exit of this function that if a quad
15866 // cell has been refined, all of its children have neighbors
15867 // in all directions in which the parent cell has neighbors as
15868 // well. The children's neighbors are either the parent
15869 // neighbor or the parent neighbor's children, or simply one of
15870 // the other children of the current cell. This check is
15871 // useful because if one creates a triangulation with an
15872 // inconsistently ordered set of cells (e.g., because one has
15873 // forgotten to call GridTools::consistently_order_cells()),
15874 // then this relatively simple invariant is violated -- so the
15875 // check here can be used to catch that case, at least
15876 // sometimes.
15877 //
15878 // In 1d, this situation cannot happen. In 3d, we have explicit
15879 // orientation flags to ensure that it is not necessary to re-orient
15880 // cells at the beginning. But in both cases, the invariant should
15881 // still hold as long as the cell is a hypercube.
15882 for (const auto &cell : cell_iterators())
15883 {
15884 if (cell->has_children() && cell->reference_cell().is_hyper_cube())
15885 for (const unsigned int f : cell->face_indices())
15886 if (cell->at_boundary(f) == false)
15887 {
15888 for (const auto &child : cell->child_iterators())
15889 {
15890 Assert(
15891 child->at_boundary(f) == false,
15892 ExcMessage(
15893 "We ended up with a triangulation whose child cells "
15894 "are not connected to their neighbors as expected. "
15895 "When you created the triangulation, did you forget "
15896 "to call GridTools::consistently_order_cells() "
15897 "before calling Triangulation::create_triangulation()?"));
15898 }
15899 }
15900 }
15901# endif
15902}
15903
15904
15905
15906template <int dim, int spacedim>
15909{
15910 unsigned int active_cell_index = 0;
15911 for (raw_cell_iterator cell = begin_raw(); cell != end(); ++cell)
15912 if ((cell->used() == false) || cell->has_children())
15913 cell->set_active_cell_index(numbers::invalid_unsigned_int);
15914 else
15915 {
15916 cell->set_active_cell_index(active_cell_index);
15917 ++active_cell_index;
15918 }
15919
15920 Assert(active_cell_index == n_active_cells(), ExcInternalError());
15921}
15922
15923
15924
15925template <int dim, int spacedim>
15928{
15929 {
15931 for (const auto &cell : active_cell_iterators())
15932 cell->set_global_active_cell_index(cell_index++);
15933 }
15934
15935 for (unsigned int l = 0; l < levels.size(); ++l)
15936 {
15938 for (const auto &cell : cell_iterators_on_level(l))
15939 cell->set_global_level_cell_index(cell_index++);
15940 }
15941}
15942
15943
15944
15945template <int dim, int spacedim>
15948{
15949 for (unsigned int l = 0; l < levels.size(); ++l)
15950 {
15951 constexpr unsigned int max_vertices_per_cell = 1 << dim;
15952 std::vector<unsigned int> &cache = levels[l]->cell_vertex_indices_cache;
15953 cache.clear();
15954 cache.resize(levels[l]->refine_flags.size() * max_vertices_per_cell,
15956 for (const auto &cell : cell_iterators_on_level(l))
15957 {
15958 const unsigned int my_index = cell->index() * max_vertices_per_cell;
15959
15960 // to reduce the cost of this function when passing down into quads,
15961 // then lines, then vertices, we use a more low-level access method
15962 // for hexahedral cells, where we can streamline most of the logic
15963 const ReferenceCell ref_cell = cell->reference_cell();
15964 if (ref_cell == ReferenceCells::Hexahedron)
15965 for (unsigned int face = 4; face < 6; ++face)
15966 {
15967 const auto face_iter = cell->face(face);
15968 const std::array<bool, 2> line_orientations{
15969 {face_iter->line_orientation(0),
15970 face_iter->line_orientation(1)}};
15971 std::array<unsigned int, 4> raw_vertex_indices{
15972 {face_iter->line(0)->vertex_index(1 - line_orientations[0]),
15973 face_iter->line(1)->vertex_index(1 - line_orientations[1]),
15974 face_iter->line(0)->vertex_index(line_orientations[0]),
15975 face_iter->line(1)->vertex_index(line_orientations[1])}};
15976
15977 const unsigned char combined_orientation =
15978 levels[l]->face_orientations.get_combined_orientation(
15979 cell->index() * GeometryInfo<3>::faces_per_cell + face);
15980 std::array<unsigned int, 4> vertex_order{
15981 {ref_cell.standard_to_real_face_vertex(0,
15982 face,
15983 combined_orientation),
15985 face,
15986 combined_orientation),
15988 face,
15989 combined_orientation),
15991 3, face, combined_orientation)}};
15992
15993 const unsigned int index = my_index + 4 * (face - 4);
15994 for (unsigned int i = 0; i < 4; ++i)
15995 cache[index + i] = raw_vertex_indices[vertex_order[i]];
15996 }
15997 else if (ref_cell == ReferenceCells::Quadrilateral)
15998 {
15999 const std::array<bool, 2> line_orientations{
16000 {cell->line_orientation(0), cell->line_orientation(1)}};
16001 std::array<unsigned int, 4> raw_vertex_indices{
16002 {cell->line(0)->vertex_index(1 - line_orientations[0]),
16003 cell->line(1)->vertex_index(1 - line_orientations[1]),
16004 cell->line(0)->vertex_index(line_orientations[0]),
16005 cell->line(1)->vertex_index(line_orientations[1])}};
16006 for (unsigned int i = 0; i < 4; ++i)
16007 cache[my_index + i] = raw_vertex_indices[i];
16008 }
16009 else
16010 for (const unsigned int i : cell->vertex_indices())
16011 cache[my_index + i] = internal::TriaAccessorImplementation::
16012 Implementation::vertex_index(*cell, i);
16013 }
16014 }
16015}
16016
16017
16018
16019template <int dim, int spacedim>
16022{
16023 // first empty the currently stored objects
16024 periodic_face_map.clear();
16025
16026 typename std::vector<
16028 for (it = periodic_face_pairs_level_0.begin();
16029 it != periodic_face_pairs_level_0.end();
16030 ++it)
16031 {
16032 update_periodic_face_map_recursively<dim, spacedim>(it->cell[0],
16033 it->cell[1],
16034 it->face_idx[0],
16035 it->face_idx[1],
16036 it->orientation,
16037 periodic_face_map);
16038
16039 const auto face_reference_cell =
16040 it->cell[0]->reference_cell().face_reference_cell(it->face_idx[0]);
16041 // for the other way, we need to invert the orientation
16042 update_periodic_face_map_recursively<dim, spacedim>(
16043 it->cell[1],
16044 it->cell[0],
16045 it->face_idx[1],
16046 it->face_idx[0],
16047 face_reference_cell.get_inverse_combined_orientation(it->orientation),
16048 periodic_face_map);
16049 }
16050
16051 // check consistency
16052 typename std::map<std::pair<cell_iterator, unsigned int>,
16053 std::pair<std::pair<cell_iterator, unsigned int>,
16054 unsigned char>>::const_iterator it_test;
16055 for (it_test = periodic_face_map.begin(); it_test != periodic_face_map.end();
16056 ++it_test)
16057 {
16059 it_test->first.first;
16061 it_test->second.first.first;
16062 if (cell_1->level() == cell_2->level())
16063 {
16064 // if both cells have the same neighbor, then the same pair
16065 // order swapped has to be in the map
16066 Assert(periodic_face_map[it_test->second.first].first ==
16067 it_test->first,
16069 }
16070 }
16071}
16072
16073
16074
16075template <int dim, int spacedim>
16078{
16079 std::set<ReferenceCell> reference_cells_set;
16080 for (auto cell : active_cell_iterators())
16081 if (cell->is_locally_owned())
16082 reference_cells_set.insert(cell->reference_cell());
16083
16084 this->reference_cells =
16085 std::vector<ReferenceCell>(reference_cells_set.begin(),
16086 reference_cells_set.end());
16087}
16088
16089
16090
16091template <int dim, int spacedim>
16093const std::vector<ReferenceCell>
16095{
16096 return this->reference_cells;
16097}
16098
16099
16100
16101template <int dim, int spacedim>
16104{
16105 Assert(this->reference_cells.size() > 0,
16106 ExcMessage("You can't ask about the kinds of reference "
16107 "cells used by this triangulation if the "
16108 "triangulation doesn't yet have any cells in it."));
16109 return (this->reference_cells.size() == 1 &&
16110 this->reference_cells[0].is_hyper_cube());
16111}
16112
16113
16114
16115template <int dim, int spacedim>
16118{
16119 Assert(this->reference_cells.size() > 0,
16120 ExcMessage("You can't ask about the kinds of reference "
16121 "cells used by this triangulation if the "
16122 "triangulation doesn't yet have any cells in it."));
16123 return (this->reference_cells.size() == 1 &&
16124 this->reference_cells[0].is_simplex());
16125}
16126
16127
16128
16129template <int dim, int spacedim>
16132{
16133 Assert(this->reference_cells.size() > 0,
16134 ExcMessage("You can't ask about the kinds of reference "
16135 "cells used by this triangulation if the "
16136 "triangulation doesn't yet have any cells in it."));
16137 return reference_cells.size() > 1 ||
16138 ((reference_cells[0].is_hyper_cube() == false) &&
16139 (reference_cells[0].is_simplex() == false));
16140}
16141
16142
16143
16144template <int dim, int spacedim>
16147 const std::function<std::vector<char>(const cell_iterator &,
16148 const ::CellStatus)>
16149 &pack_callback,
16150 const bool returns_variable_size_data)
16151{
16152 unsigned int handle = numbers::invalid_unsigned_int;
16153
16154 // Add new callback function to the corresponding register.
16155 // Encode handles according to returns_variable_size_data.
16156 if (returns_variable_size_data)
16157 {
16158 handle = 2 * this->cell_attached_data.pack_callbacks_variable.size();
16159 this->cell_attached_data.pack_callbacks_variable.push_back(pack_callback);
16160 }
16161 else
16162 {
16163 handle = 2 * this->cell_attached_data.pack_callbacks_fixed.size() + 1;
16164 this->cell_attached_data.pack_callbacks_fixed.push_back(pack_callback);
16165 }
16166
16167 // Increase overall counter.
16168 ++this->cell_attached_data.n_attached_data_sets;
16169
16170 return handle;
16171}
16172
16173
16174
16175template <int dim, int spacedim>
16178 const unsigned int handle,
16179 const std::function<
16180 void(const cell_iterator &,
16181 const ::CellStatus,
16182 const boost::iterator_range<std::vector<char>::const_iterator> &)>
16183 &unpack_callback)
16184{
16185 // perform unpacking
16186 this->data_serializer.unpack_data(this->local_cell_relations,
16187 handle,
16188 unpack_callback);
16189
16190 // decrease counters
16191 --this->cell_attached_data.n_attached_data_sets;
16192 if (this->cell_attached_data.n_attached_deserialize > 0)
16193 --this->cell_attached_data.n_attached_deserialize;
16194
16195 // important: only remove data if we are not in the deserialization
16196 // process. There, each SolutionTransfer registers and unpacks before
16197 // the next one does this, so n_attached_data_sets is only 1 here. This
16198 // would destroy the saved data before the second SolutionTransfer can
16199 // get it. This created a bug that is documented in
16200 // tests/mpi/p4est_save_03 with more than one SolutionTransfer.
16201
16202 if (this->cell_attached_data.n_attached_data_sets == 0 &&
16203 this->cell_attached_data.n_attached_deserialize == 0)
16204 {
16205 // everybody got their data, time for cleanup!
16206 this->cell_attached_data.pack_callbacks_fixed.clear();
16207 this->cell_attached_data.pack_callbacks_variable.clear();
16208 this->data_serializer.clear();
16209
16210 // reset all cell_status entries after coarsening/refinement
16211 for (auto &cell_rel : this->local_cell_relations)
16212 cell_rel.second = ::CellStatus::cell_will_persist;
16213 }
16214}
16215
16216
16217
16218template <int dim, int spacedim>
16221 const unsigned int global_first_cell,
16222 const unsigned int global_num_cells,
16223 const std::string &file_basename) const
16224{
16225 // cast away constness
16226 auto tria = const_cast<Triangulation<dim, spacedim> *>(this);
16227
16228 // each cell should have been flagged `CellStatus::cell_will_persist`
16229 for (const auto &cell_rel : this->local_cell_relations)
16230 {
16231 (void)cell_rel;
16232 Assert((cell_rel.second == // cell_status
16235 }
16236
16237 if (this->cell_attached_data.n_attached_data_sets > 0)
16238 {
16239 // pack attached data first
16240 tria->data_serializer.pack_data(
16241 tria->local_cell_relations,
16242 tria->cell_attached_data.pack_callbacks_fixed,
16243 tria->cell_attached_data.pack_callbacks_variable,
16244 this->get_mpi_communicator());
16245
16246 // then store buffers in file
16247 tria->data_serializer.save(global_first_cell,
16248 global_num_cells,
16249 file_basename,
16250 this->get_mpi_communicator());
16251
16252 // and release the memory afterwards
16253 tria->data_serializer.clear();
16254 }
16255
16256 // clear all of the callback data, as explained in the documentation of
16257 // register_data_attach()
16258 {
16259 tria->cell_attached_data.n_attached_data_sets = 0;
16260 tria->cell_attached_data.pack_callbacks_fixed.clear();
16261 tria->cell_attached_data.pack_callbacks_variable.clear();
16262 }
16263}
16264
16265
16266template <int dim, int spacedim>
16269 const unsigned int global_first_cell,
16270 const unsigned int global_num_cells,
16271 const unsigned int local_num_cells,
16272 const std::string &file_basename,
16273 const unsigned int n_attached_deserialize_fixed,
16274 const unsigned int n_attached_deserialize_variable)
16275{
16276 // load saved data, if any was stored
16277 if (this->cell_attached_data.n_attached_deserialize > 0)
16278 {
16279 this->data_serializer.load(global_first_cell,
16280 global_num_cells,
16281 local_num_cells,
16282 file_basename,
16283 n_attached_deserialize_fixed,
16284 n_attached_deserialize_variable,
16285 this->get_mpi_communicator());
16286
16287 this->data_serializer.unpack_cell_status(this->local_cell_relations);
16288
16289# ifdef DEBUG
16290 // the CellStatus of all stored cells should always be
16291 // CellStatus::cell_will_persist.
16292 for (const auto &cell_rel : this->local_cell_relations)
16293 {
16294 Assert((cell_rel.second == // cell_status
16297 }
16298# endif
16299 }
16300}
16301
16302
16303template <int dim, int spacedim>
16306{
16307 levels.clear();
16308 faces.reset();
16309
16310 vertices.clear();
16311 vertices_used.clear();
16312
16313 manifolds.clear();
16314
16315 // In 1d, also reset vertex-to-(boundary|manifold) maps to empty maps
16316 if (dim == 1)
16317 {
16318 Assert(vertex_to_boundary_id_map_1d != nullptr, ExcInternalError());
16319 vertex_to_boundary_id_map_1d->clear();
16320
16321 Assert(vertex_to_manifold_id_map_1d != nullptr, ExcInternalError());
16322 vertex_to_manifold_id_map_1d->clear();
16323 }
16324 else
16325 {
16326 // For dim>1, these maps should simply not exist.
16327 Assert(vertex_to_boundary_id_map_1d == nullptr, ExcInternalError());
16328 Assert(vertex_to_manifold_id_map_1d == nullptr, ExcInternalError());
16329 }
16330
16331
16333}
16334
16335
16336
16337template <int dim, int spacedim>
16341{
16342 const DistortedCellList cells_with_distorted_children =
16343 this->policy->execute_refinement(*this, check_for_distorted_cells);
16344
16345
16346
16347 // re-compute number of lines
16349 *this, levels.size(), number_cache);
16350
16351# ifdef DEBUG
16352 for (const auto &level : levels)
16353 monitor_memory(level->cells, dim);
16354
16355 // check whether really all refinement flags are reset (also of
16356 // previously non-active cells which we may not have touched. If the
16357 // refinement flag of a non-active cell is set, something went wrong
16358 // since the cell-accessors should have caught this)
16359 for (const auto &cell : this->cell_iterators())
16360 Assert(!cell->refine_flag_set(), ExcInternalError());
16361# endif
16362
16363 return cells_with_distorted_children;
16364}
16365
16366
16367
16368template <int dim, int spacedim>
16371{
16372 // first find out if there are any cells at all to be coarsened in the
16373 // loop below
16374 const cell_iterator endc = end();
16375 bool do_coarsen = false;
16376 if (levels.size() >= 2)
16377 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
16378 if (!cell->is_active() && cell->child(0)->coarsen_flag_set())
16379 {
16380 do_coarsen = true;
16381 break;
16382 }
16383
16384 if (!do_coarsen)
16385 return;
16386
16387 // create a vector counting for each line and quads how many cells contain
16388 // the respective object. this is used later to decide which lines can be
16389 // deleted after coarsening a cell.
16390 std::vector<unsigned int> line_cell_count(dim > 1 ? this->n_raw_lines() : 0);
16391 std::vector<unsigned int> quad_cell_count(dim > 2 ? this->n_raw_quads() : 0);
16392 if (dim > 1)
16393 for (const auto &cell : this->cell_iterators())
16394 {
16395 if (dim > 2)
16396 {
16397 const auto line_indices = internal::TriaAccessorImplementation::
16398 Implementation::get_line_indices_of_cell(*cell);
16399 // avoid a compiler warning by fixing the max number of
16400 // loop iterations to 12
16401 const unsigned int n_lines = std::min(cell->n_lines(), 12u);
16402 for (unsigned int l = 0; l < n_lines; ++l)
16403 ++line_cell_count[line_indices[l]];
16404 for (const unsigned int q : cell->face_indices())
16405 ++quad_cell_count[cell->face_index(q)];
16406 }
16407 else
16408 for (unsigned int l = 0; l < cell->n_lines(); ++l)
16409 ++line_cell_count[cell->line(l)->index()];
16410 }
16411
16412 // Since the loop goes over used cells we only need not worry about
16413 // deleting some cells since the ++operator will then just hop over them
16414 // if we should hit one. Do the loop in the reverse way since we may
16415 // only delete some cells if their neighbors have already been deleted
16416 // (if the latter are on a higher level for example). In effect, only
16417 // those cells are deleted of which originally all children were flagged
16418 // and for which all children are on the same refinement level. Note
16419 // that because of the effects of
16420 // @p{fix_coarsen_flags}, of a cell either all or no children must be
16421 // flagged for coarsening, so it is ok to only check the first child
16422 //
16423 // since we delete the *children* of cells, we can ignore cells on the
16424 // highest level, i.e., level must be less than or equal to
16425 // n_levels()-2.
16426 if (levels.size() >= 2)
16427 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
16428 if (!cell->is_active() && cell->child(0)->coarsen_flag_set())
16429 {
16430 for (unsigned int child = 0; child < cell->n_children(); ++child)
16431 {
16432 Assert(cell->child(child)->coarsen_flag_set(),
16434 cell->child(child)->clear_coarsen_flag();
16435 }
16436 // inform all listeners that cell coarsening is going to happen
16437 signals.pre_coarsening_on_cell(cell);
16438 // use a separate function, since this is dimension specific
16439 this->policy->delete_children(*this,
16440 cell,
16441 line_cell_count,
16442 quad_cell_count);
16443 }
16444
16445 // re-compute number of lines and quads
16447 *this, levels.size(), number_cache);
16448}
16449
16450
16451
16452template <int dim, int spacedim>
16455{
16456 // copy a piece of code from prepare_coarsening_and_refinement that
16457 // ensures that the level difference at vertices is limited if so
16458 // desired. we need this code here since at least in 1d we don't
16459 // call the dimension-independent version of
16460 // prepare_coarsening_and_refinement function. in 2d and 3d, having
16461 // this hunk here makes our lives a bit easier as well as it takes
16462 // care of these cases earlier than it would otherwise happen.
16463 //
16464 // the main difference to the code in p_c_and_r is that here we
16465 // absolutely have to make sure that we get things right, i.e. that
16466 // in particular we set flags right if
16467 // limit_level_difference_at_vertices is set. to do so we iterate
16468 // until the flags don't change any more
16469 auto previous_coarsen_flags = internal::extract_raw_coarsen_flags(levels);
16470
16471 bool continue_iterating = true;
16472
16473 do
16474 {
16475 if (smooth_grid & limit_level_difference_at_vertices)
16476 {
16477 Assert(!anisotropic_refinement,
16478 ExcMessage("In case of anisotropic refinement the "
16479 "limit_level_difference_at_vertices flag for "
16480 "mesh smoothing must not be set!"));
16481
16482 // store highest level one of the cells adjacent to a vertex
16483 // belongs to
16484 std::vector<int> vertex_level(vertices.size(), 0);
16485 for (const auto &cell : this->active_cell_iterators())
16486 {
16487 if (cell->refine_flag_set())
16488 for (const unsigned int vertex : cell->vertex_indices())
16489 vertex_level[cell->vertex_index(vertex)] =
16490 std::max(vertex_level[cell->vertex_index(vertex)],
16491 cell->level() + 1);
16492 else if (!cell->coarsen_flag_set())
16493 for (const unsigned int vertex : cell->vertex_indices())
16494 vertex_level[cell->vertex_index(vertex)] =
16495 std::max(vertex_level[cell->vertex_index(vertex)],
16496 cell->level());
16497 else
16498 {
16499 // if coarsen flag is set then tentatively assume
16500 // that the cell will be coarsened. this isn't
16501 // always true (the coarsen flag could be removed
16502 // again) and so we may make an error here. we try
16503 // to correct this by iterating over the entire
16504 // process until we are converged
16505 Assert(cell->coarsen_flag_set(), ExcInternalError());
16506 for (const unsigned int vertex : cell->vertex_indices())
16507 vertex_level[cell->vertex_index(vertex)] =
16508 std::max(vertex_level[cell->vertex_index(vertex)],
16509 cell->level() - 1);
16510 }
16511 }
16512
16513
16514 // loop over all cells in reverse order. do so because we
16515 // can then update the vertex levels on the adjacent
16516 // vertices and maybe already flag additional cells in this
16517 // loop
16518 //
16519 // note that not only may we have to add additional
16520 // refinement flags, but we will also have to remove
16521 // coarsening flags on cells adjacent to vertices that will
16522 // see refinement
16523 active_cell_iterator endc = end();
16524 for (active_cell_iterator cell = last_active(); cell != endc; --cell)
16525 if (cell->refine_flag_set() == false)
16526 {
16527 for (const unsigned int vertex : cell->vertex_indices())
16528 if (vertex_level[cell->vertex_index(vertex)] >=
16529 cell->level() + 1)
16530 {
16531 // remove coarsen flag...
16532 cell->clear_coarsen_flag();
16533
16534 // ...and if necessary also refine the current
16535 // cell, at the same time updating the level
16536 // information about vertices
16537 if (vertex_level[cell->vertex_index(vertex)] >
16538 cell->level() + 1)
16539 {
16540 cell->set_refine_flag();
16541
16542 for (const unsigned int v : cell->vertex_indices())
16543 vertex_level[cell->vertex_index(v)] =
16544 std::max(vertex_level[cell->vertex_index(v)],
16545 cell->level() + 1);
16546 }
16547
16548 // continue and see whether we may, for example,
16549 // go into the inner 'if' above based on a
16550 // different vertex
16551 }
16552 }
16553 }
16554
16555 // loop over all cells and remove the coarsen flags for those cells that
16556 // have sister cells not marked for coarsening, or where some neighbors
16557 // are more refined.
16558
16559 // Coarsen flags of cells with no mother cell, i.e. on the
16560 // coarsest level, are deleted explicitly.
16561 for (const auto &acell : this->active_cell_iterators_on_level(0))
16562 acell->clear_coarsen_flag();
16563
16564 const cell_iterator endc = end();
16565 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
16566 {
16567 // nothing to do if we are already on the finest level
16568 if (cell->is_active())
16569 continue;
16570
16571 const unsigned int n_children = cell->n_children();
16572 unsigned int flagged_children = 0;
16573 for (unsigned int child = 0; child < n_children; ++child)
16574 {
16575 const auto child_cell = cell->child(child);
16576 if (child_cell->is_active() && child_cell->coarsen_flag_set())
16577 {
16578 ++flagged_children;
16579 // clear flag since we don't need it anymore
16580 child_cell->clear_coarsen_flag();
16581 }
16582 }
16583
16584 // flag the children for coarsening again if all children were
16585 // flagged and if the policy allows it
16586 if (flagged_children == n_children &&
16587 this->policy->coarsening_allowed(cell))
16588 for (unsigned int c = 0; c < n_children; ++c)
16589 {
16590 Assert(cell->child(c)->refine_flag_set() == false,
16592
16593 cell->child(c)->set_coarsen_flag();
16594 }
16595 }
16596
16597 // now see if anything has changed in the last iteration of this
16598 // function
16599 auto current_coarsen_flags = internal::extract_raw_coarsen_flags(levels);
16600
16601 continue_iterating = (current_coarsen_flags != previous_coarsen_flags);
16602 previous_coarsen_flags.swap(current_coarsen_flags);
16603 }
16604 while (continue_iterating == true);
16605}
16606
16607#endif
16608
16609// TODO: merge the following 3 functions since they are the same
16610template <>
16611bool
16613{
16614 // save the flags to determine whether something was changed in the
16615 // course of this function
16616 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
16617
16618 // do nothing in 1d, except setting the coarsening flags correctly
16619 fix_coarsen_flags();
16620
16621 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
16622
16623 return (flags_before != flags_after);
16624}
16625
16626
16627
16628template <>
16629bool
16631{
16632 // save the flags to determine whether something was changed in the
16633 // course of this function
16634 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
16635
16636 // do nothing in 1d, except setting the coarsening flags correctly
16637 fix_coarsen_flags();
16638
16639 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
16640
16641 return (flags_before != flags_after);
16642}
16643
16644
16645
16646template <>
16647bool
16649{
16650 // save the flags to determine whether something was changed in the
16651 // course of this function
16652 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
16653
16654 // do nothing in 1d, except setting the coarsening flags correctly
16655 fix_coarsen_flags();
16656
16657 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
16658
16659 return (flags_before != flags_after);
16660}
16661
16662
16663
16664namespace
16665{
16666 // check if the given @param cell marked for coarsening would
16667 // produce an unrefined island. To break up long chains of these
16668 // cells we recursively check our neighbors in case we change this
16669 // cell. This reduces the number of outer iterations dramatically.
16670 template <int dim, int spacedim>
16671 void
16672 possibly_do_not_produce_unrefined_islands(
16674 {
16675 Assert(cell->has_children(), ExcInternalError());
16676
16677 unsigned int n_neighbors = 0;
16678 // count all neighbors that will be refined along the face of our
16679 // cell after the next step
16680 unsigned int count = 0;
16681 for (const unsigned int n : GeometryInfo<dim>::face_indices())
16682 {
16683 const typename Triangulation<dim, spacedim>::cell_iterator neighbor =
16684 cell->neighbor(n);
16685 if (neighbor.state() == IteratorState::valid)
16686 {
16687 ++n_neighbors;
16688 if (face_will_be_refined_by_neighbor(cell, n))
16689 ++count;
16690 }
16691 }
16692 // clear coarsen flags if either all existing neighbors will be
16693 // refined or all but one will be and the cell is in the interior
16694 // of the domain
16695 if (count == n_neighbors ||
16696 (count >= n_neighbors - 1 &&
16697 n_neighbors == GeometryInfo<dim>::faces_per_cell))
16698 {
16699 for (unsigned int c = 0; c < cell->n_children(); ++c)
16700 cell->child(c)->clear_coarsen_flag();
16701
16702 for (const unsigned int face : GeometryInfo<dim>::face_indices())
16703 if (!cell->at_boundary(face) &&
16704 (!cell->neighbor(face)->is_active()) &&
16705 (cell_will_be_coarsened(cell->neighbor(face))))
16706 possibly_do_not_produce_unrefined_islands<dim, spacedim>(
16707 cell->neighbor(face));
16708 }
16709 }
16710
16711
16712 // see if the current cell needs to be refined to avoid unrefined
16713 // islands.
16714 //
16715 // there are sometimes chains of cells that induce refinement of
16716 // each other. to avoid running the loop in
16717 // prepare_coarsening_and_refinement over and over again for each
16718 // one of them, at least for the isotropic refinement case we seek
16719 // to flag neighboring elements as well as necessary. this takes
16720 // care of (slightly pathological) cases like
16721 // deal.II/mesh_smoothing_03
16722 template <int dim, int spacedim>
16723 void
16724 possibly_refine_unrefined_island(
16726 const bool allow_anisotropic_smoothing)
16727 {
16728 Assert(cell->is_active(), ExcInternalError());
16729
16730#ifdef DEBUG
16731 // If this is not a parallel::distributed::Triangulation, then we really
16732 // should only get here if the cell is marked for refinement:
16734 *>(&cell->get_triangulation()) == nullptr)
16735 Assert(cell->refine_flag_set() == false, ExcInternalError());
16736 else
16737 // But if this is a p::d::Triangulation, then we don't have that
16738 // much control and we can get here because mesh smoothing is
16739 // requested but can not be honored because p4est controls
16740 // what gets refined. In that case, we can at least provide
16741 // a better error message.
16742 Assert(cell->refine_flag_set() == false,
16743 ExcMessage(
16744 "The triangulation is trying to avoid unrefined islands "
16745 "during mesh refinement/coarsening, as you had requested "
16746 " by passing the appropriate 'smoothing flags' to the "
16747 "constructor of the triangulation. However, for objects "
16748 "of type parallel::distributed::Triangulation, control "
16749 "over which cells get refined rests with p4est, not the "
16750 "deal.II triangulation, and consequently it is not "
16751 "always possible to avoid unrefined islands in the mesh. "
16752 "Please remove the constructor argument to the triangulation "
16753 "object that requests mesh smoothing."));
16754#endif
16755
16756 // now we provide two algorithms. the first one is the standard
16757 // one, coming from the time, where only isotropic refinement was
16758 // possible. it simply counts the neighbors that are or will be
16759 // refined and compares to the number of other ones. the second
16760 // one does this check independently for each direction: if all
16761 // neighbors in one direction (normally two, at the boundary only
16762 // one) are refined, the current cell is flagged to be refined in
16763 // an according direction.
16764
16765 if (allow_anisotropic_smoothing == false)
16766 {
16767 // use first algorithm
16768 unsigned int refined_neighbors = 0, unrefined_neighbors = 0;
16769 for (const unsigned int face : GeometryInfo<dim>::face_indices())
16770 if (!cell->at_boundary(face))
16771 {
16772 if (face_will_be_refined_by_neighbor(cell, face))
16773 ++refined_neighbors;
16774 else
16775 ++unrefined_neighbors;
16776 }
16777
16778 if (unrefined_neighbors < refined_neighbors)
16779 {
16780 cell->clear_coarsen_flag();
16781 cell->set_refine_flag();
16782
16783 // ok, so now we have flagged this cell. if we know that
16784 // there were any unrefined neighbors at all, see if any
16785 // of those will have to be refined as well
16786 if (unrefined_neighbors > 0)
16787 for (const unsigned int face : GeometryInfo<dim>::face_indices())
16788 if (!cell->at_boundary(face) &&
16789 (face_will_be_refined_by_neighbor(cell, face) == false) &&
16790 (cell->neighbor(face)->has_children() == false) &&
16791 (cell->neighbor(face)->refine_flag_set() == false))
16792 possibly_refine_unrefined_island<dim, spacedim>(
16793 cell->neighbor(face), allow_anisotropic_smoothing);
16794 }
16795 }
16796 else
16797 {
16798 // variable to store the cell refine case needed to fulfill
16799 // all smoothing requirements
16800 RefinementCase<dim> smoothing_cell_refinement_case =
16802
16803 // use second algorithm, do the check individually for each
16804 // direction
16805 for (unsigned int face_pair = 0;
16806 face_pair < GeometryInfo<dim>::faces_per_cell / 2;
16807 ++face_pair)
16808 {
16809 // variable to store the cell refine case needed to refine
16810 // at the current face pair in the same way as the
16811 // neighbors do...
16812 RefinementCase<dim> directional_cell_refinement_case =
16814
16815 for (unsigned int face_index = 0; face_index < 2; ++face_index)
16816 {
16817 unsigned int face = 2 * face_pair + face_index;
16818 // variable to store the refine case (to come) of the
16819 // face under consideration
16820 RefinementCase<dim - 1> expected_face_ref_case =
16821 RefinementCase<dim - 1>::no_refinement;
16822
16823 if (cell->neighbor(face).state() == IteratorState::valid)
16824 face_will_be_refined_by_neighbor<dim, spacedim>(
16825 cell, face, expected_face_ref_case);
16826 // now extract which refine case would be necessary to
16827 // achieve the same face refinement. set the
16828 // intersection with other requirements for the same
16829 // direction.
16830
16831 // note: using the intersection is not an obvious
16832 // decision, we could also argue that it is more
16833 // natural to use the union. however, intersection is
16834 // the less aggressive tactic and favours a smaller
16835 // number of refined cells over an intensive
16836 // smoothing. this way we try not to lose too much of
16837 // the effort we put in anisotropic refinement
16838 // indicators due to overly aggressive smoothing...
16839 directional_cell_refinement_case =
16840 (directional_cell_refinement_case &
16843 expected_face_ref_case,
16844 face,
16845 cell->face_orientation(face),
16846 cell->face_flip(face),
16847 cell->face_rotation(face)));
16848 } // for both face indices
16849 // if both requirements sum up to something useful, add
16850 // this to the refine case for smoothing. note: if
16851 // directional_cell_refinement_case is isotropic still,
16852 // then something went wrong...
16853 Assert(directional_cell_refinement_case <
16856 smoothing_cell_refinement_case =
16857 smoothing_cell_refinement_case | directional_cell_refinement_case;
16858 } // for all face_pairs
16859 // no we collected contributions from all directions. combine
16860 // the new flags with the existing refine case, but only if
16861 // smoothing is required
16862 if (smoothing_cell_refinement_case)
16863 {
16864 cell->clear_coarsen_flag();
16865 cell->set_refine_flag(cell->refine_flag_set() |
16866 smoothing_cell_refinement_case);
16867 }
16868 }
16869 }
16870} // namespace
16871
16872#ifndef DOXYGEN
16873template <int dim, int spacedim>
16876{
16877 // save the flags to determine whether something was changed in the
16878 // course of this function
16879 const auto coarsen_flags_before = internal::extract_raw_coarsen_flags(levels);
16880 const auto refine_flags_before = internal::extract_raw_refine_flags(levels);
16881
16882 // save the flags at the outset of each loop. we do so in order to
16883 // find out whether something was changed in the present loop, in
16884 // which case we would have to re-run the loop. the other
16885 // possibility to find this out would be to set a flag
16886 // @p{something_changed} to true each time we change something.
16887 // however, sometimes one change in one of the parts of the loop is
16888 // undone by another one, so we might end up in an endless loop. we
16889 // could be tempted to break this loop at an arbitrary number of
16890 // runs, but that would not be a clean solution, since we would
16891 // either have to 1/ break the loop too early, in which case the
16892 // promise that a second call to this function immediately after the
16893 // first one does not change anything, would be broken, or 2/ we do
16894 // as many loops as there are levels. we know that information is
16895 // transported over one level in each run of the loop, so this is
16896 // enough. Unfortunately, each loop is rather expensive, so we chose
16897 // the way presented here
16898 auto coarsen_flags_before_loop = coarsen_flags_before;
16899 auto refine_flags_before_loop = refine_flags_before;
16900
16901 // now for what is done in each loop: we have to fulfill several
16902 // tasks at the same time, namely several mesh smoothing algorithms
16903 // and mesh regularization, by which we mean that the next mesh
16904 // fulfills several requirements such as no double refinement at
16905 // each face or line, etc.
16906 //
16907 // since doing these things at once seems almost impossible (in the
16908 // first year of this library, they were done in two functions, one
16909 // for refinement and one for coarsening, and most things within
16910 // these were done at once, so the code was rather impossible to
16911 // join into this, only, function), we do them one after each
16912 // other. the order in which we do them is such that the important
16913 // tasks, namely regularization, are done last and the least
16914 // important things are done the first. the following order is
16915 // chosen:
16916 //
16917 // 0/ Only if coarsest_level_1 or patch_level_1 is set: clear all
16918 // coarsen flags on level 1 to avoid level 0 cells being created
16919 // by coarsening. As coarsen flags will never be added, this can
16920 // be done once and for all before the actual loop starts.
16921 //
16922 // 1/ do not coarsen a cell if 'most of the neighbors' will be
16923 // refined after the step. This is to prevent occurrence of
16924 // unrefined islands.
16925 //
16926 // 2/ eliminate refined islands in the interior and at the
16927 // boundary. since they don't do much harm besides increasing the
16928 // number of degrees of freedom, doing this has a rather low
16929 // priority.
16930 //
16931 // 3/ limit the level difference of neighboring cells at each
16932 // vertex.
16933 //
16934 // 4/ eliminate unrefined islands. this has higher priority since
16935 // this diminishes the approximation properties not only of the
16936 // unrefined island, but also of the surrounding patch.
16937 //
16938 // 5/ ensure patch level 1. Then the triangulation consists of
16939 // patches, i.e. of cells that are refined once. It follows that
16940 // if at least one of the children of a cell is or will be
16941 // refined than all children need to be refined. This step only
16942 // sets refinement flags and does not set coarsening flags. If
16943 // the patch_level_1 flag is set, then
16944 // eliminate_unrefined_islands, eliminate_refined_inner_islands
16945 // and eliminate_refined_boundary_islands will be fulfilled
16946 // automatically and do not need to be enforced separately.
16947 //
16948 // 6/ take care of the requirement that no double refinement is done
16949 // at each face
16950 //
16951 // 7/ take care that no double refinement is done at each line in 3d
16952 // or higher dimensions.
16953 //
16954 // 8/ make sure that all children of each cell are either flagged
16955 // for coarsening or none of the children is
16956 //
16957 // For some of these steps, it is known that they interact. Namely,
16958 // it is not possible to guarantee that after step 6 another step 5
16959 // would have no effect; the same holds for the opposite order and
16960 // also when taking into account step 7. however, it is important to
16961 // guarantee that step five or six do not undo something that step 5
16962 // did, and step 7 not something of step 6, otherwise the
16963 // requirements will not be satisfied even if the loop
16964 // terminates. this is accomplished by the fact that steps 5 and 6
16965 // only *add* refinement flags and delete coarsening flags
16966 // (therefore, step 6 can't undo something that step 4 already did),
16967 // and step 7 only deletes coarsening flags, never adds some. step 7
16968 // needs also take care that it won't tag cells for refinement for
16969 // which some neighbors are more refined or will be refined.
16970
16971 //------------------------------------
16972 // STEP 0:
16973 // Only if coarsest_level_1 or patch_level_1 is set: clear all
16974 // coarsen flags on level 1 to avoid level 0 cells being created
16975 // by coarsening.
16976 if (((smooth_grid & coarsest_level_1) || (smooth_grid & patch_level_1)) &&
16977 n_levels() >= 2)
16978 {
16979 for (const auto &cell : active_cell_iterators_on_level(1))
16980 cell->clear_coarsen_flag();
16981 }
16982
16983 bool mesh_changed_in_this_loop = false;
16984 do
16985 {
16986 //------------------------------------
16987 // STEP 1:
16988 // do not coarsen a cell if 'most of the neighbors' will be
16989 // refined after the step. This is to prevent the occurrence
16990 // of unrefined islands. If patch_level_1 is set, this will
16991 // be automatically fulfilled.
16992 if (smooth_grid & do_not_produce_unrefined_islands &&
16993 !(smooth_grid & patch_level_1))
16994 {
16995 for (const auto &cell : cell_iterators())
16996 {
16997 // only do something if this
16998 // cell will be coarsened
16999 if (!cell->is_active() && cell_will_be_coarsened(cell))
17000 possibly_do_not_produce_unrefined_islands<dim, spacedim>(cell);
17001 }
17002 }
17003
17004
17005 //------------------------------------
17006 // STEP 2:
17007 // eliminate refined islands in the interior and at the
17008 // boundary. since they don't do much harm besides increasing
17009 // the number of degrees of freedom, doing this has a rather
17010 // low priority. If patch_level_1 is set, this will be
17011 // automatically fulfilled.
17012 //
17013 // there is one corner case to consider: if this is a
17014 // distributed triangulation, there may be refined islands on
17015 // the boundary of which we own only part (e.g. a single cell
17016 // in the corner of a domain). the rest of the island is
17017 // ghost cells and it *looks* like the area around it
17018 // (artificial cells) are coarser but this is only because
17019 // they may actually be equally fine on other
17020 // processors. it's hard to detect this case but we can do
17021 // the following: only set coarsen flags to remove this
17022 // refined island if all cells we want to set flags on are
17023 // locally owned
17024 if (smooth_grid & (eliminate_refined_inner_islands |
17025 eliminate_refined_boundary_islands) &&
17026 !(smooth_grid & patch_level_1))
17027 {
17028 for (const auto &cell : cell_iterators())
17029 if (!cell->is_active() ||
17030 (cell->is_active() && cell->refine_flag_set() &&
17031 cell->is_locally_owned()))
17032 {
17033 // check whether all children are active, i.e. not
17034 // refined themselves. This is a precondition that the
17035 // children may be coarsened away. If the cell is only
17036 // flagged for refinement, then all future children
17037 // will be active
17038 bool all_children_active = true;
17039 if (!cell->is_active())
17040 for (unsigned int c = 0; c < cell->n_children(); ++c)
17041 if (!cell->child(c)->is_active() ||
17042 cell->child(c)->is_ghost() ||
17043 cell->child(c)->is_artificial())
17044 {
17045 all_children_active = false;
17046 break;
17047 }
17048
17049 if (all_children_active)
17050 {
17051 // count number of refined and unrefined neighbors
17052 // of cell. neighbors on lower levels are counted
17053 // as unrefined since they can only get to the
17054 // same level as this cell by the next refinement
17055 // cycle
17056 unsigned int unrefined_neighbors = 0, total_neighbors = 0;
17057
17058 // Keep track if this cell is at a periodic
17059 // boundary or not. TODO: We do not currently run
17060 // the algorithm for inner islands at a periodic
17061 // boundary (remains to be implemented), but we
17062 // also don't want to consider them
17063 // boundary_island cells as this can interfere
17064 // with 2:1 refinement across periodic faces.
17065 // Instead: just ignore those cells for this
17066 // smoothing operation below.
17067 bool at_periodic_boundary = false;
17068
17069 for (const unsigned int n : cell->face_indices())
17070 {
17071 const cell_iterator neighbor = cell->neighbor(n);
17072 if (neighbor.state() == IteratorState::valid)
17073 {
17074 ++total_neighbors;
17075
17076 if (!face_will_be_refined_by_neighbor(cell, n))
17077 ++unrefined_neighbors;
17078 }
17079 else if (cell->has_periodic_neighbor(n))
17080 {
17081 ++total_neighbors;
17082 at_periodic_boundary = true;
17083 }
17084 }
17085
17086 // if all neighbors unrefined: mark this cell for
17087 // coarsening or don't refine if marked for that
17088 //
17089 // also do the distinction between the two
17090 // versions of the eliminate_refined_*_islands
17091 // flag
17092 //
17093 // the last check is whether there are any
17094 // neighbors at all. if not so, then we are (e.g.)
17095 // on the coarsest grid with one cell, for which,
17096 // of course, we do not remove the refine flag.
17097 if ((unrefined_neighbors == total_neighbors) &&
17098 ((!cell->at_boundary() &&
17099 (smooth_grid & eliminate_refined_inner_islands)) ||
17100 (cell->at_boundary() && !at_periodic_boundary &&
17101 (smooth_grid &
17102 eliminate_refined_boundary_islands))) &&
17103 (total_neighbors != 0))
17104 {
17105 if (!cell->is_active())
17106 for (unsigned int c = 0; c < cell->n_children(); ++c)
17107 {
17108 cell->child(c)->clear_refine_flag();
17109 cell->child(c)->set_coarsen_flag();
17110 }
17111 else
17112 cell->clear_refine_flag();
17113 }
17114 }
17115 }
17116 }
17117
17118 //------------------------------------
17119 // STEP 3:
17120 // limit the level difference of neighboring cells at each
17121 // vertex.
17122 //
17123 // in case of anisotropic refinement this does not make
17124 // sense. as soon as one cell is anisotropically refined, an
17125 // Assertion is thrown. therefore we can ignore this problem
17126 // later on
17127 if (smooth_grid & limit_level_difference_at_vertices)
17128 {
17129 Assert(!anisotropic_refinement,
17130 ExcMessage("In case of anisotropic refinement the "
17131 "limit_level_difference_at_vertices flag for "
17132 "mesh smoothing must not be set!"));
17133
17134 // store highest level one of the cells adjacent to a vertex
17135 // belongs to
17136 std::vector<int> vertex_level(vertices.size(), 0);
17137 for (const auto &cell : active_cell_iterators())
17138 {
17139 if (cell->refine_flag_set())
17140 for (const unsigned int vertex : cell->vertex_indices())
17141 vertex_level[cell->vertex_index(vertex)] =
17142 std::max(vertex_level[cell->vertex_index(vertex)],
17143 cell->level() + 1);
17144 else if (!cell->coarsen_flag_set())
17145 for (const unsigned int vertex : cell->vertex_indices())
17146 vertex_level[cell->vertex_index(vertex)] =
17147 std::max(vertex_level[cell->vertex_index(vertex)],
17148 cell->level());
17149 else
17150 {
17151 // if coarsen flag is set then tentatively assume
17152 // that the cell will be coarsened. this isn't
17153 // always true (the coarsen flag could be removed
17154 // again) and so we may make an error here
17155 Assert(cell->coarsen_flag_set(), ExcInternalError());
17156 for (const unsigned int vertex : cell->vertex_indices())
17157 vertex_level[cell->vertex_index(vertex)] =
17158 std::max(vertex_level[cell->vertex_index(vertex)],
17159 cell->level() - 1);
17160 }
17161 }
17162
17163
17164 // loop over all cells in reverse order. do so because we
17165 // can then update the vertex levels on the adjacent
17166 // vertices and maybe already flag additional cells in this
17167 // loop
17168 //
17169 // note that not only may we have to add additional
17170 // refinement flags, but we will also have to remove
17171 // coarsening flags on cells adjacent to vertices that will
17172 // see refinement
17173 for (active_cell_iterator cell = last_active(); cell != end(); --cell)
17174 if (cell->refine_flag_set() == false)
17175 {
17176 for (const unsigned int vertex : cell->vertex_indices())
17177 if (vertex_level[cell->vertex_index(vertex)] >=
17178 cell->level() + 1)
17179 {
17180 // remove coarsen flag...
17181 cell->clear_coarsen_flag();
17182
17183 // ...and if necessary also refine the current
17184 // cell, at the same time updating the level
17185 // information about vertices
17186 if (vertex_level[cell->vertex_index(vertex)] >
17187 cell->level() + 1)
17188 {
17189 cell->set_refine_flag();
17190
17191 for (const unsigned int v : cell->vertex_indices())
17192 vertex_level[cell->vertex_index(v)] =
17193 std::max(vertex_level[cell->vertex_index(v)],
17194 cell->level() + 1);
17195 }
17196
17197 // continue and see whether we may, for example,
17198 // go into the inner'if'
17199 // above based on a
17200 // different vertex
17201 }
17202 }
17203 }
17204
17205 //-----------------------------------
17206 // STEP 4:
17207 // eliminate unrefined islands. this has higher priority
17208 // since this diminishes the approximation properties not
17209 // only of the unrefined island, but also of the surrounding
17210 // patch.
17211 //
17212 // do the loop from finest to coarsest cells since we may
17213 // trigger a cascade by marking cells for refinement which
17214 // may trigger more cells further down below
17215 if (smooth_grid & eliminate_unrefined_islands)
17216 {
17217 for (active_cell_iterator cell = last_active(); cell != end(); --cell)
17218 // only do something if cell is not already flagged for
17219 // (isotropic) refinement
17220 if (cell->refine_flag_set() !=
17222 possibly_refine_unrefined_island<dim, spacedim>(
17223 cell, (smooth_grid & allow_anisotropic_smoothing) != 0);
17224 }
17225
17226 //-------------------------------
17227 // STEP 5:
17228 // ensure patch level 1.
17229 //
17230 // Introduce some terminology:
17231 // - a cell that is refined
17232 // once is a patch of
17233 // level 1 simply called patch.
17234 // - a cell that is globally
17235 // refined twice is called
17236 // a patch of level 2.
17237 // - patch level n says that
17238 // the triangulation consists
17239 // of patches of level n.
17240 // This makes sense only
17241 // if the grid is already at
17242 // least n times globally
17243 // refined.
17244 //
17245 // E.g. from patch level 1 follows: if at least one of the
17246 // children of a cell is or will be refined than enforce all
17247 // children to be refined.
17248
17249 // This step 4 only sets refinement flags and does not set
17250 // coarsening flags.
17251 if (smooth_grid & patch_level_1)
17252 {
17253 // An important assumption (A) is that before calling this
17254 // function the grid was already of patch level 1.
17255
17256 // loop over all cells whose children are all active. (By
17257 // assumption (A) either all or none of the children are
17258 // active). If the refine flag of at least one of the
17259 // children is set then set_refine_flag and
17260 // clear_coarsen_flag of all children.
17261 for (const auto &cell : cell_iterators())
17262 if (!cell->is_active())
17263 {
17264 // ensure the invariant. we can then check whether all
17265 // of its children are further refined or not by
17266 // simply looking at the first child
17267 Assert(cell_is_patch_level_1(cell), ExcInternalError());
17268 if (cell->child(0)->has_children() == true)
17269 continue;
17270
17271 // cell is found to be a patch. combine the refine
17272 // cases of all children
17273 RefinementCase<dim> combined_ref_case =
17275 for (unsigned int i = 0; i < cell->n_children(); ++i)
17276 combined_ref_case =
17277 combined_ref_case | cell->child(i)->refine_flag_set();
17278 if (combined_ref_case != RefinementCase<dim>::no_refinement)
17279 for (unsigned int i = 0; i < cell->n_children(); ++i)
17280 {
17281 cell_iterator child = cell->child(i);
17282
17283 child->clear_coarsen_flag();
17284 child->set_refine_flag(combined_ref_case);
17285 }
17286 }
17287
17288 // The code above dealt with the case where we may get a
17289 // non-patch_level_1 mesh from refinement. Now also deal
17290 // with the case where we could get such a mesh by
17291 // coarsening. Coarsen the children (and remove the
17292 // grandchildren) only if all cell->grandchild(i)
17293 // ->coarsen_flag_set() are set.
17294 //
17295 // for a case where this is a bit tricky, take a look at the
17296 // mesh_smoothing_0[12] testcases
17297 for (const auto &cell : cell_iterators())
17298 {
17299 // check if this cell has active grandchildren. note
17300 // that we know that it is patch_level_1, i.e. if one of
17301 // its children is active then so are all, and it isn't
17302 // going to have any grandchildren at all:
17303 if (cell->is_active() || cell->child(0)->is_active())
17304 continue;
17305
17306 // cell is not active, and so are none of its
17307 // children. check the grandchildren. note that the
17308 // children are also patch_level_1, and so we only ever
17309 // need to check their first child
17310 const unsigned int n_children = cell->n_children();
17311 bool has_active_grandchildren = false;
17312
17313 for (unsigned int i = 0; i < n_children; ++i)
17314 if (cell->child(i)->child(0)->is_active())
17315 {
17316 has_active_grandchildren = true;
17317 break;
17318 }
17319
17320 if (has_active_grandchildren == false)
17321 continue;
17322
17323
17324 // ok, there are active grandchildren. see if either all
17325 // or none of them are flagged for coarsening
17326 unsigned int n_grandchildren = 0;
17327
17328 // count all coarsen flags of the grandchildren.
17329 unsigned int n_coarsen_flags = 0;
17330
17331 // cell is not a patch (of level 1) as it has a
17332 // grandchild. Is cell a patch of level 2?? Therefore:
17333 // find out whether all cell->child(i) are patches
17334 for (unsigned int c = 0; c < n_children; ++c)
17335 {
17336 // get at the child. by assumption (A), and the
17337 // check by which we got here, the child is not
17338 // active
17339 cell_iterator child = cell->child(c);
17340
17341 const unsigned int nn_children = child->n_children();
17342 n_grandchildren += nn_children;
17343
17344 // if child is found to be a patch of active cells
17345 // itself, then add up how many of its children are
17346 // supposed to be coarsened
17347 if (child->child(0)->is_active())
17348 for (unsigned int cc = 0; cc < nn_children; ++cc)
17349 if (child->child(cc)->coarsen_flag_set())
17350 ++n_coarsen_flags;
17351 }
17352
17353 // if not all grandchildren are supposed to be coarsened
17354 // (e.g. because some simply don't have the flag set, or
17355 // because they are not active and therefore cannot
17356 // carry the flag), then remove the coarsen flag from
17357 // all of the active grandchildren. note that there may
17358 // be coarsen flags on the grandgrandchildren -- we
17359 // don't clear them here, but we'll get to them in later
17360 // iterations if necessary
17361 //
17362 // there is nothing we have to do if no coarsen flags
17363 // have been set at all
17364 if ((n_coarsen_flags != n_grandchildren) && (n_coarsen_flags > 0))
17365 for (unsigned int c = 0; c < n_children; ++c)
17366 {
17367 const cell_iterator child = cell->child(c);
17368 if (child->child(0)->is_active())
17369 for (unsigned int cc = 0; cc < child->n_children(); ++cc)
17370 child->child(cc)->clear_coarsen_flag();
17371 }
17372 }
17373 }
17374
17375 //--------------------------------
17376 //
17377 // at the boundary we could end up with cells with negative
17378 // volume or at least with a part, that is negative, if the
17379 // cell is refined anisotropically. we have to check, whether
17380 // that can happen
17381 this->policy->prevent_distorted_boundary_cells(*this);
17382
17383 //-------------------------------
17384 // STEP 6:
17385 // take care of the requirement that no
17386 // double refinement is done at each face
17387 //
17388 // in case of anisotropic refinement it is only likely, but
17389 // not sure, that the cells, which are more refined along a
17390 // certain face common to two cells are on a higher
17391 // level. therefore we cannot be sure, that the requirement
17392 // of no double refinement is fulfilled after a single pass
17393 // of the following actions. We could just wait for the next
17394 // global loop. when this function terminates, the
17395 // requirement will be fulfilled. However, it might be faster
17396 // to insert an inner loop here.
17397 bool changed = true;
17398 while (changed)
17399 {
17400 changed = false;
17401 active_cell_iterator cell = last_active(), endc = end();
17402
17403 for (; cell != endc; --cell)
17404 if (cell->refine_flag_set())
17405 {
17406 // loop over neighbors of cell
17407 for (const auto i : cell->face_indices())
17408 {
17409 // only do something if the face is not at the
17410 // boundary and if the face will be refined with
17411 // the RefineCase currently flagged for
17412 const bool has_periodic_neighbor =
17413 cell->has_periodic_neighbor(i);
17414 const bool has_neighbor_or_periodic_neighbor =
17415 !cell->at_boundary(i) || has_periodic_neighbor;
17416 if (has_neighbor_or_periodic_neighbor &&
17418 cell->refine_flag_set(), i) !=
17420 {
17421 // 1) if the neighbor has children: nothing to
17422 // worry about. 2) if the neighbor is active
17423 // and a coarser one, ensure, that its
17424 // refine_flag is set 3) if the neighbor is
17425 // active and as refined along the face as our
17426 // current cell, make sure, that no
17427 // coarsen_flag is set. if we remove the
17428 // coarsen flag of our neighbor,
17429 // fix_coarsen_flags() makes sure, that the
17430 // mother cell will not be coarsened
17431 if (cell->neighbor_or_periodic_neighbor(i)->is_active())
17432 {
17433 if ((!has_periodic_neighbor &&
17434 cell->neighbor_is_coarser(i)) ||
17435 (has_periodic_neighbor &&
17436 cell->periodic_neighbor_is_coarser(i)))
17437 {
17438 if (cell->neighbor_or_periodic_neighbor(i)
17439 ->coarsen_flag_set())
17440 cell->neighbor_or_periodic_neighbor(i)
17441 ->clear_coarsen_flag();
17442 // we'll set the refine flag for this
17443 // neighbor below. we note, that we
17444 // have changed something by setting
17445 // the changed flag to true. We do not
17446 // need to do so, if we just removed
17447 // the coarsen flag, as the changed
17448 // flag only indicates the need to
17449 // re-run the inner loop. however, we
17450 // only loop over cells flagged for
17451 // refinement here, so nothing to
17452 // worry about if we remove coarsen
17453 // flags
17454
17455 if (dim == 2)
17456 {
17457 if (smooth_grid &
17458 allow_anisotropic_smoothing)
17459 changed =
17460 has_periodic_neighbor ?
17461 cell->periodic_neighbor(i)
17462 ->flag_for_face_refinement(
17463 cell
17464 ->periodic_neighbor_of_coarser_periodic_neighbor(
17465 i)
17466 .first,
17468 cell->neighbor(i)
17469 ->flag_for_face_refinement(
17470 cell
17471 ->neighbor_of_coarser_neighbor(
17472 i)
17473 .first,
17475 else
17476 {
17477 if (!cell
17478 ->neighbor_or_periodic_neighbor(
17479 i)
17480 ->refine_flag_set())
17481 changed = true;
17482 cell->neighbor_or_periodic_neighbor(i)
17483 ->set_refine_flag();
17484 }
17485 }
17486 else // i.e. if (dim==3)
17487 {
17488 // ugly situations might arise here,
17489 // consider the following situation, which
17490 // shows neighboring cells at the common
17491 // face, where the upper right element is
17492 // coarser at the given face. Now the upper
17493 // child element of the lower left wants to
17494 // refine according to cut_z, such that
17495 // there is a 'horizontal' refinement of the
17496 // face marked with #####
17497 //
17498 // / /
17499 // / /
17500 // *---------------*
17501 // | |
17502 // | |
17503 // | |
17504 // | |
17505 // | |
17506 // | | /
17507 // | |/
17508 // *---------------*
17509 //
17510 //
17511 // *---------------*
17512 // /| /|
17513 // / | ##### / |
17514 // | |
17515 // *---------------*
17516 // /| /|
17517 // / | / |
17518 // | |
17519 // *---------------*
17520 // / /
17521 // / /
17522 //
17523 // this introduces too many hanging nodes
17524 // and the neighboring (coarser) cell (upper
17525 // right) has to be refined. If it is only
17526 // refined according to cut_z, then
17527 // everything is ok:
17528 //
17529 // / /
17530 // / /
17531 // *---------------*
17532 // | |
17533 // | | /
17534 // | |/
17535 // *---------------*
17536 // | |
17537 // | | /
17538 // | |/
17539 // *---------------*
17540 //
17541 //
17542 // *---------------*
17543 // /| /|
17544 // / *---------------*
17545 // /| /|
17546 // *---------------*
17547 // /| /|
17548 // / | / |
17549 // | |
17550 // *---------------*
17551 // / /
17552 // / /
17553 //
17554 // if however the cell wants to refine
17555 // itself in an other way, or if we disallow
17556 // anisotropic smoothing, then simply
17557 // refining the neighbor isotropically is
17558 // not going to work, since this introduces
17559 // a refinement of face ##### with both
17560 // cut_x and cut_y, which is not possible:
17561 //
17562 // / / /
17563 // / / /
17564 // *-------*-------*
17565 // | | |
17566 // | | | /
17567 // | | |/
17568 // *-------*-------*
17569 // | | |
17570 // | | | /
17571 // | | |/
17572 // *-------*-------*
17573 //
17574 //
17575 // *---------------*
17576 // /| /|
17577 // / *---------------*
17578 // /| /|
17579 // *---------------*
17580 // /| /|
17581 // / | / |
17582 // | |
17583 // *---------------*
17584 // / /
17585 // / /
17586 //
17587 // thus, in this case we also need to refine
17588 // our current cell in the new direction:
17589 //
17590 // / / /
17591 // / / /
17592 // *-------*-------*
17593 // | | |
17594 // | | | /
17595 // | | |/
17596 // *-------*-------*
17597 // | | |
17598 // | | | /
17599 // | | |/
17600 // *-------*-------*
17601 //
17602 //
17603 // *-------*-------*
17604 // /| /| /|
17605 // / *-------*-------*
17606 // /| /| /|
17607 // *-------*-------*
17608 // /| / /|
17609 // / | / |
17610 // | |
17611 // *---------------*
17612 // / /
17613 // / /
17614
17615 std::pair<unsigned int, unsigned int>
17616 nb_indices =
17617 has_periodic_neighbor ?
17618 cell
17619 ->periodic_neighbor_of_coarser_periodic_neighbor(
17620 i) :
17621 cell->neighbor_of_coarser_neighbor(i);
17622 unsigned int refined_along_x = 0,
17623 refined_along_y = 0,
17624 to_be_refined_along_x = 0,
17625 to_be_refined_along_y = 0;
17626
17627 const int this_face_index =
17628 cell->face_index(i);
17629
17630 // step 1: detect, along which axis the face
17631 // is currently refined
17632
17633 // first, we need an iterator pointing to
17634 // the parent face. This requires a slight
17635 // detour in case the neighbor is behind a
17636 // periodic face.
17637 const auto parent_face = [&]() {
17638 if (has_periodic_neighbor)
17639 {
17640 const auto neighbor =
17641 cell->periodic_neighbor(i);
17642 const auto parent_face_no =
17643 neighbor
17644 ->periodic_neighbor_of_periodic_neighbor(
17645 nb_indices.first);
17646 auto parent =
17647 neighbor->periodic_neighbor(
17648 nb_indices.first);
17649 return parent->face(parent_face_no);
17650 }
17651 else
17652 return cell->neighbor(i)->face(
17653 nb_indices.first);
17654 }();
17655
17656 if ((this_face_index ==
17657 parent_face->child_index(0)) ||
17658 (this_face_index ==
17659 parent_face->child_index(1)))
17660 {
17661 // this might be an
17662 // anisotropic child. get the
17663 // face refine case of the
17664 // neighbors face and count
17665 // refinements in x and y
17666 // direction.
17667 RefinementCase<dim - 1> frc =
17668 parent_face->refinement_case();
17670 ++refined_along_x;
17672 ++refined_along_y;
17673 }
17674 else
17675 // this has to be an isotropic
17676 // child
17677 {
17678 ++refined_along_x;
17679 ++refined_along_y;
17680 }
17681 // step 2: detect, along which axis the face
17682 // has to be refined given the current
17683 // refine flag
17684 RefinementCase<dim - 1> flagged_frc =
17686 cell->refine_flag_set(),
17687 i,
17688 cell->face_orientation(i),
17689 cell->face_flip(i),
17690 cell->face_rotation(i));
17691 if (flagged_frc &
17693 ++to_be_refined_along_x;
17694 if (flagged_frc &
17696 ++to_be_refined_along_y;
17697
17698 // step 3: set the refine flag of the
17699 // (coarser and active) neighbor.
17700 if ((smooth_grid &
17701 allow_anisotropic_smoothing) ||
17702 cell->neighbor_or_periodic_neighbor(i)
17703 ->refine_flag_set())
17704 {
17705 if (refined_along_x +
17706 to_be_refined_along_x >
17707 1)
17708 changed |=
17709 cell
17710 ->neighbor_or_periodic_neighbor(i)
17711 ->flag_for_face_refinement(
17712 nb_indices.first,
17713 RefinementCase<dim -
17714 1>::cut_axis(0));
17715 if (refined_along_y +
17716 to_be_refined_along_y >
17717 1)
17718 changed |=
17719 cell
17720 ->neighbor_or_periodic_neighbor(i)
17721 ->flag_for_face_refinement(
17722 nb_indices.first,
17723 RefinementCase<dim -
17724 1>::cut_axis(1));
17725 }
17726 else
17727 {
17728 if (cell
17729 ->neighbor_or_periodic_neighbor(i)
17730 ->refine_flag_set() !=
17733 changed = true;
17734 cell->neighbor_or_periodic_neighbor(i)
17735 ->set_refine_flag();
17736 }
17737
17738 // step 4: if necessary (see above) add to
17739 // the refine flag of the current cell
17740 cell_iterator nb =
17741 cell->neighbor_or_periodic_neighbor(i);
17742 RefinementCase<dim - 1> nb_frc =
17744 nb->refine_flag_set(),
17745 nb_indices.first,
17746 nb->face_orientation(nb_indices.first),
17747 nb->face_flip(nb_indices.first),
17748 nb->face_rotation(nb_indices.first));
17749 if ((nb_frc & RefinementCase<dim>::cut_x) &&
17750 !((refined_along_x != 0u) ||
17751 (to_be_refined_along_x != 0u)))
17752 changed |= cell->flag_for_face_refinement(
17753 i,
17755 if ((nb_frc & RefinementCase<dim>::cut_y) &&
17756 !((refined_along_y != 0u) ||
17757 (to_be_refined_along_y != 0u)))
17758 changed |= cell->flag_for_face_refinement(
17759 i,
17761 }
17762 } // if neighbor is coarser
17763 else // -> now the neighbor is not coarser
17764 {
17765 cell->neighbor_or_periodic_neighbor(i)
17766 ->clear_coarsen_flag();
17767 const unsigned int nb_nb =
17768 has_periodic_neighbor ?
17769 cell
17770 ->periodic_neighbor_of_periodic_neighbor(
17771 i) :
17772 cell->neighbor_of_neighbor(i);
17773 const cell_iterator neighbor =
17774 cell->neighbor_or_periodic_neighbor(i);
17775 RefinementCase<dim - 1> face_ref_case =
17777 neighbor->refine_flag_set(),
17778 nb_nb,
17779 neighbor->face_orientation(nb_nb),
17780 neighbor->face_flip(nb_nb),
17781 neighbor->face_rotation(nb_nb));
17782 RefinementCase<dim - 1> needed_face_ref_case =
17784 cell->refine_flag_set(),
17785 i,
17786 cell->face_orientation(i),
17787 cell->face_flip(i),
17788 cell->face_rotation(i));
17789 // if the neighbor wants to refine the
17790 // face with cut_x and we want cut_y
17791 // or vice versa, we have to refine
17792 // isotropically at the given face
17793 if ((face_ref_case ==
17795 needed_face_ref_case ==
17797 (face_ref_case ==
17799 needed_face_ref_case ==
17801 {
17802 changed = cell->flag_for_face_refinement(
17803 i, face_ref_case);
17804 neighbor->flag_for_face_refinement(
17805 nb_nb, needed_face_ref_case);
17806 }
17807 }
17808 }
17809 else //-> the neighbor is not active
17810 {
17811 RefinementCase<dim - 1>
17812 face_ref_case = cell->face(i)->refinement_case(),
17813 needed_face_ref_case =
17815 cell->refine_flag_set(),
17816 i,
17817 cell->face_orientation(i),
17818 cell->face_flip(i),
17819 cell->face_rotation(i));
17820 // if the face is refined with cut_x and
17821 // we want cut_y or vice versa, we have to
17822 // refine isotropically at the given face
17823 if ((face_ref_case == RefinementCase<dim>::cut_x &&
17824 needed_face_ref_case ==
17826 (face_ref_case == RefinementCase<dim>::cut_y &&
17827 needed_face_ref_case ==
17829 changed =
17830 cell->flag_for_face_refinement(i,
17831 face_ref_case);
17832 }
17833 }
17834 }
17835 }
17836 }
17837
17838 //------------------------------------
17839 // STEP 7:
17840 // take care that no double refinement is done at each line in 3d or
17841 // higher dimensions.
17842 this->policy->prepare_refinement_dim_dependent(*this);
17843
17844 //------------------------------------
17845 // STEP 8:
17846 // make sure that all children of each cell are either flagged for
17847 // coarsening or none of the children is
17848 fix_coarsen_flags();
17849
17850 // get the refinement and coarsening flags
17851 auto coarsen_flags_after_loop =
17852 internal::extract_raw_coarsen_flags(levels);
17853 auto refine_flags_after_loop = internal::extract_raw_refine_flags(levels);
17854
17855 // find out whether something was changed in this loop
17856 mesh_changed_in_this_loop =
17857 ((coarsen_flags_before_loop != coarsen_flags_after_loop) ||
17858 (refine_flags_before_loop != refine_flags_after_loop));
17859
17860 // set the flags for the next loop already
17861 coarsen_flags_before_loop.swap(coarsen_flags_after_loop);
17862 refine_flags_before_loop.swap(refine_flags_after_loop);
17863 }
17864 while (mesh_changed_in_this_loop);
17865
17866
17867 // find out whether something was really changed in this
17868 // function. Note that @p{..._flags_before_loop} represents the state
17869 // after the last loop, i.e., the present state
17870 return ((coarsen_flags_before != coarsen_flags_before_loop) ||
17871 (refine_flags_before != refine_flags_before_loop));
17872}
17873
17874
17875
17876template <int dim, int spacedim>
17879 const unsigned int magic_number1,
17880 const std::vector<bool> &v,
17881 const unsigned int magic_number2,
17882 std::ostream &out)
17883{
17884 const unsigned int N = v.size();
17885 unsigned char *flags = new unsigned char[N / 8 + 1];
17886 for (unsigned int i = 0; i < N / 8 + 1; ++i)
17887 flags[i] = 0;
17888
17889 for (unsigned int position = 0; position < N; ++position)
17890 flags[position / 8] |= (v[position] ? (1 << (position % 8)) : 0);
17891
17892 AssertThrow(out.fail() == false, ExcIO());
17893
17894 // format:
17895 // 0. magic number
17896 // 1. number of flags
17897 // 2. the flags
17898 // 3. magic number
17899 out << magic_number1 << ' ' << N << std::endl;
17900 for (unsigned int i = 0; i < N / 8 + 1; ++i)
17901 out << static_cast<unsigned int>(flags[i]) << ' ';
17902
17903 out << std::endl << magic_number2 << std::endl;
17904
17905 delete[] flags;
17906
17907 AssertThrow(out.fail() == false, ExcIO());
17908}
17909
17910
17911template <int dim, int spacedim>
17914 const unsigned int magic_number1,
17915 std::vector<bool> &v,
17916 const unsigned int magic_number2,
17917 std::istream &in)
17918{
17919 AssertThrow(in.fail() == false, ExcIO());
17920
17921 unsigned int magic_number;
17922 in >> magic_number;
17923 AssertThrow(magic_number == magic_number1, ExcGridReadError());
17924
17925 unsigned int N;
17926 in >> N;
17927 v.resize(N);
17928
17929 unsigned char *flags = new unsigned char[N / 8 + 1];
17930 unsigned short int tmp;
17931 for (unsigned int i = 0; i < N / 8 + 1; ++i)
17932 {
17933 in >> tmp;
17934 flags[i] = tmp;
17935 }
17936
17937 for (unsigned int position = 0; position != N; ++position)
17938 v[position] = ((flags[position / 8] & (1 << (position % 8))) != 0);
17939
17940 in >> magic_number;
17941 AssertThrow(magic_number == magic_number2, ExcGridReadError());
17942
17943 delete[] flags;
17944
17945 AssertThrow(in.fail() == false, ExcIO());
17946}
17947
17948
17949
17950template <int dim, int spacedim>
17953{
17954 std::size_t mem = 0;
17955 mem += sizeof(MeshSmoothing);
17956 mem += MemoryConsumption::memory_consumption(reference_cells);
17957 mem += MemoryConsumption::memory_consumption(periodic_face_pairs_level_0);
17959 for (const auto &level : levels)
17962 mem += MemoryConsumption::memory_consumption(vertices_used);
17963 mem += sizeof(manifolds);
17964 mem += sizeof(smooth_grid);
17965 mem += MemoryConsumption::memory_consumption(number_cache);
17966 mem += sizeof(faces);
17967 if (faces)
17969
17970 return mem;
17971}
17972
17973
17974
17975template <int dim, int spacedim>
17978 default;
17979
17980#endif
17981
17982// explicit instantiations
17983#include "tria.inst"
17984
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:949
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:111
numbers::NumberTraits< Number >::real_type distance(const Point< dim, Number > &p) const
unsigned int face_to_cell_vertices(const unsigned int face, const unsigned int vertex, const unsigned char face_orientation) const
static constexpr unsigned char default_combined_face_orientation()
unsigned int standard_to_real_face_vertex(const unsigned int vertex, const unsigned int face, const unsigned char face_orientation) const
static constexpr unsigned char reversed_combined_line_orientation()
unsigned int n_lines() const
unsigned char get_combined_orientation(const ArrayView< const T > &vertices_0, const ArrayView< const T > &vertices_1) 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:4125
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:4501
virtual void clear()
bool anisotropic_refinement
Definition tria.h:4512
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:4570
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
const std::map< std::pair< cell_iterator, unsigned int >, std::pair< std::pair< cell_iterator, unsigned int >, unsigned char > > & get_periodic_face_map() 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:4496
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:4519
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:4547
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:4041
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:4490
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:4126
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:4530
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:4102
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:4127
MeshSmoothing smooth_grid
Definition tria.h:4035
void save_refine_flags(std::ostream &out) const
std::unique_ptr< ::internal::TriangulationImplementation::Policy< dim, spacedim > > policy
Definition tria.h:4093
Triangulation< dim, spacedim > & get_triangulation()
void save_user_flags_quad(std::ostream &out) const
Signals signals
Definition tria.h:2526
virtual ~Triangulation() override
unsigned int n_vertices() const
void load(Archive &ar, const unsigned int version)
void save_user_indices(std::vector< unsigned int > &v) const
void notify_ready_to_unpack(const unsigned int handle, const std::function< void(const cell_iterator &, const ::CellStatus, const boost::iterator_range< std::vector< char >::const_iterator > &)> &unpack_callback)
bool all_reference_cells_are_simplex() const
std::vector< std::unique_ptr<::internal::TriangulationImplementation::TriaLevel > > levels
Definition tria.h:4482
unsigned int n_raw_hexs(const unsigned int level) const
void set_all_refine_flags()
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:393
void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation) override
Definition tria.cc:2558
void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation) override
Definition tria.cc:2565
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:2541
void update_neighbors(Triangulation< dim, spacedim > &tria) override
Definition tria.cc:2535
bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell) override
Definition tria.cc:2572
Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells) override
Definition tria.cc:2551
std::unique_ptr< Policy< dim, spacedim > > clone() override
Definition tria.cc:2580
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
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:498
#define DEAL_II_CXX20_REQUIRES(condition)
Definition config.h:175
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:499
Point< 2 > second
Definition grid_out.cc:4630
Point< 2 > first
Definition grid_out.cc:4629
unsigned int level
Definition grid_out.cc:4632
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)
Definition exceptions.h:534
#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)
Definition exceptions.h:557
#define DeclException1(Exception1, type1, outsequence)
Definition exceptions.h:511
static ::ExceptionBase & ExcInvalidVertexIndex(int arg1, int arg2, int arg3)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define DeclException5( Exception5, type1, type2, type3, type4, type5, outsequence)
Definition exceptions.h:606
#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:1691
typename IteratorSelector::active_quad_iterator active_quad_iterator
Definition tria.h:1682
typename IteratorSelector::active_hex_iterator active_hex_iterator
Definition tria.h:1702
typename IteratorSelector::quad_iterator quad_iterator
Definition tria.h:1667
typename IteratorSelector::line_iterator line_iterator
Definition tria.h:1643
TriaIterator< CellAccessor< dim, spacedim > > cell_iterator
Definition tria.h:1556
typename IteratorSelector::active_line_iterator active_line_iterator
Definition tria.h:1658
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)
#define AssertIsNotUsed(obj)
#define DEAL_II_ASSERT_UNREACHABLE()
#define DEAL_II_NOT_IMPLEMENTED()
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:296
std::vector< index_type > data
Definition mpi.cc:735
std::size_t size
Definition mpi.cc:734
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.
std::enable_if_t< std::is_fundamental_v< T >, std::size_t > memory_consumption(const T &t)
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
Tensor< 2, dim, Number > l(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
constexpr const ReferenceCell Tetrahedron
constexpr const ReferenceCell Quadrilateral
constexpr const ReferenceCell Invalid
constexpr const ReferenceCell Triangle
constexpr const ReferenceCell Hexahedron
constexpr const ReferenceCell Line
VectorType::value_type * end(VectorType &V)
VectorType::value_type * begin(VectorType &V)
int File_write_at_c(MPI_File fh, MPI_Offset offset, const void *buf, MPI_Count count, MPI_Datatype datatype, MPI_Status *status)
int File_read_at_c(MPI_File fh, MPI_Offset offset, void *buf, MPI_Count count, MPI_Datatype datatype, MPI_Status *status)
unsigned int n_mpi_processes(const MPI_Comm mpi_communicator)
Definition mpi.cc:92
T max(const T &t, const MPI_Comm mpi_communicator)
unsigned int this_mpi_process(const MPI_Comm mpi_communicator)
Definition mpi.cc:107
size_t pack(const T &object, std::vector< char > &dest_buffer, const bool allow_compression=true)
Definition utilities.h:1381
constexpr T fixed_power(const T t)
Definition utilities.h:942
unsigned int n_active_cells(const internal::TriangulationImplementation::NumberCache< 1 > &c)
Definition tria.cc:14881
const Manifold< dim, spacedim > & get_default_flat_manifold()
Definition tria.cc:11983
unsigned int n_cells(const internal::TriangulationImplementation::NumberCache< 1 > &c)
Definition tria.cc:14874
void reserve_space(TriaFaces &tria_faces, const unsigned int new_quads_in_pairs, const unsigned int new_quads_single)
Definition tria.cc:1997
void monitor_memory(const TriaLevel &tria_level, const unsigned int true_dimension)
Definition tria.cc:2199
std::tuple< bool, bool, bool > split_face_orientation(const unsigned char combined_face_orientation)
const types::boundary_id internal_face_boundary_id
Definition types.h:312
const types::subdomain_id invalid_subdomain_id
Definition types.h:341
static const unsigned int invalid_unsigned_int
Definition types.h:220
const types::manifold_id flat_manifold_id
Definition types.h:325
const types::global_dof_index invalid_dof_index
Definition types.h:252
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:156
unsigned int boundary_id
Definition types.h:144
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])
bool check_consistency(const unsigned int dim) const
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:1737
boost::signals2::signal< void(const Triangulation< dim, spacedim > &destination_tria)> copy
Definition tria.h:2372
static void update_neighbors(Triangulation< 1, spacedim > &)
Definition tria.cc:11865
static void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &)
Definition tria.cc:11955
static Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:11946
static bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &)
Definition tria.cc:11971
static void update_neighbors(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:11869
static void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:11963
static void delete_children(Triangulation< dim, spacedim > &, typename Triangulation< dim, spacedim >::cell_iterator &, std::vector< unsigned int > &, std::vector< unsigned int > &)
Definition tria.cc:11935
static void reserve_space_(TriaObjects &obj, const unsigned int size)
Definition tria.cc:3628
static void reserve_space_(TriaFaces &faces, const unsigned structdim, const unsigned int size)
Definition tria.cc:3567
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:2786
static void prevent_distorted_boundary_cells(Triangulation< 1, spacedim > &)
Definition tria.cc:11472
static void update_neighbors(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:3014
static void prepare_refinement_dim_dependent(const Triangulation< dim, spacedim > &)
Definition tria.cc:11560
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:3923
static void reserve_space_(TriaLevel &level, const unsigned int spacedim, const unsigned int size, const bool orientation_needed)
Definition tria.cc:3589
static void update_neighbors(Triangulation< 1, spacedim > &)
Definition tria.cc:3008
static Triangulation< 3, spacedim >::DistortedCellList execute_refinement(Triangulation< 3, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:7111
static Triangulation< dim, spacedim >::DistortedCellList execute_refinement_isotropic(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:4918
static void compute_number_cache(const Triangulation< dim, spacedim > &triangulation, const unsigned int level_objects, internal::TriangulationImplementation::NumberCache< dim > &number_cache)
Definition tria.cc:2986
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:4551
static void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:11479
static bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell)
Definition tria.cc:11793
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:2893
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:3681
static void prepare_refinement_dim_dependent(Triangulation< 3, spacedim > &triangulation)
Definition tria.cc:11570
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:3785
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:2698
static Triangulation< 1, spacedim >::DistortedCellList execute_refinement(Triangulation< 1, spacedim > &triangulation, const bool)
Definition tria.cc:5376
static Triangulation< 3, spacedim >::DistortedCellList execute_refinement_isotropic(Triangulation< 3, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:5920
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:3193
static Triangulation< 2, spacedim >::DistortedCellList execute_refinement(Triangulation< 2, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:5611
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:3456
std::vector< std::vector< CellData< dim > > > cell_infos