Reference documentation for deal.II version GIT relicensing-464-g14f7274e4d 2024-04-22 15:40:02+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
25
30#include <deal.II/grid/tria.h>
35
36#include <boost/archive/text_iarchive.hpp>
37#include <boost/archive/text_oarchive.hpp>
38
39#include <algorithm>
40#include <array>
41#include <cmath>
42#include <cstdint>
43#include <fstream>
44#include <functional>
45#include <limits>
46#include <list>
47#include <map>
48#include <memory>
49#include <numeric>
50
51
53
54
55namespace internal
56{
57 namespace TriangulationImplementation
58 {
60 : n_levels(0)
61 , n_lines(0)
62 , n_active_lines(0)
63 // all other fields are
64 // default constructed
65 {}
66
67
68
69 std::size_t
71 {
72 std::size_t mem =
77 MemoryConsumption::memory_consumption(n_active_lines_level);
78
79 if (active_cell_index_partitioner)
80 mem += active_cell_index_partitioner->memory_consumption();
81
82 for (const auto &partitioner : level_cell_index_partitioners)
83 if (partitioner)
84 mem += partitioner->memory_consumption();
85
86 return mem;
87 }
88
89
91 : n_quads(0)
92 , n_active_quads(0)
93 // all other fields are
94 // default constructed
95 {}
96
97
98
99 std::size_t
108
109
110
112 : n_hexes(0)
113 , n_active_hexes(0)
114 // all other fields are
115 // default constructed
116 {}
117
118
119
120 std::size_t
129 } // namespace TriangulationImplementation
130
131
132 template <int dim, int spacedim>
135 : variable_size_data_stored(false)
136 {}
137
138
139 template <int dim, int spacedim>
141 void CellAttachedDataSerializer<dim, spacedim>::pack_data(
142 const std::vector<cell_relation_t> &cell_relations,
143 const std::vector<
144 typename internal::CellAttachedData<dim, spacedim>::pack_callback_t>
145 &pack_callbacks_fixed,
146 const std::vector<
147 typename internal::CellAttachedData<dim, spacedim>::pack_callback_t>
148 &pack_callbacks_variable,
149 const MPI_Comm &mpi_communicator)
150 {
151 Assert(src_data_fixed.empty(),
152 ExcMessage("Previously packed data has not been released yet!"));
153 Assert(src_sizes_variable.empty(), ExcInternalError());
154
155 const unsigned int n_callbacks_fixed = pack_callbacks_fixed.size();
156 const unsigned int n_callbacks_variable = pack_callbacks_variable.size();
157
158 // Store information that we packed variable size data in
159 // a member variable for later.
160 variable_size_data_stored = (n_callbacks_variable > 0);
161
162 // If variable transfer is scheduled, we will store the data size that
163 // each variable size callback function writes in this auxiliary
164 // container. The information will be stored by each cell in this vector
165 // temporarily.
166 std::vector<unsigned int> cell_sizes_variable_cumulative(
167 n_callbacks_variable);
168
169 // Prepare the buffer structure, in which each callback function will
170 // store its data for each active cell.
171 // The outmost shell in this container construct corresponds to the
172 // data packed per cell. The next layer resembles the data that
173 // each callback function packs on the corresponding cell. These
174 // buffers are chains of chars stored in an std::vector<char>.
175 // A visualisation of the data structure:
176 /* clang-format off */
177 // | cell_1 | | cell_2 | ...
178 // || callback_1 || callback_2 |...| || callback_1 || callback_2 |...| ...
179 // |||char|char|...|||char|char|...|...| |||char|char|...|||char|char|...|...| ...
180 /* clang-format on */
181 std::vector<std::vector<std::vector<char>>> packed_fixed_size_data(
182 cell_relations.size());
183 std::vector<std::vector<std::vector<char>>> packed_variable_size_data(
184 variable_size_data_stored ? cell_relations.size() : 0);
185
186 //
187 // --------- Pack data for fixed and variable size transfer ---------
188 //
189 // Iterate over all cells, call all callback functions on each cell,
190 // and store their data in the corresponding buffer scope.
191 {
192 auto cell_rel_it = cell_relations.cbegin();
193 auto data_cell_fixed_it = packed_fixed_size_data.begin();
194 auto data_cell_variable_it = packed_variable_size_data.begin();
195 for (; cell_rel_it != cell_relations.cend(); ++cell_rel_it)
196 {
197 const auto &dealii_cell = cell_rel_it->first;
198 const auto &cell_status = cell_rel_it->second;
199
200 // Assertions about the tree structure.
201 switch (cell_status)
202 {
205 // double check the condition that we will only ever attach
206 // data to active cells when we get here
207 Assert(dealii_cell->is_active(), ExcInternalError());
208 break;
209
211 // double check the condition that we will only ever attach
212 // data to cells with children when we get here. however, we
213 // can only tolerate one level of coarsening at a time, so
214 // check that the children are all active
215 Assert(dealii_cell->is_active() == false, ExcInternalError());
216 for (unsigned int c = 0;
217 c < GeometryInfo<dim>::max_children_per_cell;
218 ++c)
219 Assert(dealii_cell->child(c)->is_active(),
221 break;
222
224 // do nothing on invalid cells
225 break;
226
227 default:
229 break;
230 }
231
232 // Reserve memory corresponding to the number of callback
233 // functions that will be called.
234 // If variable size transfer is scheduled, we need to leave
235 // room for an array that holds information about how many
236 // bytes each of the variable size callback functions will
237 // write.
238 // On cells flagged with CellStatus::cell_invalid, only its CellStatus
239 // will be stored.
240 const unsigned int n_fixed_size_data_sets_on_cell =
241 1 + ((cell_status == CellStatus::cell_invalid) ?
242 0 :
243 ((variable_size_data_stored ? 1 : 0) + n_callbacks_fixed));
244 data_cell_fixed_it->resize(n_fixed_size_data_sets_on_cell);
245
246 // We continue with packing all data on this specific cell.
247 auto data_fixed_it = data_cell_fixed_it->begin();
248
249 // First, we pack the CellStatus information.
250 // to get consistent data sizes on each cell for the fixed size
251 // transfer, we won't allow compression
252 *data_fixed_it =
253 Utilities::pack(cell_status, /*allow_compression=*/false);
254 ++data_fixed_it;
255
256 // Proceed with all registered callback functions.
257 // Skip cells with the CellStatus::cell_invalid flag.
258 if (cell_status != CellStatus::cell_invalid)
259 {
260 // Pack fixed size data.
261 for (auto callback_it = pack_callbacks_fixed.cbegin();
262 callback_it != pack_callbacks_fixed.cend();
263 ++callback_it, ++data_fixed_it)
264 {
265 *data_fixed_it = (*callback_it)(dealii_cell, cell_status);
266 }
267
268 // Pack variable size data.
269 // If we store variable size data, we need to transfer
270 // the sizes of each corresponding callback function
271 // via fixed size transfer as well.
272 if (variable_size_data_stored)
273 {
274 const unsigned int n_variable_size_data_sets_on_cell =
275 ((cell_status == CellStatus::cell_invalid) ?
276 0 :
277 n_callbacks_variable);
278 data_cell_variable_it->resize(
279 n_variable_size_data_sets_on_cell);
280
281 auto callback_it = pack_callbacks_variable.cbegin();
282 auto data_variable_it = data_cell_variable_it->begin();
283 auto sizes_variable_it =
284 cell_sizes_variable_cumulative.begin();
285 for (; callback_it != pack_callbacks_variable.cend();
286 ++callback_it, ++data_variable_it, ++sizes_variable_it)
287 {
288 *data_variable_it =
289 (*callback_it)(dealii_cell, cell_status);
290
291 // Store data sizes for each callback function first.
292 // Make it cumulative below.
293 *sizes_variable_it = data_variable_it->size();
294 }
295
296 // Turn size vector into its cumulative representation.
297 std::partial_sum(cell_sizes_variable_cumulative.begin(),
298 cell_sizes_variable_cumulative.end(),
299 cell_sizes_variable_cumulative.begin());
300
301 // Serialize cumulative variable size vector
302 // value-by-value. This way we can circumvent the overhead
303 // of storing the container object as a whole, since we
304 // know its size by the number of registered callback
305 // functions.
306 data_fixed_it->resize(n_callbacks_variable *
307 sizeof(unsigned int));
308 for (unsigned int i = 0; i < n_callbacks_variable; ++i)
309 std::memcpy(&(data_fixed_it->at(i * sizeof(unsigned int))),
310 &(cell_sizes_variable_cumulative.at(i)),
311 sizeof(unsigned int));
312
313 ++data_fixed_it;
314 }
315
316 // Double check that we packed everything we wanted
317 // in the fixed size buffers.
318 Assert(data_fixed_it == data_cell_fixed_it->end(),
320 }
321
322 ++data_cell_fixed_it;
323
324 // Increment the variable size data iterator
325 // only if we actually pack this kind of data
326 // to avoid getting out of bounds.
327 if (variable_size_data_stored)
328 ++data_cell_variable_it;
329 } // loop over cell_relations
330 }
331
332 //
333 // ----------- Gather data sizes for fixed size transfer ------------
334 //
335 // Generate a vector which stores the sizes of each callback function,
336 // including the packed CellStatus transfer.
337 // Find the very first cell that we wrote to with all callback
338 // functions (i.e. a cell that was not flagged with
339 // CellStatus::cell_invalid) and store the sizes of each buffer.
340 //
341 // To deal with the case that at least one of the processors does not
342 // own any cell at all, we will exchange the information about the data
343 // sizes among them later. The code in between is still well-defined,
344 // since the following loops will be skipped.
345 std::vector<unsigned int> local_sizes_fixed(
346 1 + n_callbacks_fixed + (variable_size_data_stored ? 1 : 0));
347 for (const auto &data_cell : packed_fixed_size_data)
348 {
349 if (data_cell.size() == local_sizes_fixed.size())
350 {
351 auto sizes_fixed_it = local_sizes_fixed.begin();
352 auto data_fixed_it = data_cell.cbegin();
353 for (; data_fixed_it != data_cell.cend();
354 ++data_fixed_it, ++sizes_fixed_it)
355 {
356 *sizes_fixed_it = data_fixed_it->size();
357 }
358
359 break;
360 }
361 }
362
363 // Check if all cells have valid sizes.
364 for (auto data_cell_fixed_it = packed_fixed_size_data.cbegin();
365 data_cell_fixed_it != packed_fixed_size_data.cend();
366 ++data_cell_fixed_it)
367 {
368 Assert((data_cell_fixed_it->size() == 1) ||
369 (data_cell_fixed_it->size() == local_sizes_fixed.size()),
371 }
372
373 // Share information about the packed data sizes
374 // of all callback functions across all processors, in case one
375 // of them does not own any cells at all.
376 std::vector<unsigned int> global_sizes_fixed(local_sizes_fixed.size());
377 Utilities::MPI::max(local_sizes_fixed,
378 mpi_communicator,
379 global_sizes_fixed);
380
381 // Construct cumulative sizes, since this is the only information
382 // we need from now on.
383 sizes_fixed_cumulative.resize(global_sizes_fixed.size());
384 std::partial_sum(global_sizes_fixed.begin(),
385 global_sizes_fixed.end(),
386 sizes_fixed_cumulative.begin());
387
388 //
389 // ---------- Gather data sizes for variable size transfer ----------
390 //
391 if (variable_size_data_stored)
392 {
393 src_sizes_variable.reserve(packed_variable_size_data.size());
394 for (const auto &data_cell : packed_variable_size_data)
395 {
396 int variable_data_size_on_cell = 0;
397
398 for (const auto &data : data_cell)
399 variable_data_size_on_cell += data.size();
401 src_sizes_variable.push_back(variable_data_size_on_cell);
402 }
403 }
404
405 //
406 // ------------------------ Build buffers ---------------------------
407 //
408 const unsigned int expected_size_fixed =
409 cell_relations.size() * sizes_fixed_cumulative.back();
410 const unsigned int expected_size_variable =
411 std::accumulate(src_sizes_variable.begin(),
412 src_sizes_variable.end(),
413 std::vector<int>::size_type(0));
414
415 // Move every piece of packed fixed size data into the consecutive
416 // buffer.
417 src_data_fixed.reserve(expected_size_fixed);
418 for (const auto &data_cell_fixed : packed_fixed_size_data)
419 {
420 // Move every fraction of packed data into the buffer
421 // reserved for this particular cell.
422 for (const auto &data_fixed : data_cell_fixed)
423 std::move(data_fixed.begin(),
424 data_fixed.end(),
425 std::back_inserter(src_data_fixed));
426
427 // If we only packed the CellStatus information
428 // (i.e. encountered a cell flagged CellStatus::cell_invalid),
429 // fill the remaining space with invalid entries.
430 // We can skip this if there is nothing else to pack.
431 if ((data_cell_fixed.size() == 1) &&
432 (sizes_fixed_cumulative.size() > 1))
434 const std::size_t bytes_skipped =
435 sizes_fixed_cumulative.back() - sizes_fixed_cumulative.front();
436
437 src_data_fixed.insert(src_data_fixed.end(),
438 bytes_skipped,
439 static_cast<char>(-1)); // invalid_char
440 }
441 }
442
443 // Move every piece of packed variable size data into the consecutive
444 // buffer.
445 if (variable_size_data_stored)
446 {
447 src_data_variable.reserve(expected_size_variable);
448 for (const auto &data_cell : packed_variable_size_data)
449 {
450 // Move every fraction of packed data into the buffer
451 // reserved for this particular cell.
452 for (const auto &data : data_cell)
453 std::move(data.begin(),
454 data.end(),
455 std::back_inserter(src_data_variable));
456 }
458
459 // Double check that we packed everything correctly.
460 Assert(src_data_fixed.size() == expected_size_fixed, ExcInternalError());
461 Assert(src_data_variable.size() == expected_size_variable,
463 }
464
465
466
467 template <int dim, int spacedim>
469 void CellAttachedDataSerializer<dim, spacedim>::unpack_cell_status(
470 std::vector<
471 typename CellAttachedDataSerializer<dim, spacedim>::cell_relation_t>
472 &cell_relations) const
473 {
474 Assert(sizes_fixed_cumulative.size() > 0,
475 ExcMessage("No data has been packed!"));
476 if (cell_relations.size() > 0)
477 {
478 Assert(dest_data_fixed.size() > 0,
479 ExcMessage("No data has been received!"));
480 }
482 // Size of CellStatus object that will be unpacked on each cell.
483 const unsigned int size = sizes_fixed_cumulative.front();
484
485 // Iterate over all cells and overwrite the CellStatus
486 // information from the transferred data.
487 // Proceed buffer iterator position to next cell after
488 // each iteration.
489 auto cell_rel_it = cell_relations.begin();
490 auto dest_fixed_it = dest_data_fixed.cbegin();
491 for (; cell_rel_it != cell_relations.end();
492 ++cell_rel_it, dest_fixed_it += sizes_fixed_cumulative.back())
493 {
494 cell_rel_it->second = // cell_status
495 Utilities::unpack<CellStatus>(dest_fixed_it,
496 dest_fixed_it + size,
497 /*allow_compression=*/false);
498 }
499 }
500
501
502
503 template <int dim, int spacedim>
505 void CellAttachedDataSerializer<dim, spacedim>::unpack_data(
506 const std::vector<
507 typename CellAttachedDataSerializer<dim, spacedim>::cell_relation_t>
508 &cell_relations,
509 const unsigned int handle,
510 const std::function<
511 void(const cell_iterator &,
512 const CellStatus &,
513 const boost::iterator_range<std::vector<char>::const_iterator> &)>
514 &unpack_callback) const
515 {
516 // We decode the handle returned by register_data_attach() back into
517 // a format we can use. All even handles belong to those callback
518 // functions which write/read variable size data, all odd handles
519 // interact with fixed size buffers.
520 const bool callback_variable_transfer = (handle % 2 == 0);
521 const unsigned int callback_index = handle / 2;
522
523 // Cells will always receive fixed size data (i.e., CellStatus
524 // information), but not necessarily variable size data (e.g., with a
525 // ParticleHandler a cell might not contain any particle at all).
526 // Thus it is sufficient to check if fixed size data has been received.
527 Assert(sizes_fixed_cumulative.size() > 0,
528 ExcMessage("No data has been packed!"));
529 if (cell_relations.size() > 0)
530 {
531 Assert(dest_data_fixed.size() > 0,
532 ExcMessage("No data has been received!"));
533 }
534
535 std::vector<char>::const_iterator dest_data_it;
536 std::vector<char>::const_iterator dest_sizes_cell_it;
537
538 // Depending on whether our callback function unpacks fixed or
539 // variable size data, we have to pursue different approaches
540 // to localize the correct fraction of the buffer from which
541 // we are allowed to read.
542 unsigned int offset = numbers::invalid_unsigned_int;
543 unsigned int size = numbers::invalid_unsigned_int;
544 unsigned int data_increment = numbers::invalid_unsigned_int;
545
546 if (callback_variable_transfer)
547 {
548 // For the variable size data, we need to extract the
549 // data size from the fixed size buffer on each cell.
550 //
551 // We packed this information last, so the last packed
552 // object in the fixed size buffer corresponds to the
553 // variable data sizes.
554 //
555 // The last entry of sizes_fixed_cumulative corresponds
556 // to the size of all fixed size data packed on the cell.
557 // To get the offset for the last packed object, we need
558 // to get the next-to-last entry.
559 const unsigned int offset_variable_data_sizes =
560 sizes_fixed_cumulative[sizes_fixed_cumulative.size() - 2];
561
562 // This iterator points to the data size that the
563 // callback_function packed for each specific cell.
564 // Adjust buffer iterator to the offset of the callback
565 // function so that we only have to advance its position
566 // to the next cell after each iteration.
567 dest_sizes_cell_it = dest_data_fixed.cbegin() +
568 offset_variable_data_sizes +
569 callback_index * sizeof(unsigned int);
570
571 // Let the data iterator point to the correct buffer.
572 dest_data_it = dest_data_variable.cbegin();
573 }
574 else
575 {
576 // For the fixed size data, we can get the information about
577 // the buffer location on each cell directly from the
578 // sizes_fixed_cumulative vector.
579 offset = sizes_fixed_cumulative[callback_index];
580 size = sizes_fixed_cumulative[callback_index + 1] - offset;
581 data_increment = sizes_fixed_cumulative.back();
582
583 // Let the data iterator point to the correct buffer.
584 // Adjust buffer iterator to the offset of the callback
585 // function so that we only have to advance its position
586 // to the next cell after each iteration.
587 if (cell_relations.begin() != cell_relations.end())
588 dest_data_it = dest_data_fixed.cbegin() + offset;
589 }
590
591 // Iterate over all cells and unpack the transferred data.
592 auto cell_rel_it = cell_relations.begin();
593 auto dest_sizes_it = dest_sizes_variable.cbegin();
594 for (; cell_rel_it != cell_relations.end(); ++cell_rel_it)
595 {
596 const auto &dealii_cell = cell_rel_it->first;
597 const auto &cell_status = cell_rel_it->second;
598
599 if (callback_variable_transfer)
600 {
601 // Update the increment according to the whole data size
602 // of the current cell.
603 data_increment = *dest_sizes_it;
604
605 if (cell_status != CellStatus::cell_invalid)
606 {
607 // Extract the corresponding values for offset and size from
608 // the cumulative sizes array stored in the fixed size
609 // buffer.
610 if (callback_index == 0)
611 offset = 0;
612 else
613 std::memcpy(&offset,
614 &(*(dest_sizes_cell_it - sizeof(unsigned int))),
615 sizeof(unsigned int));
616
617 std::memcpy(&size,
618 &(*dest_sizes_cell_it),
619 sizeof(unsigned int));
620
621 size -= offset;
622
623 // Move the data iterator to the corresponding position
624 // of the callback function and adjust the increment
625 // accordingly.
626 dest_data_it += offset;
627 data_increment -= offset;
628 }
629
630 // Advance data size iterators to the next cell, avoid iterating
631 // past the end of dest_sizes_cell_it
632 if (cell_rel_it != cell_relations.end() - 1)
633 dest_sizes_cell_it += sizes_fixed_cumulative.back();
634 ++dest_sizes_it;
635 }
636
637 switch (cell_status)
638 {
641 unpack_callback(dealii_cell,
642 cell_status,
643 boost::make_iterator_range(dest_data_it,
644 dest_data_it + size));
645 break;
646
648 unpack_callback(dealii_cell->parent(),
649 cell_status,
650 boost::make_iterator_range(dest_data_it,
651 dest_data_it + size));
652 break;
653
655 // Skip this cell.
656 break;
657
658 default:
660 break;
661 }
662
663 if (cell_rel_it != cell_relations.end() - 1)
664 dest_data_it += data_increment;
665 }
666 }
667
668
669
670 template <int dim, int spacedim>
672 void CellAttachedDataSerializer<dim, spacedim>::save(
673 const unsigned int global_first_cell,
674 const unsigned int global_num_cells,
675 const std::string &filename,
676 const MPI_Comm &mpi_communicator) const
677 {
678 Assert(sizes_fixed_cumulative.size() > 0,
679 ExcMessage("No data has been packed!"));
680
681#ifdef DEAL_II_WITH_MPI
682 // Large fractions of this function have been copied from
683 // DataOutInterface::write_vtu_in_parallel.
684 // TODO: Write general MPIIO interface.
685
686 const int myrank = Utilities::MPI::this_mpi_process(mpi_communicator);
687 const int mpisize = Utilities::MPI::n_mpi_processes(mpi_communicator);
688
689 if (mpisize > 1)
690 {
691 const unsigned int bytes_per_cell = sizes_fixed_cumulative.back();
692
693 //
694 // ---------- Fixed size data ----------
695 //
696 {
697 const std::string fname_fixed = std::string(filename) + "_fixed.data";
698
699 MPI_Info info;
700 int ierr = MPI_Info_create(&info);
701 AssertThrowMPI(ierr);
702
703 MPI_File fh;
704 ierr = MPI_File_open(mpi_communicator,
705 fname_fixed.c_str(),
706 MPI_MODE_CREATE | MPI_MODE_WRONLY,
707 info,
708 &fh);
709 AssertThrowMPI(ierr);
710
711 ierr = MPI_File_set_size(fh, 0); // delete the file contents
712 AssertThrowMPI(ierr);
713 // this barrier is necessary, because otherwise others might already
714 // write while one core is still setting the size to zero.
715 ierr = MPI_Barrier(mpi_communicator);
716 AssertThrowMPI(ierr);
717 ierr = MPI_Info_free(&info);
718 AssertThrowMPI(ierr);
719 // ------------------
720
721 // Write cumulative sizes to file.
722 // Since each processor owns the same information about the data
723 // sizes, it is sufficient to let only the first processor perform
724 // this task.
725 if (myrank == 0)
726 {
728 fh,
729 0,
730 sizes_fixed_cumulative.data(),
731 sizes_fixed_cumulative.size(),
732 MPI_UNSIGNED,
733 MPI_STATUS_IGNORE);
734 AssertThrowMPI(ierr);
735 }
736
737 // Write packed data to file simultaneously.
738 const MPI_Offset size_header =
739 sizes_fixed_cumulative.size() * sizeof(unsigned int);
740
741 // Make sure we do the following computation in 64bit integers to be
742 // able to handle 4GB+ files:
743 const MPI_Offset my_global_file_position =
744 size_header +
745 static_cast<MPI_Offset>(global_first_cell) * bytes_per_cell;
746
747 ierr =
749 my_global_file_position,
750 src_data_fixed.data(),
751 src_data_fixed.size(),
752 MPI_BYTE,
753 MPI_STATUS_IGNORE);
754 AssertThrowMPI(ierr);
755
756 ierr = MPI_File_close(&fh);
757 AssertThrowMPI(ierr);
758 }
759
760
761
762 //
763 // ---------- Variable size data ----------
764 //
765 if (variable_size_data_stored)
766 {
767 const std::string fname_variable =
768 std::string(filename) + "_variable.data";
769
770 MPI_Info info;
771 int ierr = MPI_Info_create(&info);
772 AssertThrowMPI(ierr);
773
774 MPI_File fh;
775 ierr = MPI_File_open(mpi_communicator,
776 fname_variable.c_str(),
777 MPI_MODE_CREATE | MPI_MODE_WRONLY,
778 info,
779 &fh);
780 AssertThrowMPI(ierr);
781
782 ierr = MPI_File_set_size(fh, 0); // delete the file contents
783 AssertThrowMPI(ierr);
784 // this barrier is necessary, because otherwise others might already
785 // write while one core is still setting the size to zero.
786 ierr = MPI_Barrier(mpi_communicator);
787 AssertThrowMPI(ierr);
788 ierr = MPI_Info_free(&info);
789 AssertThrowMPI(ierr);
790
791 // Write sizes of each cell into file simultaneously.
792 {
793 const MPI_Offset my_global_file_position =
794 static_cast<MPI_Offset>(global_first_cell) *
795 sizeof(unsigned int);
796
797 // It is very unlikely that a single process has more than
798 // 2 billion cells, but we might as well check.
799 AssertThrow(src_sizes_variable.size() <
800 static_cast<std::size_t>(
801 std::numeric_limits<int>::max()),
803
805 fh,
806 my_global_file_position,
807 src_sizes_variable.data(),
808 src_sizes_variable.size(),
809 MPI_INT,
810 MPI_STATUS_IGNORE);
811 AssertThrowMPI(ierr);
812 }
813
814 // Gather size of data in bytes we want to store from this
815 // processor and compute the prefix sum. We do this in 64 bit
816 // to avoid overflow for files larger than 4GB:
817 const std::uint64_t size_on_proc = src_data_variable.size();
818 std::uint64_t prefix_sum = 0;
819 ierr = MPI_Exscan(&size_on_proc,
820 &prefix_sum,
821 1,
822 MPI_UINT64_T,
823 MPI_SUM,
824 mpi_communicator);
825 AssertThrowMPI(ierr);
826
827 const MPI_Offset my_global_file_position =
828 static_cast<MPI_Offset>(global_num_cells) * sizeof(unsigned int) +
829 prefix_sum;
830
831 // Write data consecutively into file.
833 fh,
834 my_global_file_position,
835 src_data_variable.data(),
836 src_data_variable.size(),
837 MPI_BYTE,
838 MPI_STATUS_IGNORE);
839 AssertThrowMPI(ierr);
840
841
842 ierr = MPI_File_close(&fh);
843 AssertThrowMPI(ierr);
844 }
845 } // if (mpisize > 1)
846 else
847#endif
848 {
849 (void)global_first_cell;
850 (void)global_num_cells;
851 (void)mpi_communicator;
852
853 //
854 // ---------- Fixed size data ----------
855 //
856 {
857 const std::string fname_fixed = std::string(filename) + "_fixed.data";
858
859 std::ofstream file(fname_fixed, std::ios::binary | std::ios::out);
860
861 // Write header data.
862 file.write(reinterpret_cast<const char *>(
863 sizes_fixed_cumulative.data()),
864 sizes_fixed_cumulative.size() * sizeof(unsigned int));
865
866 // Write packed data.
867 file.write(reinterpret_cast<const char *>(src_data_fixed.data()),
868 src_data_fixed.size() * sizeof(char));
869
870 file.close();
871 }
872
873 //
874 // ---------- Variable size data ----------
875 //
876 if (variable_size_data_stored)
877 {
878 const std::string fname_variable =
879 std::string(filename) + "_variable.data";
880
881 std::ofstream file(fname_variable,
882 std::ios::binary | std::ios::out);
883
884 // Write header data.
885 file.write(reinterpret_cast<const char *>(
886 src_sizes_variable.data()),
887 src_sizes_variable.size() * sizeof(int));
888
889 // Write packed data.
890 file.write(reinterpret_cast<const char *>(src_data_variable.data()),
891 src_data_variable.size() * sizeof(char));
892
893 file.close();
894 }
895 }
896 }
897
898
899 template <int dim, int spacedim>
901 void CellAttachedDataSerializer<dim, spacedim>::load(
902 const unsigned int global_first_cell,
903 const unsigned int global_num_cells,
904 const unsigned int local_num_cells,
905 const std::string &filename,
906 const unsigned int n_attached_deserialize_fixed,
907 const unsigned int n_attached_deserialize_variable,
908 const MPI_Comm &mpi_communicator)
909 {
910 Assert(dest_data_fixed.empty(),
911 ExcMessage("Previously loaded data has not been released yet!"));
912
913 variable_size_data_stored = (n_attached_deserialize_variable > 0);
914
915#ifdef DEAL_II_WITH_MPI
916 // Large fractions of this function have been copied from
917 // DataOutInterface::write_vtu_in_parallel.
918 // TODO: Write general MPIIO interface.
919
920 const int mpisize = Utilities::MPI::n_mpi_processes(mpi_communicator);
921
922 if (mpisize > 1)
923 {
924 //
925 // ---------- Fixed size data ----------
926 //
927 {
928 const std::string fname_fixed = std::string(filename) + "_fixed.data";
929
930 MPI_Info info;
931 int ierr = MPI_Info_create(&info);
932 AssertThrowMPI(ierr);
933
934 MPI_File fh;
935 ierr = MPI_File_open(
936 mpi_communicator, fname_fixed.c_str(), MPI_MODE_RDONLY, info, &fh);
937 AssertThrowMPI(ierr);
938
939 ierr = MPI_Info_free(&info);
940 AssertThrowMPI(ierr);
941
942 // Read cumulative sizes from file.
943 // Since all processors need the same information about the data
944 // sizes, let each of them retrieve it by reading from the same
945 // location in the file.
946 sizes_fixed_cumulative.resize(1 + n_attached_deserialize_fixed +
947 (variable_size_data_stored ? 1 : 0));
949 fh,
950 0,
951 sizes_fixed_cumulative.data(),
952 sizes_fixed_cumulative.size(),
953 MPI_UNSIGNED,
954 MPI_STATUS_IGNORE);
955 AssertThrowMPI(ierr);
956
957 // Allocate sufficient memory.
958 const unsigned int bytes_per_cell = sizes_fixed_cumulative.back();
959 dest_data_fixed.resize(static_cast<size_t>(local_num_cells) *
960 bytes_per_cell);
961
962 // Read packed data from file simultaneously.
963 const MPI_Offset size_header =
964 sizes_fixed_cumulative.size() * sizeof(unsigned int);
965
966 // Make sure we do the following computation in 64bit integers to be
967 // able to handle 4GB+ files:
968 const MPI_Offset my_global_file_position =
969 size_header +
970 static_cast<MPI_Offset>(global_first_cell) * bytes_per_cell;
971
972 ierr =
974 my_global_file_position,
975 dest_data_fixed.data(),
976 dest_data_fixed.size(),
977 MPI_BYTE,
978 MPI_STATUS_IGNORE);
979 AssertThrowMPI(ierr);
980
981
982 ierr = MPI_File_close(&fh);
983 AssertThrowMPI(ierr);
984 }
985
986 //
987 // ---------- Variable size data ----------
988 //
989 if (variable_size_data_stored)
990 {
991 const std::string fname_variable =
992 std::string(filename) + "_variable.data";
993
994 MPI_Info info;
995 int ierr = MPI_Info_create(&info);
996 AssertThrowMPI(ierr);
997
998 MPI_File fh;
999 ierr = MPI_File_open(mpi_communicator,
1000 fname_variable.c_str(),
1001 MPI_MODE_RDONLY,
1002 info,
1003 &fh);
1004 AssertThrowMPI(ierr);
1005
1006 ierr = MPI_Info_free(&info);
1007 AssertThrowMPI(ierr);
1008
1009 // Read sizes of all locally owned cells.
1010 dest_sizes_variable.resize(local_num_cells);
1011
1012 const MPI_Offset my_global_file_position_sizes =
1013 static_cast<MPI_Offset>(global_first_cell) * sizeof(unsigned int);
1014
1016 fh,
1017 my_global_file_position_sizes,
1018 dest_sizes_variable.data(),
1019 dest_sizes_variable.size(),
1020 MPI_INT,
1021 MPI_STATUS_IGNORE);
1022 AssertThrowMPI(ierr);
1023
1024
1025 // Compute my data size in bytes and compute prefix sum. We do this
1026 // in 64 bit to avoid overflow for files larger than 4 GB:
1027 const std::uint64_t size_on_proc =
1028 std::accumulate(dest_sizes_variable.begin(),
1029 dest_sizes_variable.end(),
1030 0ULL);
1031
1032 std::uint64_t prefix_sum = 0;
1033 ierr = MPI_Exscan(&size_on_proc,
1034 &prefix_sum,
1035 1,
1036 MPI_UINT64_T,
1037 MPI_SUM,
1038 mpi_communicator);
1039 AssertThrowMPI(ierr);
1040
1041 const MPI_Offset my_global_file_position =
1042 static_cast<MPI_Offset>(global_num_cells) * sizeof(unsigned int) +
1043 prefix_sum;
1044
1045 dest_data_variable.resize(size_on_proc);
1046
1048 fh,
1049 my_global_file_position,
1050 dest_data_variable.data(),
1051 dest_data_variable.size(),
1052 MPI_BYTE,
1053 MPI_STATUS_IGNORE);
1054 AssertThrowMPI(ierr);
1055
1056 ierr = MPI_File_close(&fh);
1057 AssertThrowMPI(ierr);
1058 }
1059 }
1060 else // if (mpisize > 1)
1061#endif
1062 {
1063 (void)global_first_cell;
1064 (void)global_num_cells;
1065 (void)mpi_communicator;
1066
1067 //
1068 // ---------- Fixed size data ----------
1069 //
1070 {
1071 const std::string fname_fixed = std::string(filename) + "_fixed.data";
1072
1073 std::ifstream file(fname_fixed, std::ios::binary | std::ios::in);
1074 sizes_fixed_cumulative.resize(1 + n_attached_deserialize_fixed +
1075 (variable_size_data_stored ? 1 : 0));
1076
1077 // Read header data.
1078 file.read(reinterpret_cast<char *>(sizes_fixed_cumulative.data()),
1079 sizes_fixed_cumulative.size() * sizeof(unsigned int));
1080
1081 const unsigned int bytes_per_cell = sizes_fixed_cumulative.back();
1082 dest_data_fixed.resize(static_cast<size_t>(local_num_cells) *
1083 bytes_per_cell);
1084
1085 // Read packed data.
1086 file.read(reinterpret_cast<char *>(dest_data_fixed.data()),
1087 dest_data_fixed.size() * sizeof(char));
1088
1089 file.close();
1090 }
1091
1092 //
1093 // ---------- Variable size data ----------
1094 //
1095 if (variable_size_data_stored)
1096 {
1097 const std::string fname_variable =
1098 std::string(filename) + "_variable.data";
1099
1100 std::ifstream file(fname_variable, std::ios::binary | std::ios::in);
1101
1102 // Read header data.
1103 dest_sizes_variable.resize(local_num_cells);
1104 file.read(reinterpret_cast<char *>(dest_sizes_variable.data()),
1105 dest_sizes_variable.size() * sizeof(int));
1106
1107 // Read packed data.
1108 const std::uint64_t size =
1109 std::accumulate(dest_sizes_variable.begin(),
1110 dest_sizes_variable.end(),
1111 0ULL);
1112 dest_data_variable.resize(size);
1113 file.read(reinterpret_cast<char *>(dest_data_variable.data()),
1114 dest_data_variable.size() * sizeof(char));
1115
1116 file.close();
1117 }
1118 }
1119 }
1120
1121
1122 template <int dim, int spacedim>
1124 void CellAttachedDataSerializer<dim, spacedim>::clear()
1125 {
1126 variable_size_data_stored = false;
1127
1128 // free information about data sizes
1129 sizes_fixed_cumulative.clear();
1130 sizes_fixed_cumulative.shrink_to_fit();
1131
1132 // free fixed size transfer data
1133 src_data_fixed.clear();
1134 src_data_fixed.shrink_to_fit();
1135
1136 dest_data_fixed.clear();
1137 dest_data_fixed.shrink_to_fit();
1138
1139 // free variable size transfer data
1140 src_sizes_variable.clear();
1141 src_sizes_variable.shrink_to_fit();
1142
1143 src_data_variable.clear();
1144 src_data_variable.shrink_to_fit();
1145
1146 dest_sizes_variable.clear();
1147 dest_sizes_variable.shrink_to_fit();
1148
1149 dest_data_variable.clear();
1150 dest_data_variable.shrink_to_fit();
1151 }
1152
1153} // namespace internal
1154
1155// anonymous namespace for internal helper functions
1156namespace
1157{
1158 // return whether the given cell is
1159 // patch_level_1, i.e. determine
1160 // whether either all or none of
1161 // its children are further
1162 // refined. this function can only
1163 // be called for non-active cells.
1164 template <int dim, int spacedim>
1165 bool
1166 cell_is_patch_level_1(
1168 {
1169 Assert(cell->is_active() == false, ExcInternalError());
1170
1171 unsigned int n_active_children = 0;
1172 for (unsigned int i = 0; i < cell->n_children(); ++i)
1173 if (cell->child(i)->is_active())
1174 ++n_active_children;
1175
1176 return (n_active_children == 0) ||
1177 (n_active_children == cell->n_children());
1178 }
1179
1180
1181
1182 // return, whether a given @p cell will be
1183 // coarsened, which is the case if all
1184 // children are active and have their coarsen
1185 // flag set. In case only part of the coarsen
1186 // flags are set, remove them.
1187 template <int dim, int spacedim>
1188 bool
1189 cell_will_be_coarsened(
1191 {
1192 // only cells with children should be
1193 // considered for coarsening
1194
1195 if (cell->has_children())
1196 {
1197 unsigned int children_to_coarsen = 0;
1198 const unsigned int n_children = cell->n_children();
1199
1200 for (unsigned int c = 0; c < n_children; ++c)
1201 if (cell->child(c)->is_active() && cell->child(c)->coarsen_flag_set())
1202 ++children_to_coarsen;
1203 if (children_to_coarsen == n_children)
1204 return true;
1205 else
1206 for (unsigned int c = 0; c < n_children; ++c)
1207 if (cell->child(c)->is_active())
1208 cell->child(c)->clear_coarsen_flag();
1209 }
1210 // no children, so no coarsening
1211 // possible. however, no children also
1212 // means that this cell will be in the same
1213 // state as if it had children and was
1214 // coarsened. So, what should we return -
1215 // false or true?
1216 // make sure we do not have to do this at
1217 // all...
1218 Assert(cell->has_children(), ExcInternalError());
1219 // ... and then simply return false
1220 return false;
1221 }
1222
1223
1224 // return, whether the face @p face_no of the
1225 // given @p cell will be refined after the
1226 // current refinement step, considering
1227 // refine and coarsen flags and considering
1228 // only those refinemnts that will be caused
1229 // by the neighboring cell.
1230
1231 // this function is used on both active cells
1232 // and cells with children. on cells with
1233 // children it also of interest to know 'how'
1234 // the face will be refined. thus there is an
1235 // additional third argument @p
1236 // expected_face_ref_case returning just
1237 // that. be aware, that this variable will
1238 // only contain useful information if this
1239 // function is called for an active cell.
1240 //
1241 // thus, this is an internal function, users
1242 // should call one of the two alternatives
1243 // following below.
1244 template <int dim, int spacedim>
1245 bool
1246 face_will_be_refined_by_neighbor_internal(
1248 const unsigned int face_no,
1249 RefinementCase<dim - 1> &expected_face_ref_case)
1250 {
1251 // first of all: set the default value for
1252 // expected_face_ref_case, which is no
1253 // refinement at all
1254 expected_face_ref_case = RefinementCase<dim - 1>::no_refinement;
1255
1256 const typename Triangulation<dim, spacedim>::cell_iterator neighbor =
1257 cell->neighbor(face_no);
1258
1259 // If we are at the boundary, there is no
1260 // neighbor which could refine the face
1261 if (neighbor.state() != IteratorState::valid)
1262 return false;
1263
1264 if (neighbor->has_children())
1265 {
1266 // if the neighbor is refined, it may be
1267 // coarsened. if so, then it won't refine
1268 // the face, no matter what else happens
1269 if (cell_will_be_coarsened(neighbor))
1270 return false;
1271 else
1272 // if the neighbor is refined, then it
1273 // is also refined at our current
1274 // face. It will stay so without
1275 // coarsening, so return true in that
1276 // case.
1277 {
1278 expected_face_ref_case = cell->face(face_no)->refinement_case();
1279 return true;
1280 }
1281 }
1282
1283 // now, the neighbor is not refined, but
1284 // perhaps it will be
1285 const RefinementCase<dim> nb_ref_flag = neighbor->refine_flag_set();
1286 if (nb_ref_flag != RefinementCase<dim>::no_refinement)
1287 {
1288 // now we need to know, which of the
1289 // neighbors faces points towards us
1290 const unsigned int neighbor_neighbor = cell->neighbor_face_no(face_no);
1291 // check, whether the cell will be
1292 // refined in a way that refines our
1293 // face
1294 const RefinementCase<dim - 1> face_ref_case =
1296 nb_ref_flag,
1297 neighbor_neighbor,
1298 neighbor->face_orientation(neighbor_neighbor),
1299 neighbor->face_flip(neighbor_neighbor),
1300 neighbor->face_rotation(neighbor_neighbor));
1301 if (face_ref_case != RefinementCase<dim - 1>::no_refinement)
1302 {
1304 neighbor_face = neighbor->face(neighbor_neighbor);
1305 const int this_face_index = cell->face_index(face_no);
1306
1307 // there are still two basic
1308 // possibilities here: the neighbor
1309 // might be coarser or as coarse
1310 // as we are
1311 if (neighbor_face->index() == this_face_index)
1312 // the neighbor is as coarse as
1313 // we are and will be refined at
1314 // the face of consideration, so
1315 // return true
1316 {
1317 expected_face_ref_case = face_ref_case;
1318 return true;
1319 }
1320 else
1321 {
1322 // the neighbor is coarser.
1323 // this is the most complicated
1324 // case. It might be, that the
1325 // neighbor's face will be
1326 // refined, but that we will
1327 // not see this, as we are
1328 // refined in a similar way.
1329
1330 // so, the neighbor's face must
1331 // have children. check, if our
1332 // cell's face is one of these
1333 // (it could also be a
1334 // grand_child)
1335 for (unsigned int c = 0; c < neighbor_face->n_children(); ++c)
1336 if (neighbor_face->child_index(c) == this_face_index)
1337 {
1338 // if the flagged refine
1339 // case of the face is a
1340 // subset or the same as
1341 // the current refine case,
1342 // then the face, as seen
1343 // from our cell, won't be
1344 // refined by the neighbor
1345 if ((neighbor_face->refinement_case() | face_ref_case) ==
1346 neighbor_face->refinement_case())
1347 return false;
1348 else
1349 {
1350 // if we are active, we
1351 // must be an
1352 // anisotropic child
1353 // and the coming
1354 // face_ref_case is
1355 // isotropic. Thus,
1356 // from our cell we
1357 // will see exactly the
1358 // opposite refine case
1359 // that the face has
1360 // now...
1361 Assert(
1362 face_ref_case ==
1365 expected_face_ref_case =
1366 ~neighbor_face->refinement_case();
1367 return true;
1368 }
1369 }
1370
1371 // so, obviously we were not
1372 // one of the children, but a
1373 // grandchild. This is only
1374 // possible in 3d.
1375 Assert(dim == 3, ExcInternalError());
1376 // In that case, however, no
1377 // matter what the neighbor
1378 // does, it won't be finer
1379 // after the next refinement
1380 // step.
1381 return false;
1382 }
1383 } // if face will be refined
1384 } // if neighbor is flagged for refinement
1385
1386 // no cases left, so the neighbor will not
1387 // refine the face
1388 return false;
1389 }
1390
1391 // version of above function for both active
1392 // and non-active cells
1393 template <int dim, int spacedim>
1394 bool
1395 face_will_be_refined_by_neighbor(
1397 const unsigned int face_no)
1398 {
1399 RefinementCase<dim - 1> dummy = RefinementCase<dim - 1>::no_refinement;
1400 return face_will_be_refined_by_neighbor_internal(cell, face_no, dummy);
1401 }
1402
1403 // version of above function for active cells
1404 // only. Additionally returning the refine
1405 // case (to come) of the face under
1406 // consideration
1407 template <int dim, int spacedim>
1408 bool
1409 face_will_be_refined_by_neighbor(
1411 const unsigned int face_no,
1412 RefinementCase<dim - 1> &expected_face_ref_case)
1413 {
1414 return face_will_be_refined_by_neighbor_internal(cell,
1415 face_no,
1416 expected_face_ref_case);
1417 }
1418
1419
1420
1421 template <int dim, int spacedim>
1422 bool
1423 satisfies_level1_at_vertex_rule(
1425 {
1426 std::vector<unsigned int> min_adjacent_cell_level(
1427 triangulation.n_vertices(), triangulation.n_levels());
1428 std::vector<unsigned int> max_adjacent_cell_level(
1429 triangulation.n_vertices(), 0);
1430
1431 for (const auto &cell : triangulation.active_cell_iterators())
1432 for (const unsigned int v : cell->vertex_indices())
1433 {
1434 min_adjacent_cell_level[cell->vertex_index(v)] =
1435 std::min<unsigned int>(
1436 min_adjacent_cell_level[cell->vertex_index(v)], cell->level());
1437 max_adjacent_cell_level[cell->vertex_index(v)] =
1438 std::max<unsigned int>(
1439 min_adjacent_cell_level[cell->vertex_index(v)], cell->level());
1440 }
1441
1442 for (unsigned int k = 0; k < triangulation.n_vertices(); ++k)
1443 if (triangulation.vertex_used(k))
1444 if (max_adjacent_cell_level[k] - min_adjacent_cell_level[k] > 1)
1445 return false;
1446 return true;
1447 }
1448
1449
1450
1468 template <int dim, int spacedim>
1469 unsigned int
1470 middle_vertex_index(
1472 {
1473 if (line->has_children())
1474 return line->child(0)->vertex_index(1);
1476 }
1477
1478
1479 template <int dim, int spacedim>
1480 unsigned int
1481 middle_vertex_index(
1483 {
1484 switch (static_cast<unsigned char>(quad->refinement_case()))
1485 {
1487 return middle_vertex_index<dim, spacedim>(quad->child(0)->line(1));
1488 break;
1490 return middle_vertex_index<dim, spacedim>(quad->child(0)->line(3));
1491 break;
1493 return quad->child(0)->vertex_index(3);
1494 break;
1495 default:
1496 break;
1497 }
1499 }
1500
1501
1502 template <int dim, int spacedim>
1503 unsigned int
1504 middle_vertex_index(
1506 {
1507 switch (static_cast<unsigned char>(hex->refinement_case()))
1508 {
1510 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(1));
1511 break;
1513 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(3));
1514 break;
1516 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(5));
1517 break;
1519 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(11));
1520 break;
1522 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(5));
1523 break;
1525 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(7));
1526 break;
1528 return hex->child(0)->vertex_index(7);
1529 break;
1530 default:
1531 break;
1532 }
1534 }
1535
1536
1549 template <class TRIANGULATION>
1550 inline typename TRIANGULATION::DistortedCellList
1551 collect_distorted_coarse_cells(const TRIANGULATION &)
1552 {
1553 return typename TRIANGULATION::DistortedCellList();
1554 }
1555
1556
1557
1566 template <int dim>
1568 collect_distorted_coarse_cells(const Triangulation<dim, dim> &triangulation)
1569 {
1570 typename Triangulation<dim, dim>::DistortedCellList distorted_cells;
1571 for (const auto &cell : triangulation.cell_iterators_on_level(0))
1572 {
1574 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1575 vertices[i] = cell->vertex(i);
1576
1579
1580 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1581 if (determinants[i] <=
1582 1e-9 * Utilities::fixed_power<dim>(cell->diameter()))
1583 {
1584 distorted_cells.distorted_cells.push_back(cell);
1585 break;
1586 }
1587 }
1588
1589 return distorted_cells;
1590 }
1591
1592
1599 template <int dim>
1600 bool
1601 has_distorted_children(
1602 const typename Triangulation<dim, dim>::cell_iterator &cell)
1603 {
1604 Assert(cell->has_children(), ExcInternalError());
1605
1606 for (unsigned int c = 0; c < cell->n_children(); ++c)
1607 {
1609 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1610 vertices[i] = cell->child(c)->vertex(i);
1611
1614
1615 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1616 if (determinants[i] <=
1617 1e-9 * Utilities::fixed_power<dim>(cell->child(c)->diameter()))
1618 return true;
1619 }
1620
1621 return false;
1622 }
1623
1624
1632 template <int dim, int spacedim>
1633 bool
1634 has_distorted_children(
1636 {
1637 return false;
1638 }
1639
1640
1641 template <int dim, int spacedim>
1642 void
1643 update_periodic_face_map_recursively(
1644 const typename Triangulation<dim, spacedim>::cell_iterator &cell_1,
1645 const typename Triangulation<dim, spacedim>::cell_iterator &cell_2,
1646 unsigned int n_face_1,
1647 unsigned int n_face_2,
1648 const unsigned char orientation,
1649 typename std::map<
1651 unsigned int>,
1652 std::pair<std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
1653 unsigned int>,
1654 unsigned char>> &periodic_face_map)
1655 {
1656 using FaceIterator = typename Triangulation<dim, spacedim>::face_iterator;
1657 const FaceIterator face_1 = cell_1->face(n_face_1);
1658 const FaceIterator face_2 = cell_2->face(n_face_2);
1659
1660 const unsigned char inverse_orientation =
1661 face_1->reference_cell().get_inverse_combined_orientation(orientation);
1662
1663#ifdef DEBUG
1664 const auto [face_orientation, face_rotation, face_flip] =
1666
1667 Assert((dim != 1) || (face_orientation == true && face_flip == false &&
1668 face_rotation == false),
1669 ExcMessage("The supplied orientation "
1670 "(face_orientation, face_flip, face_rotation) "
1671 "is invalid for 1d"));
1672
1673 Assert((dim != 2) || (face_flip == false && face_rotation == false),
1674 ExcMessage("The supplied orientation "
1675 "(face_orientation, face_flip, face_rotation) "
1676 "is invalid for 2d"));
1677#endif
1678
1679 Assert(face_1 != face_2, ExcMessage("face_1 and face_2 are equal!"));
1680
1681 Assert(face_1->at_boundary() && face_2->at_boundary(),
1682 ExcMessage("Periodic faces must be on the boundary"));
1683
1684 // Check if the requirement that each edge can only have at most one hanging
1685 // node, and as a consequence neighboring cells can differ by at most
1686 // one refinement level is enforced. In 1d, there are no hanging nodes and
1687 // so neighboring cells can differ by more than one refinement level.
1688 Assert(dim == 1 || std::abs(cell_1->level() - cell_2->level()) < 2,
1690
1691 // insert periodic face pair for both cells
1692 using CellFace =
1693 std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
1694 unsigned int>;
1695 const CellFace cell_face_1(cell_1, n_face_1);
1696 const CellFace cell_face_2(cell_2, n_face_2);
1697 const std::pair<CellFace, unsigned char> cell_face_orientation_2(
1698 cell_face_2, orientation);
1699
1700 const std::pair<CellFace, std::pair<CellFace, unsigned char>>
1701 periodic_faces(cell_face_1, cell_face_orientation_2);
1702
1703 // Only one periodic neighbor is allowed
1704 Assert(periodic_face_map.count(cell_face_1) == 0, ExcInternalError());
1705 periodic_face_map.insert(periodic_faces);
1706
1707 if (dim == 1)
1708 {
1709 if (cell_1->has_children())
1710 {
1711 if (cell_2->has_children())
1712 {
1713 update_periodic_face_map_recursively<dim, spacedim>(
1714 cell_1->child(n_face_1),
1715 cell_2->child(n_face_2),
1716 n_face_1,
1717 n_face_2,
1718 orientation,
1719 periodic_face_map);
1720 }
1721 else // only face_1 has children
1722 {
1723 update_periodic_face_map_recursively<dim, spacedim>(
1724 cell_1->child(n_face_1),
1725 cell_2,
1726 n_face_1,
1727 n_face_2,
1728 orientation,
1729 periodic_face_map);
1730 }
1731 }
1732 }
1733 else // dim == 2 || dim == 3
1734 {
1735 if (cell_1->has_children())
1736 {
1737 if (cell_2->has_children())
1738 {
1739 // In the case that both faces have children, we loop over all
1740 // children and apply update_periodic_face_map_recursively
1741 // recursively:
1742
1743 Assert(face_1->n_children() ==
1745 face_2->n_children() ==
1748
1749 const auto reference_cell = cell_1->reference_cell();
1750
1751 for (unsigned int i = 0;
1752 i < GeometryInfo<dim>::max_children_per_face;
1753 ++i)
1754 {
1755 // Lookup the index for the second face
1756 const unsigned int j =
1757 reference_cell.standard_to_real_face_vertex(
1758 i, n_face_1, inverse_orientation);
1759
1760 // find subcell ids that belong to the subface indices
1761 unsigned int child_cell_1 =
1763 cell_1->refinement_case(),
1764 n_face_1,
1765 i,
1766 cell_1->face_orientation(n_face_1),
1767 cell_1->face_flip(n_face_1),
1768 cell_1->face_rotation(n_face_1),
1769 face_1->refinement_case());
1770 unsigned int child_cell_2 =
1772 cell_2->refinement_case(),
1773 n_face_2,
1774 j,
1775 cell_2->face_orientation(n_face_2),
1776 cell_2->face_flip(n_face_2),
1777 cell_2->face_rotation(n_face_2),
1778 face_2->refinement_case());
1779
1780 Assert(cell_1->child(child_cell_1)->face(n_face_1) ==
1781 face_1->child(i),
1783 Assert(cell_2->child(child_cell_2)->face(n_face_2) ==
1784 face_2->child(j),
1786
1787 // precondition: subcell has the same orientation as cell
1788 // (so that the face numbers coincide) recursive call
1789 update_periodic_face_map_recursively<dim, spacedim>(
1790 cell_1->child(child_cell_1),
1791 cell_2->child(child_cell_2),
1792 n_face_1,
1793 n_face_2,
1794 orientation,
1795 periodic_face_map);
1796 }
1797 }
1798 else // only face_1 has children
1799 {
1800 for (unsigned int i = 0;
1801 i < GeometryInfo<dim>::max_children_per_face;
1802 ++i)
1803 {
1804 // find subcell ids that belong to the subface indices
1805 unsigned int child_cell_1 =
1807 cell_1->refinement_case(),
1808 n_face_1,
1809 i,
1810 cell_1->face_orientation(n_face_1),
1811 cell_1->face_flip(n_face_1),
1812 cell_1->face_rotation(n_face_1),
1813 face_1->refinement_case());
1814
1815 // recursive call
1816 update_periodic_face_map_recursively<dim, spacedim>(
1817 cell_1->child(child_cell_1),
1818 cell_2,
1819 n_face_1,
1820 n_face_2,
1821 orientation,
1822 periodic_face_map);
1823 }
1824 }
1825 }
1826 }
1827 }
1828
1829
1830} // end of anonymous namespace
1831
1832
1833namespace internal
1834{
1835 namespace TriangulationImplementation
1836 {
1837 // make sure that if in the following we
1838 // write Triangulation<dim,spacedim>
1839 // we mean the *class*
1840 // ::Triangulation, not the
1841 // enclosing namespace
1842 // internal::TriangulationImplementation
1843 using ::Triangulation;
1844
1850 int,
1851 << "Something went wrong upon construction of cell "
1852 << arg1);
1863 int,
1864 << "Cell " << arg1
1865 << " has negative measure. This typically "
1866 << "indicates some distortion in the cell, or a mistakenly "
1867 << "swapped pair of vertices in the input to "
1868 << "Triangulation::create_triangulation().");
1877 int,
1878 int,
1879 int,
1880 << "Error while creating cell " << arg1
1881 << ": the vertex index " << arg2 << " must be between 0 and "
1882 << arg3 << '.');
1889 int,
1890 int,
1892 << "The input data for creating a triangulation contained "
1893 << "information about a line with indices " << arg1 << " and " << arg2
1894 << " that is described to have boundary indicator "
1895 << static_cast<int>(arg3)
1896 << ". However, this is an internal line not located on the "
1897 << "boundary. You cannot assign a boundary indicator to it." << std::endl
1898 << std::endl
1899 << "If this happened at a place where you call "
1900 << "Triangulation::create_triangulation() yourself, you need "
1901 << "to check the SubCellData object you pass to this function."
1902 << std::endl
1903 << std::endl
1904 << "If this happened in a place where you are reading a mesh "
1905 << "from a file, then you need to investigate why such a line "
1906 << "ended up in the input file. A typical case is a geometry "
1907 << "that consisted of multiple parts and for which the mesh "
1908 << "generator program assumes that the interface between "
1909 << "two parts is a boundary when that isn't supposed to be "
1910 << "the case, or where the mesh generator simply assigns "
1911 << "'geometry indicators' to lines at the perimeter of "
1912 << "a part that are not supposed to be interpreted as "
1913 << "'boundary indicators'.");
1920 int,
1921 int,
1922 int,
1923 int,
1925 << "The input data for creating a triangulation contained "
1926 << "information about a quad with indices " << arg1 << ", " << arg2
1927 << ", " << arg3 << ", and " << arg4
1928 << " that is described to have boundary indicator "
1929 << static_cast<int>(arg5)
1930 << ". However, this is an internal quad not located on the "
1931 << "boundary. You cannot assign a boundary indicator to it." << std::endl
1932 << std::endl
1933 << "If this happened at a place where you call "
1934 << "Triangulation::create_triangulation() yourself, you need "
1935 << "to check the SubCellData object you pass to this function."
1936 << std::endl
1937 << std::endl
1938 << "If this happened in a place where you are reading a mesh "
1939 << "from a file, then you need to investigate why such a quad "
1940 << "ended up in the input file. A typical case is a geometry "
1941 << "that consisted of multiple parts and for which the mesh "
1942 << "generator program assumes that the interface between "
1943 << "two parts is a boundary when that isn't supposed to be "
1944 << "the case, or where the mesh generator simply assigns "
1945 << "'geometry indicators' to quads at the surface of "
1946 << "a part that are not supposed to be interpreted as "
1947 << "'boundary indicators'.");
1954 int,
1955 int,
1956 << "In SubCellData the line info of the line with vertex indices " << arg1
1957 << " and " << arg2 << " appears more than once. "
1958 << "This is not allowed.");
1965 int,
1966 int,
1967 std::string,
1968 << "In SubCellData the line info of the line with vertex indices " << arg1
1969 << " and " << arg2 << " appears multiple times with different (valid) "
1970 << arg3 << ". This is not allowed.");
1977 int,
1978 int,
1979 int,
1980 int,
1981 std::string,
1982 << "In SubCellData the quad info of the quad with line indices " << arg1
1983 << ", " << arg2 << ", " << arg3 << " and " << arg4
1984 << " appears multiple times with different (valid) " << arg5
1985 << ". This is not allowed.");
1986
1987 /*
1988 * Reserve space for TriaFaces. Details:
1989 *
1990 * Reserve space for line_orientations.
1991 *
1992 * @note Used only for dim=3.
1993 */
1994 void
1996 const unsigned int new_quads_in_pairs,
1997 const unsigned int new_quads_single)
1998 {
1999 AssertDimension(tria_faces.dim, 3);
2000
2001 Assert(new_quads_in_pairs % 2 == 0, ExcInternalError());
2002
2003 unsigned int next_free_single = 0;
2004 unsigned int next_free_pair = 0;
2005
2006 // count the number of objects, of unused single objects and of
2007 // unused pairs of objects
2008 unsigned int n_quads = 0;
2009 unsigned int n_unused_pairs = 0;
2010 unsigned int n_unused_singles = 0;
2011 for (unsigned int i = 0; i < tria_faces.quads.used.size(); ++i)
2012 {
2013 if (tria_faces.quads.used[i])
2014 ++n_quads;
2015 else if (i + 1 < tria_faces.quads.used.size())
2016 {
2017 if (tria_faces.quads.used[i + 1])
2018 {
2019 ++n_unused_singles;
2020 if (next_free_single == 0)
2021 next_free_single = i;
2022 }
2023 else
2024 {
2025 ++n_unused_pairs;
2026 if (next_free_pair == 0)
2027 next_free_pair = i;
2028 ++i;
2029 }
2030 }
2031 else
2032 ++n_unused_singles;
2033 }
2034 Assert(n_quads + 2 * n_unused_pairs + n_unused_singles ==
2035 tria_faces.quads.used.size(),
2037 (void)n_quads;
2038
2039 // how many single quads are needed in addition to n_unused_quads?
2040 const int additional_single_quads = new_quads_single - n_unused_singles;
2041
2042 unsigned int new_size =
2043 tria_faces.quads.used.size() + new_quads_in_pairs - 2 * n_unused_pairs;
2044 if (additional_single_quads > 0)
2045 new_size += additional_single_quads;
2046
2047 // see above...
2048 if (new_size > tria_faces.quads.n_objects())
2049 {
2050 // reserve the field of the derived class
2051 tria_faces.quads_line_orientations.resize(
2052 new_size * GeometryInfo<3>::lines_per_face, true);
2053
2054 auto &q_is_q = tria_faces.quad_is_quadrilateral;
2055 q_is_q.reserve(new_size);
2056 q_is_q.insert(q_is_q.end(), new_size - q_is_q.size(), true);
2057 }
2058 }
2059
2060
2061
2075 void
2077 const unsigned int total_cells,
2078 const unsigned int dimension,
2079 const unsigned int space_dimension)
2080 {
2081 // we need space for total_cells cells. Maybe we have more already
2082 // with those cells which are unused, so only allocate new space if
2083 // needed.
2084 //
2085 // note that all arrays should have equal sizes (checked by
2086 // @p{monitor_memory}
2087 if (total_cells > tria_level.refine_flags.size())
2088 {
2089 tria_level.refine_flags.reserve(total_cells);
2090 tria_level.refine_flags.insert(tria_level.refine_flags.end(),
2091 total_cells -
2092 tria_level.refine_flags.size(),
2093 /*RefinementCase::no_refinement=*/0);
2094
2095 tria_level.coarsen_flags.reserve(total_cells);
2096 tria_level.coarsen_flags.insert(tria_level.coarsen_flags.end(),
2097 total_cells -
2098 tria_level.coarsen_flags.size(),
2099 false);
2100
2101 tria_level.active_cell_indices.reserve(total_cells);
2102 tria_level.active_cell_indices.insert(
2103 tria_level.active_cell_indices.end(),
2104 total_cells - tria_level.active_cell_indices.size(),
2106
2107 tria_level.subdomain_ids.reserve(total_cells);
2108 tria_level.subdomain_ids.insert(tria_level.subdomain_ids.end(),
2109 total_cells -
2110 tria_level.subdomain_ids.size(),
2111 0);
2112
2113 tria_level.level_subdomain_ids.reserve(total_cells);
2114 tria_level.level_subdomain_ids.insert(
2115 tria_level.level_subdomain_ids.end(),
2116 total_cells - tria_level.level_subdomain_ids.size(),
2117 0);
2118
2119 tria_level.global_active_cell_indices.reserve(total_cells);
2120 tria_level.global_active_cell_indices.insert(
2121 tria_level.global_active_cell_indices.end(),
2122 total_cells - tria_level.global_active_cell_indices.size(),
2124
2125 tria_level.global_level_cell_indices.reserve(total_cells);
2126 tria_level.global_level_cell_indices.insert(
2127 tria_level.global_level_cell_indices.end(),
2128 total_cells - tria_level.global_level_cell_indices.size(),
2130
2131 if (dimension == space_dimension - 1)
2132 {
2133 tria_level.direction_flags.reserve(total_cells);
2134 tria_level.direction_flags.insert(
2135 tria_level.direction_flags.end(),
2136 total_cells - tria_level.direction_flags.size(),
2137 true);
2138 }
2139 else
2140 tria_level.direction_flags.clear();
2141
2142 tria_level.parents.reserve((total_cells + 1) / 2);
2143 tria_level.parents.insert(tria_level.parents.end(),
2144 (total_cells + 1) / 2 -
2145 tria_level.parents.size(),
2146 -1);
2147
2148 tria_level.neighbors.reserve(total_cells * (2 * dimension));
2149 tria_level.neighbors.insert(tria_level.neighbors.end(),
2150 total_cells * (2 * dimension) -
2151 tria_level.neighbors.size(),
2152 std::make_pair(-1, -1));
2153
2154 if (tria_level.dim == 2 || tria_level.dim == 3)
2155 {
2156 const unsigned int max_faces_per_cell = 2 * dimension;
2157 tria_level.face_orientations.resize(total_cells *
2158 max_faces_per_cell);
2159
2160 tria_level.reference_cell.reserve(total_cells);
2161 tria_level.reference_cell.insert(
2162 tria_level.reference_cell.end(),
2163 total_cells - tria_level.reference_cell.size(),
2164 tria_level.dim == 2 ? ReferenceCells::Quadrilateral :
2166 }
2167 }
2168 }
2169
2170
2171
2176 int,
2177 int,
2178 << "The containers have sizes " << arg1 << " and " << arg2
2179 << ", which is not as expected.");
2180
2186 void
2187 monitor_memory(const TriaLevel &tria_level,
2188 const unsigned int true_dimension)
2189 {
2190 (void)tria_level;
2191 (void)true_dimension;
2192 Assert(2 * true_dimension * tria_level.refine_flags.size() ==
2193 tria_level.neighbors.size(),
2194 ExcMemoryInexact(tria_level.refine_flags.size(),
2195 tria_level.neighbors.size()));
2196 Assert(2 * true_dimension * tria_level.coarsen_flags.size() ==
2197 tria_level.neighbors.size(),
2198 ExcMemoryInexact(tria_level.coarsen_flags.size(),
2199 tria_level.neighbors.size()));
2200 }
2201
2202
2203
2216 void
2218 const unsigned int new_objects_in_pairs,
2219 const unsigned int new_objects_single = 0)
2220 {
2221 if (tria_objects.structdim <= 2)
2222 {
2223 Assert(new_objects_in_pairs % 2 == 0, ExcInternalError());
2224
2225 tria_objects.next_free_single = 0;
2226 tria_objects.next_free_pair = 0;
2227 tria_objects.reverse_order_next_free_single = false;
2228
2229 // count the number of objects, of unused single objects and of
2230 // unused pairs of objects
2231 unsigned int n_objects = 0;
2232 unsigned int n_unused_pairs = 0;
2233 unsigned int n_unused_singles = 0;
2234 for (unsigned int i = 0; i < tria_objects.used.size(); ++i)
2235 {
2236 if (tria_objects.used[i])
2237 ++n_objects;
2238 else if (i + 1 < tria_objects.used.size())
2239 {
2240 if (tria_objects.used[i + 1])
2241 {
2242 ++n_unused_singles;
2243 if (tria_objects.next_free_single == 0)
2244 tria_objects.next_free_single = i;
2245 }
2246 else
2247 {
2248 ++n_unused_pairs;
2249 if (tria_objects.next_free_pair == 0)
2250 tria_objects.next_free_pair = i;
2251 ++i;
2252 }
2253 }
2254 else
2255 ++n_unused_singles;
2256 }
2257 Assert(n_objects + 2 * n_unused_pairs + n_unused_singles ==
2258 tria_objects.used.size(),
2260 (void)n_objects;
2261
2262 // how many single objects are needed in addition to
2263 // n_unused_objects?
2264 const int additional_single_objects =
2265 new_objects_single - n_unused_singles;
2266
2267 unsigned int new_size = tria_objects.used.size() +
2268 new_objects_in_pairs - 2 * n_unused_pairs;
2269 if (additional_single_objects > 0)
2270 new_size += additional_single_objects;
2271
2272 // only allocate space if necessary
2273 if (new_size > tria_objects.n_objects())
2274 {
2275 const unsigned int max_faces_per_cell =
2276 2 * tria_objects.structdim;
2277 const unsigned int max_children_per_cell =
2278 1 << tria_objects.structdim;
2279
2280 tria_objects.cells.reserve(new_size * max_faces_per_cell);
2281 tria_objects.cells.insert(tria_objects.cells.end(),
2282 (new_size - tria_objects.n_objects()) *
2283 max_faces_per_cell,
2284 -1);
2285
2286 tria_objects.used.reserve(new_size);
2287 tria_objects.used.insert(tria_objects.used.end(),
2288 new_size - tria_objects.used.size(),
2289 false);
2290
2291 tria_objects.user_flags.reserve(new_size);
2292 tria_objects.user_flags.insert(tria_objects.user_flags.end(),
2293 new_size -
2294 tria_objects.user_flags.size(),
2295 false);
2296
2297 const unsigned int factor = max_children_per_cell / 2;
2298 tria_objects.children.reserve(factor * new_size);
2299 tria_objects.children.insert(tria_objects.children.end(),
2300 factor * new_size -
2301 tria_objects.children.size(),
2302 -1);
2303
2304 if (tria_objects.structdim > 1)
2305 {
2306 tria_objects.refinement_cases.reserve(new_size);
2307 tria_objects.refinement_cases.insert(
2308 tria_objects.refinement_cases.end(),
2309 new_size - tria_objects.refinement_cases.size(),
2310 /*RefinementCase::no_refinement=*/0);
2311 }
2312
2313 // first reserve, then resize. Otherwise the std library can
2314 // decide to allocate more entries.
2315 tria_objects.boundary_or_material_id.reserve(new_size);
2316 tria_objects.boundary_or_material_id.resize(new_size);
2317
2318 tria_objects.user_data.reserve(new_size);
2319 tria_objects.user_data.resize(new_size);
2320
2321 tria_objects.manifold_id.reserve(new_size);
2322 tria_objects.manifold_id.insert(tria_objects.manifold_id.end(),
2323 new_size -
2324 tria_objects.manifold_id.size(),
2326 }
2327
2328 if (n_unused_singles == 0)
2329 {
2330 tria_objects.next_free_single = new_size - 1;
2331 tria_objects.reverse_order_next_free_single = true;
2332 }
2333 }
2334 else
2335 {
2336 const unsigned int new_hexes = new_objects_in_pairs;
2337
2338 const unsigned int new_size =
2339 new_hexes + std::count(tria_objects.used.begin(),
2340 tria_objects.used.end(),
2341 true);
2342
2343 // see above...
2344 if (new_size > tria_objects.n_objects())
2345 {
2346 const unsigned int max_faces_per_cell =
2347 2 * tria_objects.structdim;
2348
2349 tria_objects.cells.reserve(new_size * max_faces_per_cell);
2350 tria_objects.cells.insert(tria_objects.cells.end(),
2351 (new_size - tria_objects.n_objects()) *
2352 max_faces_per_cell,
2353 -1);
2354
2355 tria_objects.used.reserve(new_size);
2356 tria_objects.used.insert(tria_objects.used.end(),
2357 new_size - tria_objects.used.size(),
2358 false);
2359
2360 tria_objects.user_flags.reserve(new_size);
2361 tria_objects.user_flags.insert(tria_objects.user_flags.end(),
2362 new_size -
2363 tria_objects.user_flags.size(),
2364 false);
2365
2366 tria_objects.children.reserve(4 * new_size);
2367 tria_objects.children.insert(tria_objects.children.end(),
2368 4 * new_size -
2369 tria_objects.children.size(),
2370 -1);
2371
2372 // for the following fields, we know exactly how many elements
2373 // we need, so first reserve then resize (resize itself, at least
2374 // with some compiler libraries, appears to round up the size it
2375 // actually reserves)
2376 tria_objects.boundary_or_material_id.reserve(new_size);
2377 tria_objects.boundary_or_material_id.resize(new_size);
2378
2379 tria_objects.manifold_id.reserve(new_size);
2380 tria_objects.manifold_id.insert(tria_objects.manifold_id.end(),
2381 new_size -
2382 tria_objects.manifold_id.size(),
2384
2385 tria_objects.user_data.reserve(new_size);
2386 tria_objects.user_data.resize(new_size);
2387
2388 tria_objects.refinement_cases.reserve(new_size);
2389 tria_objects.refinement_cases.insert(
2390 tria_objects.refinement_cases.end(),
2391 new_size - tria_objects.refinement_cases.size(),
2392 /*RefinementCase::no_refinement=*/0);
2393 }
2394 tria_objects.next_free_single = tria_objects.next_free_pair = 0;
2395 }
2396 }
2397
2398
2399
2405 void
2406 monitor_memory(const TriaObjects &tria_object, const unsigned int)
2407 {
2408 Assert(tria_object.n_objects() == tria_object.used.size(),
2409 ExcMemoryInexact(tria_object.n_objects(),
2410 tria_object.used.size()));
2411 Assert(tria_object.n_objects() == tria_object.user_flags.size(),
2412 ExcMemoryInexact(tria_object.n_objects(),
2413 tria_object.user_flags.size()));
2414 Assert(tria_object.n_objects() ==
2415 tria_object.boundary_or_material_id.size(),
2416 ExcMemoryInexact(tria_object.n_objects(),
2417 tria_object.boundary_or_material_id.size()));
2418 Assert(tria_object.n_objects() == tria_object.manifold_id.size(),
2419 ExcMemoryInexact(tria_object.n_objects(),
2420 tria_object.manifold_id.size()));
2421 Assert(tria_object.n_objects() == tria_object.user_data.size(),
2422 ExcMemoryInexact(tria_object.n_objects(),
2423 tria_object.user_data.size()));
2424
2425 if (tria_object.structdim == 1)
2426 {
2427 Assert(1 * tria_object.n_objects() == tria_object.children.size(),
2428 ExcMemoryInexact(tria_object.n_objects(),
2429 tria_object.children.size()));
2430 }
2431 else if (tria_object.structdim == 2)
2432 {
2433 Assert(2 * tria_object.n_objects() == tria_object.children.size(),
2434 ExcMemoryInexact(tria_object.n_objects(),
2435 tria_object.children.size()));
2436 }
2437 else if (tria_object.structdim == 3)
2438 {
2439 Assert(4 * tria_object.n_objects() == tria_object.children.size(),
2440 ExcMemoryInexact(tria_object.n_objects(),
2441 tria_object.children.size()));
2442 }
2443 }
2444
2445
2446
2451 template <int dim, int spacedim>
2453 {
2454 public:
2458 virtual ~Policy() = default;
2459
2463 virtual void
2465
2469 virtual void
2473 std::vector<unsigned int> &line_cell_count,
2474 std::vector<unsigned int> &quad_cell_count) = 0;
2475
2481 const bool check_for_distorted_cells) = 0;
2482
2486 virtual void
2489
2493 virtual void
2496
2500 virtual bool
2502 const typename Triangulation<dim, spacedim>::cell_iterator &cell) = 0;
2503
2510 virtual std::unique_ptr<Policy<dim, spacedim>>
2511 clone() = 0;
2512 };
2513
2514
2515
2521 template <int dim, int spacedim, typename T>
2522 class PolicyWrapper : public Policy<dim, spacedim>
2523 {
2524 public:
2525 void
2527 {
2528 T::update_neighbors(tria);
2529 }
2530
2531 void
2535 std::vector<unsigned int> &line_cell_count,
2536 std::vector<unsigned int> &quad_cell_count) override
2537 {
2538 T::delete_children(tria, cell, line_cell_count, quad_cell_count);
2539 }
2540
2543 const bool check_for_distorted_cells) override
2544 {
2545 return T::execute_refinement(triangulation, check_for_distorted_cells);
2546 }
2547
2548 void
2551 {
2552 T::prevent_distorted_boundary_cells(triangulation);
2553 }
2554
2555 void
2558 {
2559 T::prepare_refinement_dim_dependent(triangulation);
2560 }
2561
2562 bool
2565 override
2566 {
2567 return T::template coarsening_allowed<dim, spacedim>(cell);
2568 }
2569
2570 std::unique_ptr<Policy<dim, spacedim>>
2571 clone() override
2572 {
2573 return std::make_unique<PolicyWrapper<dim, spacedim, T>>();
2574 }
2575 };
2576
2577
2578
2675 {
2687 template <int dim, int spacedim>
2688 static void
2691 const unsigned int level_objects,
2693 {
2694 using line_iterator =
2696
2697 number_cache.n_levels = 0;
2698 if (level_objects > 0)
2699 // find the last level on which there are used cells
2700 for (unsigned int level = 0; level < level_objects; ++level)
2701 if (triangulation.begin(level) != triangulation.end(level))
2702 number_cache.n_levels = level + 1;
2703
2704 // no cells at all?
2705 Assert(number_cache.n_levels > 0, ExcInternalError());
2706
2707 //---------------------------------
2708 // update the number of lines on the different levels in the
2709 // cache
2710 number_cache.n_lines = 0;
2711 number_cache.n_active_lines = 0;
2712
2713 // for 1d, lines have levels so take count the objects per
2714 // level and globally
2715 if (dim == 1)
2716 {
2717 number_cache.n_lines_level.resize(number_cache.n_levels);
2718 number_cache.n_active_lines_level.resize(number_cache.n_levels);
2719
2720 for (unsigned int level = 0; level < number_cache.n_levels; ++level)
2721 {
2722 // count lines on this level
2723 number_cache.n_lines_level[level] = 0;
2724 number_cache.n_active_lines_level[level] = 0;
2725
2726 line_iterator line = triangulation.begin_line(level),
2727 endc =
2728 (level == number_cache.n_levels - 1 ?
2729 line_iterator(triangulation.end_line()) :
2730 triangulation.begin_line(level + 1));
2731 for (; line != endc; ++line)
2732 {
2733 ++number_cache.n_lines_level[level];
2734 if (line->has_children() == false)
2735 ++number_cache.n_active_lines_level[level];
2736 }
2737
2738 // update total number of lines
2739 number_cache.n_lines += number_cache.n_lines_level[level];
2740 number_cache.n_active_lines +=
2741 number_cache.n_active_lines_level[level];
2742 }
2743 }
2744 else
2745 {
2746 // for dim>1, there are no levels for lines
2747 number_cache.n_lines_level.clear();
2748 number_cache.n_active_lines_level.clear();
2749
2750 line_iterator line = triangulation.begin_line(),
2751 endc = triangulation.end_line();
2752 for (; line != endc; ++line)
2753 {
2754 ++number_cache.n_lines;
2755 if (line->has_children() == false)
2756 ++number_cache.n_active_lines;
2757 }
2758 }
2759 }
2760
2775 template <int dim, int spacedim>
2776 static void
2779 const unsigned int level_objects,
2781 {
2782 // update lines and n_levels in number_cache. since we don't
2783 // access any of these numbers, we can do this in the
2784 // background
2786 static_cast<
2787 void (*)(const Triangulation<dim, spacedim> &,
2788 const unsigned int,
2790 &compute_number_cache_dim<dim, spacedim>),
2792 level_objects,
2794 number_cache));
2795
2796 using quad_iterator =
2798
2799 //---------------------------------
2800 // update the number of quads on the different levels in the
2801 // cache
2802 number_cache.n_quads = 0;
2803 number_cache.n_active_quads = 0;
2804
2805 // for 2d, quads have levels so take count the objects per
2806 // level and globally
2807 if (dim == 2)
2808 {
2809 // count the number of levels; the function we called above
2810 // on a separate Task for lines also does this and puts it into
2811 // number_cache.n_levels, but this datum may not yet be
2812 // available as we call the function on a separate task
2813 unsigned int n_levels = 0;
2814 if (level_objects > 0)
2815 // find the last level on which there are used cells
2816 for (unsigned int level = 0; level < level_objects; ++level)
2817 if (triangulation.begin(level) != triangulation.end(level))
2818 n_levels = level + 1;
2819
2820 number_cache.n_quads_level.resize(n_levels);
2821 number_cache.n_active_quads_level.resize(n_levels);
2822
2823 for (unsigned int level = 0; level < n_levels; ++level)
2824 {
2825 // count quads on this level
2826 number_cache.n_quads_level[level] = 0;
2827 number_cache.n_active_quads_level[level] = 0;
2828
2829 quad_iterator quad = triangulation.begin_quad(level),
2830 endc =
2831 (level == n_levels - 1 ?
2832 quad_iterator(triangulation.end_quad()) :
2833 triangulation.begin_quad(level + 1));
2834 for (; quad != endc; ++quad)
2835 {
2836 ++number_cache.n_quads_level[level];
2837 if (quad->has_children() == false)
2838 ++number_cache.n_active_quads_level[level];
2839 }
2840
2841 // update total number of quads
2842 number_cache.n_quads += number_cache.n_quads_level[level];
2843 number_cache.n_active_quads +=
2844 number_cache.n_active_quads_level[level];
2845 }
2846 }
2847 else
2848 {
2849 // for dim>2, there are no levels for quads
2850 number_cache.n_quads_level.clear();
2851 number_cache.n_active_quads_level.clear();
2852
2853 quad_iterator quad = triangulation.begin_quad(),
2854 endc = triangulation.end_quad();
2855 for (; quad != endc; ++quad)
2856 {
2857 ++number_cache.n_quads;
2858 if (quad->has_children() == false)
2859 ++number_cache.n_active_quads;
2860 }
2861 }
2862
2863 // wait for the background computation for lines
2864 update_lines.join();
2865 }
2866
2882 template <int dim, int spacedim>
2883 static void
2886 const unsigned int level_objects,
2888 {
2889 // update quads, lines and n_levels in number_cache. since we
2890 // don't access any of these numbers, we can do this in the
2891 // background
2892 Threads::Task<void> update_quads_and_lines = Threads::new_task(
2893 static_cast<
2894 void (*)(const Triangulation<dim, spacedim> &,
2895 const unsigned int,
2897 &compute_number_cache_dim<dim, spacedim>),
2899 level_objects,
2901 number_cache));
2902
2903 using hex_iterator =
2905
2906 //---------------------------------
2907 // update the number of hexes on the different levels in the
2908 // cache
2909 number_cache.n_hexes = 0;
2910 number_cache.n_active_hexes = 0;
2911
2912 // for 3d, hexes have levels so take count the objects per
2913 // level and globally
2914 if (dim == 3)
2915 {
2916 // count the number of levels; the function we called
2917 // above on a separate Task for quads (recursively, via
2918 // the lines function) also does this and puts it into
2919 // number_cache.n_levels, but this datum may not yet be
2920 // available as we call the function on a separate task
2921 unsigned int n_levels = 0;
2922 if (level_objects > 0)
2923 // find the last level on which there are used cells
2924 for (unsigned int level = 0; level < level_objects; ++level)
2925 if (triangulation.begin(level) != triangulation.end(level))
2926 n_levels = level + 1;
2927
2928 number_cache.n_hexes_level.resize(n_levels);
2929 number_cache.n_active_hexes_level.resize(n_levels);
2930
2931 for (unsigned int level = 0; level < n_levels; ++level)
2932 {
2933 // count hexes on this level
2934 number_cache.n_hexes_level[level] = 0;
2935 number_cache.n_active_hexes_level[level] = 0;
2936
2937 hex_iterator hex = triangulation.begin_hex(level),
2938 endc = (level == n_levels - 1 ?
2939 hex_iterator(triangulation.end_hex()) :
2940 triangulation.begin_hex(level + 1));
2941 for (; hex != endc; ++hex)
2942 {
2943 ++number_cache.n_hexes_level[level];
2944 if (hex->has_children() == false)
2945 ++number_cache.n_active_hexes_level[level];
2946 }
2947
2948 // update total number of hexes
2949 number_cache.n_hexes += number_cache.n_hexes_level[level];
2950 number_cache.n_active_hexes +=
2951 number_cache.n_active_hexes_level[level];
2952 }
2953 }
2954 else
2955 {
2956 // for dim>3, there are no levels for hexes
2957 number_cache.n_hexes_level.clear();
2958 number_cache.n_active_hexes_level.clear();
2959
2960 hex_iterator hex = triangulation.begin_hex(),
2961 endc = triangulation.end_hex();
2962 for (; hex != endc; ++hex)
2963 {
2964 ++number_cache.n_hexes;
2965 if (hex->has_children() == false)
2966 ++number_cache.n_active_hexes;
2967 }
2968 }
2969
2970 // wait for the background computation for quads
2971 update_quads_and_lines.join();
2972 }
2973
2974
2975 template <int dim, int spacedim>
2976 static void
2979 const unsigned int level_objects,
2981 {
2982 compute_number_cache_dim(triangulation, level_objects, number_cache);
2983
2984 number_cache.active_cell_index_partitioner =
2985 std::make_shared<const Utilities::MPI::Partitioner>(
2986 triangulation.n_active_cells());
2987
2988 number_cache.level_cell_index_partitioners.resize(
2989 triangulation.n_levels());
2990 for (unsigned int level = 0; level < triangulation.n_levels(); ++level)
2991 number_cache.level_cell_index_partitioners[level] =
2992 std::make_shared<const Utilities::MPI::Partitioner>(
2993 triangulation.n_cells(level));
2994 }
2995
2996
2997 template <int spacedim>
2998 static void
3001
3002
3003 template <int dim, int spacedim>
3004 static void
3006 {
3007 // each face can be neighbored on two sides
3008 // by cells. according to the face's
3009 // intrinsic normal we define the left
3010 // neighbor as the one for which the face
3011 // normal points outward, and store that
3012 // one first; the second one is then
3013 // the right neighbor for which the
3014 // face normal points inward. This
3015 // information depends on the type of cell
3016 // and local number of face for the
3017 // 'standard ordering and orientation' of
3018 // faces and then on the face_orientation
3019 // information for the real mesh. Set up a
3020 // table to have fast access to those
3021 // offsets (0 for left and 1 for
3022 // right). Some of the values are invalid
3023 // as they reference too large face
3024 // numbers, but we just leave them at a
3025 // zero value.
3026 //
3027 // Note, that in 2d for lines as faces the
3028 // normal direction given in the
3029 // GeometryInfo class is not consistent. We
3030 // thus define here that the normal for a
3031 // line points to the right if the line
3032 // points upwards.
3033 //
3034 // There is one more point to
3035 // consider, however: if we have
3036 // dim<spacedim, then we may have
3037 // cases where cells are
3038 // inverted. In effect, both
3039 // cells think they are the left
3040 // neighbor of an edge, for
3041 // example, which leads us to
3042 // forget neighborship
3043 // information (a case that shows
3044 // this is
3045 // codim_one/hanging_nodes_02). We
3046 // store whether a cell is
3047 // inverted using the
3048 // direction_flag, so if a cell
3049 // has a false direction_flag,
3050 // then we need to invert our
3051 // selection whether we are a
3052 // left or right neighbor in all
3053 // following computations.
3054 //
3055 // first index: dimension (minus 2)
3056 // second index: local face index
3057 // third index: face_orientation (false and true)
3058 static const unsigned int left_right_offset[2][6][2] = {
3059 // quadrilateral
3060 {{0, 1}, // face 0, face_orientation = false and true
3061 {1, 0}, // face 1, face_orientation = false and true
3062 {1, 0}, // face 2, face_orientation = false and true
3063 {0, 1}, // face 3, face_orientation = false and true
3064 {0, 0}, // face 4, invalid face
3065 {0, 0}}, // face 5, invalid face
3066 // hexahedron
3067 {{0, 1}, {1, 0}, {0, 1}, {1, 0}, {0, 1}, {1, 0}}};
3068
3069 // now create a vector of the two active
3070 // neighbors (left and right) for each face
3071 // and fill it by looping over all cells. For
3072 // cases with anisotropic refinement and more
3073 // then one cell neighboring at a given side
3074 // of the face we will automatically get the
3075 // active one on the highest level as we loop
3076 // over cells from lower levels first.
3078 std::vector<typename Triangulation<dim, spacedim>::cell_iterator>
3079 adjacent_cells(2 * triangulation.n_raw_faces(), dummy);
3080
3081 for (const auto &cell : triangulation.cell_iterators())
3082 for (auto f : cell->face_indices())
3083 {
3085 cell->face(f);
3086
3087 const unsigned int offset =
3088 (cell->direction_flag() ?
3089 left_right_offset[dim - 2][f][cell->face_orientation(f)] :
3090 1 -
3091 left_right_offset[dim - 2][f][cell->face_orientation(f)]);
3092
3093 adjacent_cells[2 * face->index() + offset] = cell;
3094
3095 // if this cell is not refined, but the
3096 // face is, then we'll have to set our
3097 // cell as neighbor for the child faces
3098 // as well. Fortunately the normal
3099 // orientation of children will be just
3100 // the same.
3101 if (dim == 2)
3102 {
3103 if (cell->is_active() && face->has_children())
3104 {
3105 adjacent_cells[2 * face->child(0)->index() + offset] =
3106 cell;
3107 adjacent_cells[2 * face->child(1)->index() + offset] =
3108 cell;
3109 }
3110 }
3111 else // -> dim == 3
3112 {
3113 // We need the same as in 2d
3114 // here. Furthermore, if the face is
3115 // refined with cut_x or cut_y then
3116 // those children again in the other
3117 // direction, and if this cell is
3118 // refined isotropically (along the
3119 // face) then the neighbor will
3120 // (probably) be refined as cut_x or
3121 // cut_y along the face. For those
3122 // neighboring children cells, their
3123 // neighbor will be the current,
3124 // inactive cell, as our children are
3125 // too fine to be neighbors. Catch that
3126 // case by also acting on inactive
3127 // cells with isotropic refinement
3128 // along the face. If the situation
3129 // described is not present, the data
3130 // will be overwritten later on when we
3131 // visit cells on finer levels, so no
3132 // harm will be done.
3133 if (face->has_children() &&
3134 (cell->is_active() ||
3136 cell->refinement_case(), f) ==
3137 RefinementCase<dim - 1>::isotropic_refinement))
3138 {
3139 for (unsigned int c = 0; c < face->n_children(); ++c)
3140 adjacent_cells[2 * face->child(c)->index() + offset] =
3141 cell;
3142 if (face->child(0)->has_children())
3143 {
3144 adjacent_cells[2 * face->child(0)->child(0)->index() +
3145 offset] = cell;
3146 adjacent_cells[2 * face->child(0)->child(1)->index() +
3147 offset] = cell;
3148 }
3149 if (face->child(1)->has_children())
3150 {
3151 adjacent_cells[2 * face->child(1)->child(0)->index() +
3152 offset] = cell;
3153 adjacent_cells[2 * face->child(1)->child(1)->index() +
3154 offset] = cell;
3155 }
3156 } // if cell active and face refined
3157 } // else -> dim==3
3158 } // for all faces of all cells
3159
3160 // now loop again over all cells and set the
3161 // corresponding neighbor cell. Note, that we
3162 // have to use the opposite of the
3163 // left_right_offset in this case as we want
3164 // the offset of the neighbor, not our own.
3165 for (const auto &cell : triangulation.cell_iterators())
3166 for (auto f : cell->face_indices())
3167 {
3168 const unsigned int offset =
3169 (cell->direction_flag() ?
3170 left_right_offset[dim - 2][f][cell->face_orientation(f)] :
3171 1 -
3172 left_right_offset[dim - 2][f][cell->face_orientation(f)]);
3173 cell->set_neighbor(
3174 f, adjacent_cells[2 * cell->face(f)->index() + 1 - offset]);
3175 }
3176 }
3177
3178
3182 template <int dim, int spacedim>
3183 static void
3185 const std::vector<CellData<dim>> &cells,
3186 const SubCellData &subcelldata,
3188 {
3189 AssertThrow(vertices.size() > 0, ExcMessage("No vertices given"));
3190 AssertThrow(cells.size() > 0, ExcMessage("No cells given"));
3191
3192 // Check that all cells have positive volume.
3193#ifndef _MSC_VER
3194 // TODO: The following code does not compile with MSVC. Find a way
3195 // around it
3196 if (dim == spacedim)
3197 for (unsigned int cell_no = 0; cell_no < cells.size(); ++cell_no)
3198 {
3199 // If we should check for distorted cells, then we permit them
3200 // to exist. If a cell has negative measure, then it must be
3201 // distorted (the converse is not necessarily true); hence
3202 // throw an exception if no such cells should exist.
3204 {
3205 const double cell_measure = GridTools::cell_measure<spacedim>(
3206 vertices,
3207 ArrayView<const unsigned int>(cells[cell_no].vertices));
3208 AssertThrow(cell_measure > 0, ExcGridHasInvalidCell(cell_no));
3209 }
3210 }
3211#endif
3212
3213 // clear old content
3214 tria.levels.clear();
3215 tria.levels.push_back(
3216 std::make_unique<
3218
3219 if (dim > 1)
3220 tria.faces = std::make_unique<
3222
3223 // copy vertices
3224 tria.vertices = vertices;
3225 tria.vertices_used.assign(vertices.size(), true);
3226
3227 // compute connectivity
3228 const auto connectivity = build_connectivity<unsigned int>(cells);
3229 const unsigned int n_cell = cells.size();
3230
3231 // TriaObjects: lines
3232 if (dim >= 2)
3233 {
3234 auto &lines_0 = tria.faces->lines; // data structure to be filled
3235
3236 // get connectivity between quads and lines
3237 const auto &crs = connectivity.entity_to_entities(1, 0);
3238 const unsigned int n_lines = crs.ptr.size() - 1;
3239
3240 // allocate memory
3241 reserve_space_(lines_0, n_lines);
3242
3243 // loop over lines
3244 for (unsigned int line = 0; line < n_lines; ++line)
3245 for (unsigned int i = crs.ptr[line], j = 0; i < crs.ptr[line + 1];
3246 ++i, ++j)
3247 lines_0.cells[line * GeometryInfo<1>::faces_per_cell + j] =
3248 crs.col[i]; // set vertex indices
3249 }
3250
3251 // TriaObjects: quads
3252 if (dim == 3)
3253 {
3254 auto &quads_0 = tria.faces->quads; // data structures to be filled
3255 auto &faces = *tria.faces;
3256
3257 // get connectivity between quads and lines
3258 const auto &crs = connectivity.entity_to_entities(2, 1);
3259 const unsigned int n_quads = crs.ptr.size() - 1;
3260
3261 // allocate memory
3262 reserve_space_(quads_0, n_quads);
3263 reserve_space_(faces, 2 /*structdim*/, n_quads);
3264
3265 // loop over all quads -> entity type, line indices/orientations
3266 for (unsigned int q = 0, k = 0; q < n_quads; ++q)
3267 {
3268 // set entity type of quads
3269 faces.set_quad_type(q, connectivity.entity_types(2)[q]);
3270
3271 // loop over all its lines
3272 for (unsigned int i = crs.ptr[q], j = 0; i < crs.ptr[q + 1];
3273 ++i, ++j, ++k)
3274 {
3275 // set line index
3276 quads_0.cells[q * GeometryInfo<3>::lines_per_face + j] =
3277 crs.col[i];
3278
3279 // set line orientations
3280 const unsigned char combined_orientation =
3281 connectivity.entity_orientations(1)
3282 .get_combined_orientation(k);
3283 // it doesn't make sense to set any flags except
3284 // orientation for a line
3285 Assert(
3286 combined_orientation ==
3288 combined_orientation ==
3291 faces.quads_line_orientations
3293 combined_orientation ==
3295 }
3296 }
3297 }
3298
3299 // TriaObjects/TriaLevel: cell
3300 {
3301 auto &cells_0 = tria.levels[0]->cells; // data structure to be filled
3302 auto &level = *tria.levels[0];
3303
3304 // get connectivity between cells/faces and cells/cells
3305 const auto &crs = connectivity.entity_to_entities(dim, dim - 1);
3306 const auto &nei = connectivity.entity_to_entities(dim, dim);
3307
3308 // in 2d optional: since in in pure QUAD meshes same line
3309 // orientations can be guaranteed
3310 bool orientation_needed = false;
3311 if (dim == 3)
3312 orientation_needed = true;
3313 else if (dim == 2)
3314 {
3315 const auto &orientations = connectivity.entity_orientations(1);
3316 for (unsigned int i = 0; i < orientations.n_objects(); ++i)
3317 if (orientations.get_combined_orientation(i) !=
3319 {
3320 orientation_needed = true;
3321 break;
3322 }
3323 }
3324
3325 // allocate memory
3326 reserve_space_(cells_0, n_cell);
3327 reserve_space_(level, spacedim, n_cell, orientation_needed);
3328
3329 // loop over all cells
3330 for (unsigned int cell = 0; cell < n_cell; ++cell)
3331 {
3332 // set material ids
3333 cells_0.boundary_or_material_id[cell].material_id =
3334 cells[cell].material_id;
3335
3336 // set manifold ids
3337 cells_0.manifold_id[cell] = cells[cell].manifold_id;
3338
3339 // set entity types
3340 level.reference_cell[cell] = connectivity.entity_types(dim)[cell];
3341
3342 // loop over faces
3343 for (unsigned int i = crs.ptr[cell], j = 0; i < crs.ptr[cell + 1];
3344 ++i, ++j)
3345 {
3346 // set neighbor if not at boundary
3347 if (nei.col[i] != static_cast<unsigned int>(-1))
3348 level.neighbors[cell * GeometryInfo<dim>::faces_per_cell +
3349 j] = {0, nei.col[i]};
3350
3351 // set face indices
3352 cells_0.cells[cell * GeometryInfo<dim>::faces_per_cell + j] =
3353 crs.col[i];
3354
3355 // set face orientation if needed
3356 if (orientation_needed)
3357 {
3358 level.face_orientations.set_combined_orientation(
3360 connectivity.entity_orientations(dim - 1)
3361 .get_combined_orientation(i));
3362 }
3363 }
3364 }
3365 }
3366
3367 // TriaFaces: boundary id of boundary faces
3368 if (dim > 1)
3369 {
3370 auto &bids_face = dim == 3 ?
3371 tria.faces->quads.boundary_or_material_id :
3372 tria.faces->lines.boundary_or_material_id;
3373
3374 // count number of cells a face is belonging to
3375 std::vector<unsigned int> count(bids_face.size(), 0);
3376
3377 // get connectivity between cells/faces
3378 const auto &crs = connectivity.entity_to_entities(dim, dim - 1);
3379
3380 // count how many cells are adjacent to the same face
3381 for (unsigned int cell = 0; cell < cells.size(); ++cell)
3382 for (unsigned int i = crs.ptr[cell]; i < crs.ptr[cell + 1]; ++i)
3383 count[crs.col[i]]++;
3384
3385 // loop over all faces
3386 for (unsigned int face = 0; face < count.size(); ++face)
3387 {
3388 if (count[face] != 1) // inner face
3389 continue;
3390
3391 // boundary faces ...
3392 bids_face[face].boundary_id = 0;
3393
3394 if (dim != 3)
3395 continue;
3396
3397 // ... and the lines of quads in 3d
3398 const auto &crs = connectivity.entity_to_entities(2, 1);
3399 for (unsigned int i = crs.ptr[face]; i < crs.ptr[face + 1]; ++i)
3400 tria.faces->lines.boundary_or_material_id[crs.col[i]]
3401 .boundary_id = 0;
3402 }
3403 }
3404 else // 1d
3405 {
3406 static const unsigned int t_tba = static_cast<unsigned int>(-1);
3407 static const unsigned int t_inner = static_cast<unsigned int>(-2);
3408
3409 std::vector<unsigned int> type(vertices.size(), t_tba);
3410
3411 const auto &crs = connectivity.entity_to_entities(1, 0);
3412
3413 for (unsigned int cell = 0; cell < cells.size(); ++cell)
3414 for (unsigned int i = crs.ptr[cell], j = 0; i < crs.ptr[cell + 1];
3415 ++i, ++j)
3416 if (type[crs.col[i]] != t_inner)
3417 type[crs.col[i]] = type[crs.col[i]] == t_tba ? j : t_inner;
3418
3419 for (unsigned int face = 0; face < type.size(); ++face)
3420 {
3421 // note: we also treat manifolds here!?
3422 (*tria.vertex_to_manifold_id_map_1d)[face] =
3424 if (type[face] != t_inner && type[face] != t_tba)
3425 (*tria.vertex_to_boundary_id_map_1d)[face] = type[face];
3426 }
3427 }
3428
3429 // SubCellData: line
3430 if (dim >= 2)
3431 process_subcelldata(connectivity.entity_to_entities(1, 0),
3432 tria.faces->lines,
3433 subcelldata.boundary_lines,
3434 vertices);
3435
3436 // SubCellData: quad
3437 if (dim == 3)
3438 process_subcelldata(connectivity.entity_to_entities(2, 0),
3439 tria.faces->quads,
3440 subcelldata.boundary_quads,
3441 vertices);
3442 }
3443
3444
3445 template <int structdim, int spacedim, typename T>
3446 static void
3448 const CRS<T> &crs,
3449 TriaObjects &obj,
3450 const std::vector<CellData<structdim>> &boundary_objects_in,
3451 const std::vector<Point<spacedim>> &vertex_locations)
3452 {
3453 AssertDimension(obj.structdim, structdim);
3454
3455 if (boundary_objects_in.empty())
3456 return; // empty subcelldata -> nothing to do
3457
3458 // pre-sort subcelldata
3459 auto boundary_objects = boundary_objects_in;
3460
3461 // ... sort vertices
3462 for (auto &boundary_object : boundary_objects)
3463 std::sort(boundary_object.vertices.begin(),
3464 boundary_object.vertices.end());
3465
3466 // ... sort cells
3467 std::sort(boundary_objects.begin(),
3468 boundary_objects.end(),
3469 [](const auto &a, const auto &b) {
3470 return a.vertices < b.vertices;
3471 });
3472
3473 unsigned int counter = 0;
3474
3475 std::vector<unsigned int> key;
3477
3478 for (unsigned int o = 0; o < obj.n_objects(); ++o)
3479 {
3480 auto &boundary_id = obj.boundary_or_material_id[o].boundary_id;
3481 auto &manifold_id = obj.manifold_id[o];
3482
3483 // assert that object has not been visited yet and its value
3484 // has not been modified yet
3485 AssertThrow(boundary_id == 0 ||
3490
3491 // create key
3492 key.assign(crs.col.data() + crs.ptr[o],
3493 crs.col.data() + crs.ptr[o + 1]);
3494 std::sort(key.begin(), key.end());
3495
3496 // is subcelldata provided? -> binary search
3497 const auto subcell_object =
3498 std::lower_bound(boundary_objects.begin(),
3499 boundary_objects.end(),
3500 key,
3501 [&](const auto &cell, const auto &key) {
3502 return cell.vertices < key;
3503 });
3504
3505 // no subcelldata provided for this object
3506 if (subcell_object == boundary_objects.end() ||
3507 subcell_object->vertices != key)
3508 continue;
3509
3510 ++counter;
3511
3512 // set manifold id
3513 manifold_id = subcell_object->manifold_id;
3514
3515 // set boundary id
3516 if (subcell_object->boundary_id !=
3518 {
3519 (void)vertex_locations;
3522 ExcMessage(
3523 "The input arguments for creating a triangulation "
3524 "specified a boundary id for an internal face. This "
3525 "is not allowed."
3526 "\n\n"
3527 "The object in question has vertex indices " +
3528 [subcell_object]() {
3529 std::string s;
3530 for (const auto v : subcell_object->vertices)
3531 s += std::to_string(v) + ',';
3532 return s;
3533 }() +
3534 " which are located at positions " +
3535 [vertex_locations, subcell_object]() {
3536 std::ostringstream s;
3537 for (const auto v : subcell_object->vertices)
3538 s << '(' << vertex_locations[v] << ')';
3539 return s.str();
3540 }() +
3541 "."));
3542 boundary_id = subcell_object->boundary_id;
3543 }
3544 }
3545
3546 // make sure that all subcelldata entries have been processed
3547 // TODO: this is not guaranteed, why?
3548 // AssertDimension(counter, boundary_objects_in.size());
3549 (void)counter;
3550 }
3551
3552
3553
3554 static void
3556 const unsigned structdim,
3557 const unsigned int size)
3558 {
3559 const unsigned int dim = faces.dim;
3560
3561 const unsigned int max_lines_per_face = 2 * structdim;
3562
3563 if (dim == 3 && structdim == 2)
3564 {
3565 // quad entity types
3566 faces.quad_is_quadrilateral.assign(size, true);
3567
3568 // quad line orientations
3569 faces.quads_line_orientations.assign(size * max_lines_per_face,
3570 true);
3571 }
3572 }
3573
3574
3575
3576 static void
3578 const unsigned int spacedim,
3579 const unsigned int size,
3580 const bool orientation_needed)
3581 {
3582 const unsigned int dim = level.dim;
3583
3584 const unsigned int max_faces_per_cell = 2 * dim;
3585
3586 level.active_cell_indices.assign(size, numbers::invalid_unsigned_int);
3587 level.subdomain_ids.assign(size, 0);
3588 level.level_subdomain_ids.assign(size, 0);
3589
3590 level.refine_flags.assign(size, 0u);
3591 level.coarsen_flags.assign(size, false);
3592
3593 level.parents.assign((size + 1) / 2, -1);
3594
3595 if (dim == spacedim - 1)
3596 level.direction_flags.assign(size, true);
3597
3598 level.neighbors.assign(size * max_faces_per_cell, {-1, -1});
3599
3600 level.reference_cell.assign(size, ReferenceCells::Invalid);
3601
3602 if (orientation_needed)
3603 level.face_orientations.reinit(size * max_faces_per_cell);
3604
3605
3606 level.global_active_cell_indices.assign(size,
3608 level.global_level_cell_indices.assign(size,
3610 }
3611
3612
3613
3614 static void
3615 reserve_space_(TriaObjects &obj, const unsigned int size)
3616 {
3617 const unsigned int structdim = obj.structdim;
3618
3619 const unsigned int max_children_per_cell = 1 << structdim;
3620 const unsigned int max_faces_per_cell = 2 * structdim;
3621
3622 obj.used.assign(size, true);
3623 obj.boundary_or_material_id.assign(
3624 size,
3626 BoundaryOrMaterialId());
3627 obj.manifold_id.assign(size, -1);
3628 obj.user_flags.assign(size, false);
3629 obj.user_data.resize(size);
3630
3631 if (structdim > 1) // TODO: why?
3632 obj.refinement_cases.assign(size, 0);
3633
3634 obj.children.assign(max_children_per_cell / 2 * size, -1);
3635
3636 obj.cells.assign(max_faces_per_cell * size, -1);
3637
3638 if (structdim <= 2)
3639 {
3640 obj.next_free_single = size - 1;
3641 obj.next_free_pair = 0;
3643 }
3644 else
3645 {
3646 obj.next_free_single = obj.next_free_pair = 0;
3647 }
3648 }
3649
3650
3666 template <int spacedim>
3667 static void
3670 std::vector<unsigned int> &,
3671 std::vector<unsigned int> &)
3672 {
3673 const unsigned int dim = 1;
3674
3675 // first we need to reset the
3676 // neighbor pointers of the
3677 // neighbors of this cell's
3678 // children to this cell. This is
3679 // different for one dimension,
3680 // since there neighbors can have a
3681 // refinement level differing from
3682 // that of this cell's children by
3683 // more than one level.
3684
3685 Assert(!cell->child(0)->has_children() &&
3686 !cell->child(1)->has_children(),
3688
3689 // first do it for the cells to the
3690 // left
3691 if (cell->neighbor(0).state() == IteratorState::valid)
3692 if (cell->neighbor(0)->has_children())
3693 {
3695 cell->neighbor(0);
3696 Assert(neighbor->level() == cell->level(), ExcInternalError());
3697
3698 // right child
3699 neighbor = neighbor->child(1);
3700 while (true)
3701 {
3702 Assert(neighbor->neighbor(1) == cell->child(0),
3704 neighbor->set_neighbor(1, cell);
3705
3706 // move on to further
3707 // children on the
3708 // boundary between this
3709 // cell and its neighbor
3710 if (neighbor->has_children())
3711 neighbor = neighbor->child(1);
3712 else
3713 break;
3714 }
3715 }
3716
3717 // now do it for the cells to the
3718 // left
3719 if (cell->neighbor(1).state() == IteratorState::valid)
3720 if (cell->neighbor(1)->has_children())
3721 {
3723 cell->neighbor(1);
3724 Assert(neighbor->level() == cell->level(), ExcInternalError());
3725
3726 // left child
3727 neighbor = neighbor->child(0);
3728 while (true)
3729 {
3730 Assert(neighbor->neighbor(0) == cell->child(1),
3732 neighbor->set_neighbor(0, cell);
3733
3734 // move on to further
3735 // children on the
3736 // boundary between this
3737 // cell and its neighbor
3738 if (neighbor->has_children())
3739 neighbor = neighbor->child(0);
3740 else
3741 break;
3742 }
3743 }
3744
3745
3746 // delete the vertex which will not
3747 // be needed anymore. This vertex
3748 // is the second of the first child
3749 triangulation.vertices_used[cell->child(0)->vertex_index(1)] = false;
3750
3751 // invalidate children. clear user
3752 // pointers, to avoid that they may
3753 // appear at unwanted places later
3754 // on...
3755 for (unsigned int child = 0; child < cell->n_children(); ++child)
3756 {
3757 cell->child(child)->clear_user_data();
3758 cell->child(child)->clear_user_flag();
3759 cell->child(child)->clear_used_flag();
3760 }
3761
3762
3763 // delete pointer to children
3764 cell->clear_children();
3765 cell->clear_user_flag();
3766 }
3767
3768
3769
3770 template <int spacedim>
3771 static void
3774 std::vector<unsigned int> &line_cell_count,
3775 std::vector<unsigned int> &)
3776 {
3777 const unsigned int dim = 2;
3778 const RefinementCase<dim> ref_case = cell->refinement_case();
3779
3780 Assert(line_cell_count.size() == triangulation.n_raw_lines(),
3782
3783 // vectors to hold all lines which
3784 // may be deleted
3785 std::vector<typename Triangulation<dim, spacedim>::line_iterator>
3786 lines_to_delete(0);
3787
3788 lines_to_delete.reserve(4 * 2 + 4);
3789
3790 // now we decrease the counters for
3791 // lines contained in the child
3792 // cells
3793 for (unsigned int c = 0; c < cell->n_children(); ++c)
3794 {
3796 cell->child(c);
3797 for (unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++l)
3798 --line_cell_count[child->line_index(l)];
3799 }
3800
3801
3802 // delete the vertex which will not
3803 // be needed anymore. This vertex
3804 // is the second of the second line
3805 // of the first child, if the cell
3806 // is refined with cut_xy, else there
3807 // is no inner vertex.
3808 // additionally delete unneeded inner
3809 // lines
3810 if (ref_case == RefinementCase<dim>::cut_xy)
3811 {
3813 .vertices_used[cell->child(0)->line(1)->vertex_index(1)] = false;
3814
3815 lines_to_delete.push_back(cell->child(0)->line(1));
3816 lines_to_delete.push_back(cell->child(0)->line(3));
3817 lines_to_delete.push_back(cell->child(3)->line(0));
3818 lines_to_delete.push_back(cell->child(3)->line(2));
3819 }
3820 else
3821 {
3822 unsigned int inner_face_no =
3823 ref_case == RefinementCase<dim>::cut_x ? 1 : 3;
3824
3825 // the inner line will not be
3826 // used any more
3827 lines_to_delete.push_back(cell->child(0)->line(inner_face_no));
3828 }
3829
3830 // invalidate children
3831 for (unsigned int child = 0; child < cell->n_children(); ++child)
3832 {
3833 cell->child(child)->clear_user_data();
3834 cell->child(child)->clear_user_flag();
3835 cell->child(child)->clear_used_flag();
3836 }
3837
3838
3839 // delete pointer to children
3840 cell->clear_children();
3841 cell->clear_refinement_case();
3842 cell->clear_user_flag();
3843
3844 // look at the refinement of outer
3845 // lines. if nobody needs those
3846 // anymore we can add them to the
3847 // list of lines to be deleted.
3848 for (unsigned int line_no = 0;
3849 line_no < GeometryInfo<dim>::lines_per_cell;
3850 ++line_no)
3851 {
3853 cell->line(line_no);
3854
3855 if (line->has_children())
3856 {
3857 // if one of the cell counters is
3858 // zero, the other has to be as well
3859
3860 Assert((line_cell_count[line->child_index(0)] == 0 &&
3861 line_cell_count[line->child_index(1)] == 0) ||
3862 (line_cell_count[line->child_index(0)] > 0 &&
3863 line_cell_count[line->child_index(1)] > 0),
3865
3866 if (line_cell_count[line->child_index(0)] == 0)
3867 {
3868 for (unsigned int c = 0; c < 2; ++c)
3869 Assert(!line->child(c)->has_children(),
3871
3872 // we may delete the line's
3873 // children and the middle vertex
3874 // as no cell references them
3875 // anymore
3877 .vertices_used[line->child(0)->vertex_index(1)] = false;
3878
3879 lines_to_delete.push_back(line->child(0));
3880 lines_to_delete.push_back(line->child(1));
3881
3882 line->clear_children();
3883 }
3884 }
3885 }
3886
3887 // finally, delete unneeded lines
3888
3889 // clear user pointers, to avoid that
3890 // they may appear at unwanted places
3891 // later on...
3892 // same for user flags, then finally
3893 // delete the lines
3894 typename std::vector<
3896 line = lines_to_delete.begin(),
3897 endline = lines_to_delete.end();
3898 for (; line != endline; ++line)
3899 {
3900 (*line)->clear_user_data();
3901 (*line)->clear_user_flag();
3902 (*line)->clear_used_flag();
3903 }
3904 }
3905
3906
3907
3908 template <int spacedim>
3909 static void
3912 std::vector<unsigned int> &line_cell_count,
3913 std::vector<unsigned int> &quad_cell_count)
3914 {
3915 const unsigned int dim = 3;
3916
3917 Assert(line_cell_count.size() == triangulation.n_raw_lines(),
3919 Assert(quad_cell_count.size() == triangulation.n_raw_quads(),
3921
3922 // first of all, we store the RefineCase of
3923 // this cell
3924 const RefinementCase<dim> ref_case = cell->refinement_case();
3925 // vectors to hold all lines and quads which
3926 // may be deleted
3927 std::vector<typename Triangulation<dim, spacedim>::line_iterator>
3928 lines_to_delete(0);
3929 std::vector<typename Triangulation<dim, spacedim>::quad_iterator>
3930 quads_to_delete(0);
3931
3932 lines_to_delete.reserve(12 * 2 + 6 * 4 + 6);
3933 quads_to_delete.reserve(6 * 4 + 12);
3934
3935 // now we decrease the counters for lines and
3936 // quads contained in the child cells
3937 for (unsigned int c = 0; c < cell->n_children(); ++c)
3938 {
3940 cell->child(c);
3941 const auto line_indices = TriaAccessorImplementation::
3942 Implementation::get_line_indices_of_cell(*child);
3943 for (const unsigned int l : cell->line_indices())
3944 --line_cell_count[line_indices[l]];
3945 for (auto f : GeometryInfo<dim>::face_indices())
3946 --quad_cell_count[child->quad_index(f)];
3947 }
3948
3949 //-------------------------------------
3950 // delete interior quads and lines and the
3951 // interior vertex, depending on the
3952 // refinement case of the cell
3953 //
3954 // for append quads and lines: only append
3955 // them to the list of objects to be deleted
3956
3957 switch (ref_case)
3958 {
3960 quads_to_delete.push_back(cell->child(0)->face(1));
3961 break;
3963 quads_to_delete.push_back(cell->child(0)->face(3));
3964 break;
3966 quads_to_delete.push_back(cell->child(0)->face(5));
3967 break;
3969 quads_to_delete.push_back(cell->child(0)->face(1));
3970 quads_to_delete.push_back(cell->child(0)->face(3));
3971 quads_to_delete.push_back(cell->child(3)->face(0));
3972 quads_to_delete.push_back(cell->child(3)->face(2));
3973
3974 lines_to_delete.push_back(cell->child(0)->line(11));
3975 break;
3977 quads_to_delete.push_back(cell->child(0)->face(1));
3978 quads_to_delete.push_back(cell->child(0)->face(5));
3979 quads_to_delete.push_back(cell->child(3)->face(0));
3980 quads_to_delete.push_back(cell->child(3)->face(4));
3981
3982 lines_to_delete.push_back(cell->child(0)->line(5));
3983 break;
3985 quads_to_delete.push_back(cell->child(0)->face(3));
3986 quads_to_delete.push_back(cell->child(0)->face(5));
3987 quads_to_delete.push_back(cell->child(3)->face(2));
3988 quads_to_delete.push_back(cell->child(3)->face(4));
3989
3990 lines_to_delete.push_back(cell->child(0)->line(7));
3991 break;
3993 quads_to_delete.push_back(cell->child(0)->face(1));
3994 quads_to_delete.push_back(cell->child(2)->face(1));
3995 quads_to_delete.push_back(cell->child(4)->face(1));
3996 quads_to_delete.push_back(cell->child(6)->face(1));
3997
3998 quads_to_delete.push_back(cell->child(0)->face(3));
3999 quads_to_delete.push_back(cell->child(1)->face(3));
4000 quads_to_delete.push_back(cell->child(4)->face(3));
4001 quads_to_delete.push_back(cell->child(5)->face(3));
4002
4003 quads_to_delete.push_back(cell->child(0)->face(5));
4004 quads_to_delete.push_back(cell->child(1)->face(5));
4005 quads_to_delete.push_back(cell->child(2)->face(5));
4006 quads_to_delete.push_back(cell->child(3)->face(5));
4007
4008 lines_to_delete.push_back(cell->child(0)->line(5));
4009 lines_to_delete.push_back(cell->child(0)->line(7));
4010 lines_to_delete.push_back(cell->child(0)->line(11));
4011 lines_to_delete.push_back(cell->child(7)->line(0));
4012 lines_to_delete.push_back(cell->child(7)->line(2));
4013 lines_to_delete.push_back(cell->child(7)->line(8));
4014 // delete the vertex which will not
4015 // be needed anymore. This vertex
4016 // is the vertex at the heart of
4017 // this cell, which is the sixth of
4018 // the first child
4019 triangulation.vertices_used[cell->child(0)->vertex_index(7)] =
4020 false;
4021 break;
4022 default:
4023 // only remaining case is
4024 // no_refinement, thus an error
4026 break;
4027 }
4028
4029
4030 // invalidate children
4031 for (unsigned int child = 0; child < cell->n_children(); ++child)
4032 {
4033 cell->child(child)->clear_user_data();
4034 cell->child(child)->clear_user_flag();
4035
4036 for (auto f : GeometryInfo<dim>::face_indices())
4037 // set flags denoting deviations from standard orientation of
4038 // faces back to initialization values
4039 cell->child(child)->set_combined_face_orientation(
4041
4042 cell->child(child)->clear_used_flag();
4043 }
4044
4045
4046 // delete pointer to children
4047 cell->clear_children();
4048 cell->clear_refinement_case();
4049 cell->clear_user_flag();
4050
4051 // so far we only looked at inner quads,
4052 // lines and vertices. Now we have to
4053 // consider outer ones as well. here, we have
4054 // to check, whether there are other cells
4055 // still needing these objects. otherwise we
4056 // can delete them. first for quads (and
4057 // their inner lines).
4058
4059 for (const unsigned int quad_no : GeometryInfo<dim>::face_indices())
4060 {
4062 cell->face(quad_no);
4063
4064 Assert(
4065 (GeometryInfo<dim>::face_refinement_case(ref_case, quad_no) &&
4066 quad->has_children()) ||
4067 GeometryInfo<dim>::face_refinement_case(ref_case, quad_no) ==
4070
4071 switch (quad->refinement_case())
4072 {
4073 case RefinementCase<dim - 1>::no_refinement:
4074 // nothing to do as the quad
4075 // is not refined
4076 break;
4077 case RefinementCase<dim - 1>::cut_x:
4078 case RefinementCase<dim - 1>::cut_y:
4079 {
4080 // if one of the cell counters is
4081 // zero, the other has to be as
4082 // well
4083 Assert((quad_cell_count[quad->child_index(0)] == 0 &&
4084 quad_cell_count[quad->child_index(1)] == 0) ||
4085 (quad_cell_count[quad->child_index(0)] > 0 &&
4086 quad_cell_count[quad->child_index(1)] > 0),
4088 // it might be, that the quad is
4089 // refined twice anisotropically,
4090 // first check, whether we may
4091 // delete possible grand_children
4092 unsigned int deleted_grandchildren = 0;
4093 unsigned int number_of_child_refinements = 0;
4094
4095 for (unsigned int c = 0; c < 2; ++c)
4096 if (quad->child(c)->has_children())
4097 {
4098 ++number_of_child_refinements;
4099 // if one of the cell counters is
4100 // zero, the other has to be as
4101 // well
4102 Assert(
4103 (quad_cell_count[quad->child(c)->child_index(0)] ==
4104 0 &&
4105 quad_cell_count[quad->child(c)->child_index(1)] ==
4106 0) ||
4107 (quad_cell_count[quad->child(c)->child_index(0)] >
4108 0 &&
4109 quad_cell_count[quad->child(c)->child_index(1)] >
4110 0),
4112 if (quad_cell_count[quad->child(c)->child_index(0)] ==
4113 0)
4114 {
4115 // Assert, that the two
4116 // anisotropic
4117 // refinements add up to
4118 // isotropic refinement
4119 Assert(quad->refinement_case() +
4120 quad->child(c)->refinement_case() ==
4123 // we may delete the
4124 // quad's children and
4125 // the inner line as no
4126 // cell references them
4127 // anymore
4128 quads_to_delete.push_back(
4129 quad->child(c)->child(0));
4130 quads_to_delete.push_back(
4131 quad->child(c)->child(1));
4132 if (quad->child(c)->refinement_case() ==
4134 lines_to_delete.push_back(
4135 quad->child(c)->child(0)->line(1));
4136 else
4137 lines_to_delete.push_back(
4138 quad->child(c)->child(0)->line(3));
4139 quad->child(c)->clear_children();
4140 quad->child(c)->clear_refinement_case();
4141 ++deleted_grandchildren;
4142 }
4143 }
4144 // if no grandchildren are left, we
4145 // may as well delete the
4146 // refinement of the inner line
4147 // between our children and the
4148 // corresponding vertex
4149 if (number_of_child_refinements > 0 &&
4150 deleted_grandchildren == number_of_child_refinements)
4151 {
4153 middle_line;
4154 if (quad->refinement_case() == RefinementCase<2>::cut_x)
4155 middle_line = quad->child(0)->line(1);
4156 else
4157 middle_line = quad->child(0)->line(3);
4158
4159 lines_to_delete.push_back(middle_line->child(0));
4160 lines_to_delete.push_back(middle_line->child(1));
4162 .vertices_used[middle_vertex_index<dim, spacedim>(
4163 middle_line)] = false;
4164 middle_line->clear_children();
4165 }
4166
4167 // now consider the direct children
4168 // of the given quad
4169 if (quad_cell_count[quad->child_index(0)] == 0)
4170 {
4171 // we may delete the quad's
4172 // children and the inner line
4173 // as no cell references them
4174 // anymore
4175 quads_to_delete.push_back(quad->child(0));
4176 quads_to_delete.push_back(quad->child(1));
4177 if (quad->refinement_case() == RefinementCase<2>::cut_x)
4178 lines_to_delete.push_back(quad->child(0)->line(1));
4179 else
4180 lines_to_delete.push_back(quad->child(0)->line(3));
4181
4182 // if the counters just dropped
4183 // to zero, otherwise the
4184 // children would have been
4185 // deleted earlier, then this
4186 // cell's children must have
4187 // contained the anisotropic
4188 // quad children. thus, if
4189 // those have again anisotropic
4190 // children, which are in
4191 // effect isotropic children of
4192 // the original quad, those are
4193 // still needed by a
4194 // neighboring cell and we
4195 // cannot delete them. instead,
4196 // we have to reset this quad's
4197 // refine case to isotropic and
4198 // set the children
4199 // accordingly.
4200 if (quad->child(0)->has_children())
4201 if (quad->refinement_case() ==
4203 {
4204 // now evereything is
4205 // quite complicated. we
4206 // have the children
4207 // numbered according to
4208 //
4209 // *---*---*
4210 // |n+1|m+1|
4211 // *---*---*
4212 // | n | m |
4213 // *---*---*
4214 //
4215 // from the original
4216 // anisotropic
4217 // refinement. we have to
4218 // reorder them as
4219 //
4220 // *---*---*
4221 // | m |m+1|
4222 // *---*---*
4223 // | n |n+1|
4224 // *---*---*
4225 //
4226 // for isotropic refinement.
4227 //
4228 // this is a bit ugly, of
4229 // course: loop over all
4230 // cells on all levels
4231 // and look for faces n+1
4232 // (switch_1) and m
4233 // (switch_2).
4234 const typename Triangulation<dim, spacedim>::
4235 quad_iterator switch_1 =
4236 quad->child(0)->child(1),
4237 switch_2 =
4238 quad->child(1)->child(0);
4239
4240 Assert(!switch_1->has_children(),
4242 Assert(!switch_2->has_children(),
4244
4245 const int switch_1_index = switch_1->index();
4246 const int switch_2_index = switch_2->index();
4247 for (unsigned int l = 0;
4248 l < triangulation.levels.size();
4249 ++l)
4250 for (unsigned int h = 0;
4251 h <
4252 triangulation.levels[l]->cells.n_objects();
4253 ++h)
4254 for (const unsigned int q :
4256 {
4257 const int index =
4259 ->cells.get_bounding_object_indices(
4260 h)[q];
4261 if (index == switch_1_index)
4262 triangulation.levels[l]
4263 ->cells.get_bounding_object_indices(
4264 h)[q] = switch_2_index;
4265 else if (index == switch_2_index)
4266 triangulation.levels[l]
4267 ->cells.get_bounding_object_indices(
4268 h)[q] = switch_1_index;
4269 }
4270 // now we have to copy
4271 // all information of the
4272 // two quads
4273 const int switch_1_lines[4] = {
4274 static_cast<signed int>(
4275 switch_1->line_index(0)),
4276 static_cast<signed int>(
4277 switch_1->line_index(1)),
4278 static_cast<signed int>(
4279 switch_1->line_index(2)),
4280 static_cast<signed int>(
4281 switch_1->line_index(3))};
4282 const bool switch_1_line_orientations[4] = {
4283 switch_1->line_orientation(0),
4284 switch_1->line_orientation(1),
4285 switch_1->line_orientation(2),
4286 switch_1->line_orientation(3)};
4287 const types::boundary_id switch_1_boundary_id =
4288 switch_1->boundary_id();
4289 const unsigned int switch_1_user_index =
4290 switch_1->user_index();
4291 const bool switch_1_user_flag =
4292 switch_1->user_flag_set();
4293
4294 switch_1->set_bounding_object_indices(
4295 {switch_2->line_index(0),
4296 switch_2->line_index(1),
4297 switch_2->line_index(2),
4298 switch_2->line_index(3)});
4299 switch_1->set_line_orientation(
4300 0, switch_2->line_orientation(0));
4301 switch_1->set_line_orientation(
4302 1, switch_2->line_orientation(1));
4303 switch_1->set_line_orientation(
4304 2, switch_2->line_orientation(2));
4305 switch_1->set_line_orientation(
4306 3, switch_2->line_orientation(3));
4307 switch_1->set_boundary_id_internal(
4308 switch_2->boundary_id());
4309 switch_1->set_manifold_id(
4310 switch_2->manifold_id());
4311 switch_1->set_user_index(switch_2->user_index());
4312 if (switch_2->user_flag_set())
4313 switch_1->set_user_flag();
4314 else
4315 switch_1->clear_user_flag();
4316
4317 switch_2->set_bounding_object_indices(
4318 {switch_1_lines[0],
4319 switch_1_lines[1],
4320 switch_1_lines[2],
4321 switch_1_lines[3]});
4322 switch_2->set_line_orientation(
4323 0, switch_1_line_orientations[0]);
4324 switch_2->set_line_orientation(
4325 1, switch_1_line_orientations[1]);
4326 switch_2->set_line_orientation(
4327 2, switch_1_line_orientations[2]);
4328 switch_2->set_line_orientation(
4329 3, switch_1_line_orientations[3]);
4330 switch_2->set_boundary_id_internal(
4331 switch_1_boundary_id);
4332 switch_2->set_manifold_id(
4333 switch_1->manifold_id());
4334 switch_2->set_user_index(switch_1_user_index);
4335 if (switch_1_user_flag)
4336 switch_2->set_user_flag();
4337 else
4338 switch_2->clear_user_flag();
4339
4340 const unsigned int child_0 =
4341 quad->child(0)->child_index(0);
4342 const unsigned int child_2 =
4343 quad->child(1)->child_index(0);
4344 quad->clear_children();
4345 quad->clear_refinement_case();
4346 quad->set_refinement_case(
4348 quad->set_children(0, child_0);
4349 quad->set_children(2, child_2);
4350 std::swap(quad_cell_count[child_0 + 1],
4351 quad_cell_count[child_2]);
4352 }
4353 else
4354 {
4355 // the face was refined
4356 // with cut_y, thus the
4357 // children are already
4358 // in correct order. we
4359 // only have to set them
4360 // correctly, deleting
4361 // the indirection of two
4362 // anisotropic refinement
4363 // and going directly
4364 // from the quad to
4365 // isotropic children
4366 const unsigned int child_0 =
4367 quad->child(0)->child_index(0);
4368 const unsigned int child_2 =
4369 quad->child(1)->child_index(0);
4370 quad->clear_children();
4371 quad->clear_refinement_case();
4372 quad->set_refinement_case(
4374 quad->set_children(0, child_0);
4375 quad->set_children(2, child_2);
4376 }
4377 else
4378 {
4379 quad->clear_children();
4380 quad->clear_refinement_case();
4381 }
4382 }
4383 break;
4384 }
4385 case RefinementCase<dim - 1>::cut_xy:
4386 {
4387 // if one of the cell counters is
4388 // zero, the others have to be as
4389 // well
4390
4391 Assert((quad_cell_count[quad->child_index(0)] == 0 &&
4392 quad_cell_count[quad->child_index(1)] == 0 &&
4393 quad_cell_count[quad->child_index(2)] == 0 &&
4394 quad_cell_count[quad->child_index(3)] == 0) ||
4395 (quad_cell_count[quad->child_index(0)] > 0 &&
4396 quad_cell_count[quad->child_index(1)] > 0 &&
4397 quad_cell_count[quad->child_index(2)] > 0 &&
4398 quad_cell_count[quad->child_index(3)] > 0),
4400
4401 if (quad_cell_count[quad->child_index(0)] == 0)
4402 {
4403 // we may delete the quad's
4404 // children, the inner lines
4405 // and the middle vertex as no
4406 // cell references them anymore
4407 lines_to_delete.push_back(quad->child(0)->line(1));
4408 lines_to_delete.push_back(quad->child(3)->line(0));
4409 lines_to_delete.push_back(quad->child(0)->line(3));
4410 lines_to_delete.push_back(quad->child(3)->line(2));
4411
4412 for (unsigned int child = 0; child < quad->n_children();
4413 ++child)
4414 quads_to_delete.push_back(quad->child(child));
4415
4417 .vertices_used[quad->child(0)->vertex_index(3)] =
4418 false;
4419
4420 quad->clear_children();
4421 quad->clear_refinement_case();
4422 }
4423 }
4424 break;
4425
4426 default:
4428 break;
4429 }
4430 }
4431
4432 // now we repeat a similar procedure
4433 // for the outer lines of this cell.
4434
4435 // if in debug mode: check that each
4436 // of the lines for which we consider
4437 // deleting the children in fact has
4438 // children (the bits/coarsening_3d
4439 // test tripped over this initially)
4440 for (unsigned int line_no = 0;
4441 line_no < GeometryInfo<dim>::lines_per_cell;
4442 ++line_no)
4443 {
4445 cell->line(line_no);
4446
4447 Assert(
4448 (GeometryInfo<dim>::line_refinement_case(ref_case, line_no) &&
4449 line->has_children()) ||
4450 GeometryInfo<dim>::line_refinement_case(ref_case, line_no) ==
4453
4454 if (line->has_children())
4455 {
4456 // if one of the cell counters is
4457 // zero, the other has to be as well
4458
4459 Assert((line_cell_count[line->child_index(0)] == 0 &&
4460 line_cell_count[line->child_index(1)] == 0) ||
4461 (line_cell_count[line->child_index(0)] > 0 &&
4462 line_cell_count[line->child_index(1)] > 0),
4464
4465 if (line_cell_count[line->child_index(0)] == 0)
4466 {
4467 for (unsigned int c = 0; c < 2; ++c)
4468 Assert(!line->child(c)->has_children(),
4470
4471 // we may delete the line's
4472 // children and the middle vertex
4473 // as no cell references them
4474 // anymore
4476 .vertices_used[line->child(0)->vertex_index(1)] = false;
4477
4478 lines_to_delete.push_back(line->child(0));
4479 lines_to_delete.push_back(line->child(1));
4480
4481 line->clear_children();
4482 }
4483 }
4484 }
4485
4486 // finally, delete unneeded quads and lines
4487
4488 // clear user pointers, to avoid that
4489 // they may appear at unwanted places
4490 // later on...
4491 // same for user flags, then finally
4492 // delete the quads and lines
4493 typename std::vector<
4495 line = lines_to_delete.begin(),
4496 endline = lines_to_delete.end();
4497 for (; line != endline; ++line)
4498 {
4499 (*line)->clear_user_data();
4500 (*line)->clear_user_flag();
4501 (*line)->clear_used_flag();
4502 }
4503
4504 typename std::vector<
4506 quad = quads_to_delete.begin(),
4507 endquad = quads_to_delete.end();
4508 for (; quad != endquad; ++quad)
4509 {
4510 (*quad)->clear_user_data();
4511 (*quad)->clear_children();
4512 (*quad)->clear_refinement_case();
4513 (*quad)->clear_user_flag();
4514 (*quad)->clear_used_flag();
4515 }
4516 }
4517
4518
4536 template <int spacedim>
4537 static void
4540 unsigned int &next_unused_vertex,
4542 &next_unused_line,
4544 &next_unused_cell,
4545 const typename Triangulation<2, spacedim>::cell_iterator &cell)
4546 {
4547 const unsigned int dim = 2;
4548 // clear refinement flag
4549 const RefinementCase<dim> ref_case = cell->refine_flag_set();
4550 cell->clear_refine_flag();
4551
4552 /* For the refinement process: since we go the levels up from the
4553 lowest, there are (unlike above) only two possibilities: a neighbor
4554 cell is on the same level or one level up (in both cases, it may or
4555 may not be refined later on, but we don't care here).
4556
4557 First:
4558 Set up an array of the 3x3 vertices, which are distributed on the
4559 cell (the array consists of indices into the @p{vertices} std::vector
4560
4561 2--7--3
4562 | | |
4563 4--8--5
4564 | | |
4565 0--6--1
4566
4567 note: in case of cut_x or cut_y not all these vertices are needed for
4568 the new cells
4569
4570 Second:
4571 Set up an array of the new lines (the array consists of iterator
4572 pointers into the lines arrays)
4573
4574 .-6-.-7-. The directions are: .->-.->-.
4575 1 9 3 ^ ^ ^
4576 .-10.11-. .->-.->-.
4577 0 8 2 ^ ^ ^
4578 .-4-.-5-. .->-.->-.
4579
4580 cut_x:
4581 .-4-.-5-.
4582 | | |
4583 0 6 1
4584 | | |
4585 .-2-.-3-.
4586
4587 cut_y:
4588 .---5---.
4589 1 3
4590 .---6---.
4591 0 2
4592 .---4---.
4593
4594
4595 Third:
4596 Set up an array of neighbors:
4597
4598 6 7
4599 .--.--.
4600 1| | |3
4601 .--.--.
4602 0| | |2
4603 .--.--.
4604 4 5
4605
4606 We need this array for two reasons: first to get the lines which will
4607 bound the four subcells (if the neighboring cell is refined, these
4608 lines already exist), and second to update neighborship information.
4609 Since if a neighbor is not refined, its neighborship record only
4610 points to the present, unrefined, cell rather than the children we
4611 are presently creating, we only need the neighborship information
4612 if the neighbor cells are refined. In all other cases, we store
4613 the unrefined neighbor address
4614
4615 We also need for every neighbor (if refined) which number among its
4616 neighbors the present (unrefined) cell has, since that number is to
4617 be replaced and because that also is the number of the subline which
4618 will be the interface between that neighbor and the to be created
4619 cell. We will store this number (between 0 and 3) in the field
4620 @p{neighbors_neighbor}.
4621
4622 It would be sufficient to use the children of the common line to the
4623 neighbor, if we only wanted to get the new sublines and the new
4624 vertex, but because we need to update the neighborship information of
4625 the two refined subcells of the neighbor, we need to search these
4626 anyway.
4627
4628 Convention:
4629 The created children are numbered like this:
4630
4631 .--.--.
4632 |2 . 3|
4633 .--.--.
4634 |0 | 1|
4635 .--.--.
4636 */
4637 // collect the indices of the eight surrounding vertices
4638 // 2--7--3
4639 // | | |
4640 // 4--8--5
4641 // | | |
4642 // 0--6--1
4643 int new_vertices[9];
4644 for (unsigned int vertex_no = 0; vertex_no < 4; ++vertex_no)
4645 new_vertices[vertex_no] = cell->vertex_index(vertex_no);
4646 for (unsigned int line_no = 0; line_no < 4; ++line_no)
4647 if (cell->line(line_no)->has_children())
4648 new_vertices[4 + line_no] =
4649 cell->line(line_no)->child(0)->vertex_index(1);
4650
4651 if (ref_case == RefinementCase<dim>::cut_xy)
4652 {
4653 // find the next
4654 // unused vertex and
4655 // allocate it for
4656 // the new vertex we
4657 // need here
4658 while (triangulation.vertices_used[next_unused_vertex] == true)
4659 ++next_unused_vertex;
4660 Assert(next_unused_vertex < triangulation.vertices.size(),
4661 ExcMessage(
4662 "Internal error: During refinement, the triangulation "
4663 "wants to access an element of the 'vertices' array "
4664 "but it turns out that the array is not large enough."));
4665 triangulation.vertices_used[next_unused_vertex] = true;
4666
4667 new_vertices[8] = next_unused_vertex;
4668
4669 // determine middle vertex by transfinite interpolation to be
4670 // consistent with what happens to quads in a
4671 // Triangulation<3,3> when they are refined
4672 triangulation.vertices[next_unused_vertex] =
4673 cell->center(true, true);
4674 }
4675
4676
4677 // Now the lines:
4679 unsigned int lmin = 8;
4680 unsigned int lmax = 12;
4681 if (ref_case != RefinementCase<dim>::cut_xy)
4682 {
4683 lmin = 6;
4684 lmax = 7;
4685 }
4686
4687 for (unsigned int l = lmin; l < lmax; ++l)
4688 {
4689 while (next_unused_line->used() == true)
4690 ++next_unused_line;
4691 new_lines[l] = next_unused_line;
4692 ++next_unused_line;
4693
4694 AssertIsNotUsed(new_lines[l]);
4695 }
4696
4697 if (ref_case == RefinementCase<dim>::cut_xy)
4698 {
4699 // .-6-.-7-.
4700 // 1 9 3
4701 // .-10.11-.
4702 // 0 8 2
4703 // .-4-.-5-.
4704
4705 // lines 0-7 already exist, create only the four interior
4706 // lines 8-11
4707 unsigned int l = 0;
4708 for (const unsigned int face_no : GeometryInfo<dim>::face_indices())
4709 for (unsigned int c = 0; c < 2; ++c, ++l)
4710 new_lines[l] = cell->line(face_no)->child(c);
4711 Assert(l == 8, ExcInternalError());
4712
4713 new_lines[8]->set_bounding_object_indices(
4714 {new_vertices[6], new_vertices[8]});
4715 new_lines[9]->set_bounding_object_indices(
4716 {new_vertices[8], new_vertices[7]});
4717 new_lines[10]->set_bounding_object_indices(
4718 {new_vertices[4], new_vertices[8]});
4719 new_lines[11]->set_bounding_object_indices(
4720 {new_vertices[8], new_vertices[5]});
4721 }
4722 else if (ref_case == RefinementCase<dim>::cut_x)
4723 {
4724 // .-4-.-5-.
4725 // | | |
4726 // 0 6 1
4727 // | | |
4728 // .-2-.-3-.
4729 new_lines[0] = cell->line(0);
4730 new_lines[1] = cell->line(1);
4731 new_lines[2] = cell->line(2)->child(0);
4732 new_lines[3] = cell->line(2)->child(1);
4733 new_lines[4] = cell->line(3)->child(0);
4734 new_lines[5] = cell->line(3)->child(1);
4735 new_lines[6]->set_bounding_object_indices(
4736 {new_vertices[6], new_vertices[7]});
4737 }
4738 else
4739 {
4741 // .---5---.
4742 // 1 3
4743 // .---6---.
4744 // 0 2
4745 // .---4---.
4746 new_lines[0] = cell->line(0)->child(0);
4747 new_lines[1] = cell->line(0)->child(1);
4748 new_lines[2] = cell->line(1)->child(0);
4749 new_lines[3] = cell->line(1)->child(1);
4750 new_lines[4] = cell->line(2);
4751 new_lines[5] = cell->line(3);
4752 new_lines[6]->set_bounding_object_indices(
4753 {new_vertices[4], new_vertices[5]});
4754 }
4755
4756 for (unsigned int l = lmin; l < lmax; ++l)
4757 {
4758 new_lines[l]->set_used_flag();
4759 new_lines[l]->clear_user_flag();
4760 new_lines[l]->clear_user_data();
4761 new_lines[l]->clear_children();
4762 // interior line
4763 new_lines[l]->set_boundary_id_internal(
4765 new_lines[l]->set_manifold_id(cell->manifold_id());
4766 }
4767
4768 // Now add the four (two)
4769 // new cells!
4772 while (next_unused_cell->used() == true)
4773 ++next_unused_cell;
4774
4775 const unsigned int n_children = GeometryInfo<dim>::n_children(ref_case);
4776 for (unsigned int i = 0; i < n_children; ++i)
4777 {
4778 AssertIsNotUsed(next_unused_cell);
4779 subcells[i] = next_unused_cell;
4780 ++next_unused_cell;
4781 if (i % 2 == 1 && i < n_children - 1)
4782 while (next_unused_cell->used() == true)
4783 ++next_unused_cell;
4784 }
4785
4786 if (ref_case == RefinementCase<dim>::cut_xy)
4787 {
4788 // children:
4789 // .--.--.
4790 // |2 . 3|
4791 // .--.--.
4792 // |0 | 1|
4793 // .--.--.
4794 // lines:
4795 // .-6-.-7-.
4796 // 1 9 3
4797 // .-10.11-.
4798 // 0 8 2
4799 // .-4-.-5-.
4800 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
4801 new_lines[8]->index(),
4802 new_lines[4]->index(),
4803 new_lines[10]->index()});
4804 subcells[1]->set_bounding_object_indices({new_lines[8]->index(),
4805 new_lines[2]->index(),
4806 new_lines[5]->index(),
4807 new_lines[11]->index()});
4808 subcells[2]->set_bounding_object_indices({new_lines[1]->index(),
4809 new_lines[9]->index(),
4810 new_lines[10]->index(),
4811 new_lines[6]->index()});
4812 subcells[3]->set_bounding_object_indices({new_lines[9]->index(),
4813 new_lines[3]->index(),
4814 new_lines[11]->index(),
4815 new_lines[7]->index()});
4816 }
4817 else if (ref_case == RefinementCase<dim>::cut_x)
4818 {
4819 // children:
4820 // .--.--.
4821 // | . |
4822 // .0 . 1.
4823 // | | |
4824 // .--.--.
4825 // lines:
4826 // .-4-.-5-.
4827 // | | |
4828 // 0 6 1
4829 // | | |
4830 // .-2-.-3-.
4831 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
4832 new_lines[6]->index(),
4833 new_lines[2]->index(),
4834 new_lines[4]->index()});
4835 subcells[1]->set_bounding_object_indices({new_lines[6]->index(),
4836 new_lines[1]->index(),
4837 new_lines[3]->index(),
4838 new_lines[5]->index()});
4839 }
4840 else
4841 {
4843 // children:
4844 // .-----.
4845 // | 1 |
4846 // .-----.
4847 // | 0 |
4848 // .-----.
4849 // lines:
4850 // .---5---.
4851 // 1 3
4852 // .---6---.
4853 // 0 2
4854 // .---4---.
4855 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
4856 new_lines[2]->index(),
4857 new_lines[4]->index(),
4858 new_lines[6]->index()});
4859 subcells[1]->set_bounding_object_indices({new_lines[1]->index(),
4860 new_lines[3]->index(),
4861 new_lines[6]->index(),
4862 new_lines[5]->index()});
4863 }
4864
4865 types::subdomain_id subdomainid = cell->subdomain_id();
4866
4867 for (unsigned int i = 0; i < n_children; ++i)
4868 {
4869 subcells[i]->set_used_flag();
4870 subcells[i]->clear_refine_flag();
4871 subcells[i]->clear_user_flag();
4872 subcells[i]->clear_user_data();
4873 subcells[i]->clear_children();
4874 // inherit material properties
4875 subcells[i]->set_material_id(cell->material_id());
4876 subcells[i]->set_manifold_id(cell->manifold_id());
4877 subcells[i]->set_subdomain_id(subdomainid);
4878
4879 if (i % 2 == 0)
4880 subcells[i]->set_parent(cell->index());
4881 }
4882
4883
4884
4885 // set child index for even children i=0,2 (0)
4886 for (unsigned int i = 0; i < n_children / 2; ++i)
4887 cell->set_children(2 * i, subcells[2 * i]->index());
4888 // set the refine case
4889 cell->set_refinement_case(ref_case);
4890
4891 // note that the
4892 // refinement flag was
4893 // already cleared at the
4894 // beginning of this function
4895
4896 if (dim == spacedim - 1)
4897 for (unsigned int c = 0; c < n_children; ++c)
4898 cell->child(c)->set_direction_flag(cell->direction_flag());
4899 }
4900
4901
4902
4903 template <int dim, int spacedim>
4906 const bool check_for_distorted_cells)
4907 {
4908 AssertDimension(dim, 2);
4909
4910 // Check whether a new level is needed. We have to check for
4911 // this on the highest level only
4912 for (const auto &cell : triangulation.active_cell_iterators_on_level(
4913 triangulation.levels.size() - 1))
4914 if (cell->refine_flag_set())
4915 {
4916 triangulation.levels.push_back(
4917 std::make_unique<
4919 break;
4920 }
4921
4924 line != triangulation.end_line();
4925 ++line)
4926 {
4927 line->clear_user_flag();
4928 line->clear_user_data();
4929 }
4930
4931 unsigned int n_single_lines = 0;
4932 unsigned int n_lines_in_pairs = 0;
4933 unsigned int needed_vertices = 0;
4934
4935 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
4936 {
4937 // count number of flagged cells on this level and compute
4938 // how many new vertices and new lines will be needed
4939 unsigned int needed_cells = 0;
4940
4941 for (const auto &cell :
4942 triangulation.active_cell_iterators_on_level(level))
4943 if (cell->refine_flag_set())
4944 {
4945 if (cell->reference_cell() == ReferenceCells::Triangle)
4946 {
4947 needed_cells += 4;
4948 needed_vertices += 0;
4949 n_single_lines += 3;
4950 }
4951 else if (cell->reference_cell() ==
4953 {
4954 needed_cells += 4;
4955 needed_vertices += 1;
4956 n_single_lines += 4;
4957 }
4958 else
4959 {
4961 }
4962
4963 for (const auto line_no : cell->face_indices())
4964 {
4965 auto line = cell->line(line_no);
4966 if (line->has_children() == false)
4967 line->set_user_flag();
4968 }
4969 }
4970
4971
4972 const unsigned int used_cells =
4973 std::count(triangulation.levels[level + 1]->cells.used.begin(),
4974 triangulation.levels[level + 1]->cells.used.end(),
4975 true);
4976
4977
4978 reserve_space(*triangulation.levels[level + 1],
4979 used_cells + needed_cells,
4980 2,
4981 spacedim);
4982
4983 reserve_space(triangulation.levels[level + 1]->cells,
4984 needed_cells,
4985 0);
4986 }
4987
4988 for (auto line = triangulation.begin_line();
4989 line != triangulation.end_line();
4990 ++line)
4991 if (line->user_flag_set())
4992 {
4993 Assert(line->has_children() == false, ExcInternalError());
4994 n_lines_in_pairs += 2;
4995 needed_vertices += 1;
4996 }
4997
4998 reserve_space(triangulation.faces->lines, n_lines_in_pairs, 0);
4999
5000 needed_vertices += std::count(triangulation.vertices_used.begin(),
5001 triangulation.vertices_used.end(),
5002 true);
5003
5004 if (needed_vertices > triangulation.vertices.size())
5005 {
5006 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
5007 triangulation.vertices_used.resize(needed_vertices, false);
5008 }
5009
5010 unsigned int next_unused_vertex = 0;
5011
5012 {
5015 endl = triangulation.end_line();
5017 next_unused_line = triangulation.begin_raw_line();
5018
5019 for (; line != endl; ++line)
5020 if (line->user_flag_set())
5021 {
5022 // This line needs to be refined. Find the next unused vertex
5023 // and set it appropriately
5024 while (triangulation.vertices_used[next_unused_vertex] == true)
5025 ++next_unused_vertex;
5026 Assert(next_unused_vertex < triangulation.vertices.size(),
5027 ExcMessage(
5028 "Internal error: During refinement, the triangulation "
5029 "wants to access an element of the 'vertices' array "
5030 "but it turns out that the array is not large "
5031 "enough."));
5032 triangulation.vertices_used[next_unused_vertex] = true;
5033
5034 triangulation.vertices[next_unused_vertex] = line->center(true);
5035
5036 bool pair_found = false;
5037 (void)pair_found;
5038 for (; next_unused_line != endl; ++next_unused_line)
5039 if (!next_unused_line->used() &&
5040 !(++next_unused_line)->used())
5041 {
5042 --next_unused_line;
5043 pair_found = true;
5044 break;
5045 }
5046 Assert(pair_found, ExcInternalError());
5047
5048 line->set_children(0, next_unused_line->index());
5049
5051 children[2] = {next_unused_line, ++next_unused_line};
5052
5053 AssertIsNotUsed(children[0]);
5054 AssertIsNotUsed(children[1]);
5055
5056 children[0]->set_bounding_object_indices(
5057 {line->vertex_index(0), next_unused_vertex});
5058 children[1]->set_bounding_object_indices(
5059 {next_unused_vertex, line->vertex_index(1)});
5060
5061 for (auto &child : children)
5062 {
5063 child->set_used_flag();
5064 child->clear_children();
5065 child->clear_user_data();
5066 child->clear_user_flag();
5067 child->set_boundary_id_internal(line->boundary_id());
5068 child->set_manifold_id(line->manifold_id());
5069 // Line orientation is relative to the cell it is on so
5070 // those cannot be set at this point.
5071 }
5072
5073 line->clear_user_flag();
5074 }
5075 }
5076
5077 reserve_space(triangulation.faces->lines, 0, n_single_lines);
5078
5080 cells_with_distorted_children;
5081
5083 next_unused_line = triangulation.begin_raw_line();
5084
5085 const auto create_children = [](auto &triangulation,
5086 unsigned int &next_unused_vertex,
5087 auto &next_unused_line,
5088 auto &next_unused_cell,
5089 const auto &cell) {
5090 const auto ref_case = cell->refine_flag_set();
5091 cell->clear_refine_flag();
5092
5093 unsigned int n_new_vertices = 0;
5094
5095 if (cell->reference_cell() == ReferenceCells::Triangle)
5096 n_new_vertices = 6;
5097 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5098 n_new_vertices = 9;
5099 else
5101
5102 std::vector<unsigned int> new_vertices(n_new_vertices,
5104 for (unsigned int vertex_no = 0; vertex_no < cell->n_vertices();
5105 ++vertex_no)
5106 new_vertices[vertex_no] = cell->vertex_index(vertex_no);
5107 for (unsigned int line_no = 0; line_no < cell->n_lines(); ++line_no)
5108 if (cell->line(line_no)->has_children())
5109 new_vertices[cell->n_vertices() + line_no] =
5110 cell->line(line_no)->child(0)->vertex_index(1);
5111
5112 if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5113 {
5114 while (triangulation.vertices_used[next_unused_vertex] == true)
5115 ++next_unused_vertex;
5116 Assert(
5117 next_unused_vertex < triangulation.vertices.size(),
5118 ExcMessage(
5119 "Internal error: During refinement, the triangulation wants "
5120 "to access an element of the 'vertices' array but it turns "
5121 "out that the array is not large enough."));
5122 triangulation.vertices_used[next_unused_vertex] = true;
5123
5124 new_vertices[8] = next_unused_vertex;
5125
5126 triangulation.vertices[next_unused_vertex] =
5127 cell->center(true, true);
5128 }
5129
5130 std::array<typename Triangulation<dim, spacedim>::raw_line_iterator,
5131 12>
5132 new_lines;
5133 std::array<unsigned char, 12> inherited_orientations;
5134 inherited_orientations.fill(
5136 unsigned int lmin = 0;
5137 unsigned int lmax = 0;
5138
5139 if (cell->reference_cell() == ReferenceCells::Triangle)
5140 {
5141 lmin = 6;
5142 lmax = 9;
5143 // For triangles, the innermost faces are always reversed for the
5144 // first three children and are in the standard orientation for
5145 // the last one.
5146 std::fill(inherited_orientations.begin() + lmin,
5147 inherited_orientations.begin() + lmax,
5149 }
5150 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5151 {
5152 lmin = 8;
5153 lmax = 12;
5154 }
5155 else
5156 {
5158 }
5159
5160 for (unsigned int l = lmin; l < lmax; ++l)
5161 {
5162 while (next_unused_line->used() == true)
5163 ++next_unused_line;
5164 new_lines[l] = next_unused_line;
5165 ++next_unused_line;
5166
5167 AssertIsNotUsed(new_lines[l]);
5168 }
5169
5170 // set up lines which have parents:
5171 for (const unsigned int face_no : cell->face_indices())
5172 {
5173 // Check the face (line) orientation to ensure that the (six or
5174 // eight) outer lines in new_lines are indexed in the default
5175 // orientation. This way we can index into this array in the
5176 // without special casing orientations (e.g., quadrilateral child
5177 // 3 will always have lines 9, 3, 11, 7) when setting child lines.
5178 const unsigned char combined_orientation =
5179 cell->combined_face_orientation(face_no);
5180 Assert(combined_orientation ==
5182 combined_orientation ==
5185 for (unsigned int c = 0; c < 2; ++c)
5186 {
5187 new_lines[2 * face_no + c] = cell->line(face_no)->child(c);
5188 inherited_orientations[2 * face_no + c] =
5189 cell->combined_face_orientation(face_no);
5190 }
5191 if (combined_orientation ==
5193 std::swap(new_lines[2 * face_no], new_lines[2 * face_no + 1]);
5194 }
5195
5196 // set up lines which do not have parents:
5197 if (cell->reference_cell() == ReferenceCells::Triangle)
5198 {
5199 new_lines[6]->set_bounding_object_indices(
5200 {new_vertices[3], new_vertices[4]});
5201 new_lines[7]->set_bounding_object_indices(
5202 {new_vertices[4], new_vertices[5]});
5203 new_lines[8]->set_bounding_object_indices(
5204 {new_vertices[5], new_vertices[3]});
5205 }
5206 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5207 {
5208 new_lines[8]->set_bounding_object_indices(
5209 {new_vertices[6], new_vertices[8]});
5210 new_lines[9]->set_bounding_object_indices(
5211 {new_vertices[8], new_vertices[7]});
5212 new_lines[10]->set_bounding_object_indices(
5213 {new_vertices[4], new_vertices[8]});
5214 new_lines[11]->set_bounding_object_indices(
5215 {new_vertices[8], new_vertices[5]});
5216 }
5217 else
5218 {
5220 }
5221
5222 for (unsigned int l = lmin; l < lmax; ++l)
5223 {
5224 new_lines[l]->set_used_flag();
5225 new_lines[l]->clear_user_flag();
5226 new_lines[l]->clear_user_data();
5227 new_lines[l]->clear_children();
5228 // new lines are always internal.
5229 new_lines[l]->set_boundary_id_internal(
5231 new_lines[l]->set_manifold_id(cell->manifold_id());
5232 }
5233
5236 while (next_unused_cell->used() == true)
5237 ++next_unused_cell;
5238
5239 unsigned int n_children = 0;
5240 if (cell->reference_cell() == ReferenceCells::Triangle)
5241 n_children = 4;
5242 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5243 n_children = 4;
5244 else
5246
5247 for (unsigned int i = 0; i < n_children; ++i)
5248 {
5249 AssertIsNotUsed(next_unused_cell);
5250 subcells[i] = next_unused_cell;
5251 ++next_unused_cell;
5252 if (i % 2 == 1 && i < n_children - 1)
5253 while (next_unused_cell->used() == true)
5254 ++next_unused_cell;
5255 }
5256
5257 // Assign lines to child cells:
5258 constexpr unsigned int X = numbers::invalid_unsigned_int;
5259 static constexpr ::ndarray<unsigned int, 4, 4> tri_child_lines =
5260 {{{{0, 8, 5, X}}, {{1, 2, 6, X}}, {{7, 3, 4, X}}, {{6, 7, 8, X}}}};
5261 static constexpr ::ndarray<unsigned int, 4, 4>
5262 quad_child_lines = {{{{0, 8, 4, 10}},
5263 {{8, 2, 5, 11}},
5264 {{1, 9, 10, 6}},
5265 {{9, 3, 11, 7}}}};
5266 // Here and below we assume that child cells have the same reference
5267 // cell type as the parent.
5268 const auto &child_lines =
5269 cell->reference_cell() == ReferenceCells::Triangle ?
5270 tri_child_lines :
5271 quad_child_lines;
5272 for (unsigned int i = 0; i < n_children; ++i)
5273 {
5274 if (cell->reference_cell() == ReferenceCells::Triangle)
5275 subcells[i]->set_bounding_object_indices(
5276 {new_lines[child_lines[i][0]]->index(),
5277 new_lines[child_lines[i][1]]->index(),
5278 new_lines[child_lines[i][2]]->index()});
5279 else
5280 subcells[i]->set_bounding_object_indices(
5281 {new_lines[child_lines[i][0]]->index(),
5282 new_lines[child_lines[i][1]]->index(),
5283 new_lines[child_lines[i][2]]->index(),
5284 new_lines[child_lines[i][3]]->index()});
5285
5286 subcells[i]->set_used_flag();
5287 subcells[i]->clear_refine_flag();
5288 subcells[i]->clear_user_flag();
5289 subcells[i]->clear_user_data();
5290 subcells[i]->clear_children();
5291 // inherit material properties
5292 subcells[i]->set_material_id(cell->material_id());
5293 subcells[i]->set_manifold_id(cell->manifold_id());
5294 subcells[i]->set_subdomain_id(cell->subdomain_id());
5295
5296 triangulation.levels[subcells[i]->level()]
5297 ->reference_cell[subcells[i]->index()] = cell->reference_cell();
5298
5299 // Finally, now that children are marked as used, we can set
5300 // orientation flags:
5301 for (unsigned int face_no : cell->face_indices())
5302 subcells[i]->set_combined_face_orientation(
5303 face_no, inherited_orientations[child_lines[i][face_no]]);
5304
5305 if (i % 2 == 0)
5306 subcells[i]->set_parent(cell->index());
5307 }
5308
5309 // Unlike the same lines on other children, the innermost triangle's
5310 // faces are all in the default orientation:
5311 if (cell->reference_cell() == ReferenceCells::Triangle)
5312 for (unsigned int face_no : cell->face_indices())
5313 subcells[3]->set_combined_face_orientation(
5315
5316 for (unsigned int i = 0; i < n_children / 2; ++i)
5317 cell->set_children(2 * i, subcells[2 * i]->index());
5318
5319 cell->set_refinement_case(ref_case);
5320
5321 if (dim == spacedim - 1)
5322 for (unsigned int c = 0; c < n_children; ++c)
5323 cell->child(c)->set_direction_flag(cell->direction_flag());
5324 };
5325
5326 for (int level = 0;
5327 level < static_cast<int>(triangulation.levels.size()) - 1;
5328 ++level)
5329 {
5331 next_unused_cell = triangulation.begin_raw(level + 1);
5332
5333 for (const auto &cell :
5334 triangulation.active_cell_iterators_on_level(level))
5335 if (cell->refine_flag_set())
5336 {
5337 create_children(triangulation,
5338 next_unused_vertex,
5339 next_unused_line,
5340 next_unused_cell,
5341 cell);
5342
5343 if (cell->reference_cell() == ReferenceCells::Quadrilateral &&
5344 check_for_distorted_cells &&
5345 has_distorted_children<dim, spacedim>(cell))
5346 cells_with_distorted_children.distorted_cells.push_back(
5347 cell);
5348
5349 triangulation.signals.post_refinement_on_cell(cell);
5350 }
5351 }
5352
5353 return cells_with_distorted_children;
5354 }
5355
5356
5357
5362 template <int spacedim>
5365 const bool /*check_for_distorted_cells*/)
5366 {
5367 const unsigned int dim = 1;
5368
5369 // Check whether a new level is needed. We have to check for
5370 // this on the highest level only
5371 for (const auto &cell : triangulation.active_cell_iterators_on_level(
5372 triangulation.levels.size() - 1))
5373 if (cell->refine_flag_set())
5374 {
5375 triangulation.levels.push_back(
5376 std::make_unique<
5378 break;
5379 }
5380
5381
5382 // check how much space is needed on every level. We need not
5383 // check the highest level since either - on the highest level
5384 // no cells are flagged for refinement - there are, but
5385 // prepare_refinement added another empty level
5386 unsigned int needed_vertices = 0;
5387 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5388 {
5389 // count number of flagged
5390 // cells on this level
5391 unsigned int flagged_cells = 0;
5392
5393 for (const auto &acell :
5394 triangulation.active_cell_iterators_on_level(level))
5395 if (acell->refine_flag_set())
5396 ++flagged_cells;
5397
5398 // count number of used cells
5399 // on the next higher level
5400 const unsigned int used_cells =
5401 std::count(triangulation.levels[level + 1]->cells.used.begin(),
5402 triangulation.levels[level + 1]->cells.used.end(),
5403 true);
5404
5405 // reserve space for the used_cells cells already existing
5406 // on the next higher level as well as for the
5407 // 2*flagged_cells that will be created on that level
5408 reserve_space(*triangulation.levels[level + 1],
5410 flagged_cells,
5411 1,
5412 spacedim);
5413 // reserve space for 2*flagged_cells new lines on the next
5414 // higher level
5415 reserve_space(triangulation.levels[level + 1]->cells,
5417 flagged_cells,
5418 0);
5419
5420 needed_vertices += flagged_cells;
5421 }
5422
5423 // add to needed vertices how many
5424 // vertices are already in use
5425 needed_vertices += std::count(triangulation.vertices_used.begin(),
5426 triangulation.vertices_used.end(),
5427 true);
5428 // if we need more vertices: create them, if not: leave the
5429 // array as is, since shrinking is not really possible because
5430 // some of the vertices at the end may be in use
5431 if (needed_vertices > triangulation.vertices.size())
5432 {
5433 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
5434 triangulation.vertices_used.resize(needed_vertices, false);
5435 }
5436
5437
5438 // Do REFINEMENT on every level; exclude highest level as
5439 // above
5440
5441 // index of next unused vertex
5442 unsigned int next_unused_vertex = 0;
5443
5444 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5445 {
5447 next_unused_cell = triangulation.begin_raw(level + 1);
5448
5449 for (const auto &cell :
5450 triangulation.active_cell_iterators_on_level(level))
5451 if (cell->refine_flag_set())
5452 {
5453 // clear refinement flag
5454 cell->clear_refine_flag();
5455
5456 // search for next unused
5457 // vertex
5458 while (triangulation.vertices_used[next_unused_vertex] ==
5459 true)
5460 ++next_unused_vertex;
5461 Assert(
5462 next_unused_vertex < triangulation.vertices.size(),
5463 ExcMessage(
5464 "Internal error: During refinement, the triangulation "
5465 "wants to access an element of the 'vertices' array "
5466 "but it turns out that the array is not large enough."));
5467
5468 // Now we always ask the cell itself where to put
5469 // the new point. The cell in turn will query the
5470 // manifold object internally.
5471 triangulation.vertices[next_unused_vertex] =
5472 cell->center(true);
5473
5474 triangulation.vertices_used[next_unused_vertex] = true;
5475
5476 // search for next two unused cell (++ takes care of
5477 // the end of the vector)
5479 first_child,
5480 second_child;
5481 while (next_unused_cell->used() == true)
5482 ++next_unused_cell;
5483 first_child = next_unused_cell;
5484 first_child->set_used_flag();
5485 first_child->clear_user_data();
5486 ++next_unused_cell;
5487 AssertIsNotUsed(next_unused_cell);
5488 second_child = next_unused_cell;
5489 second_child->set_used_flag();
5490 second_child->clear_user_data();
5491
5492 types::subdomain_id subdomainid = cell->subdomain_id();
5493
5494 // insert first child
5495 cell->set_children(0, first_child->index());
5496 first_child->clear_children();
5497 first_child->set_bounding_object_indices(
5498 {cell->vertex_index(0), next_unused_vertex});
5499 first_child->set_material_id(cell->material_id());
5500 first_child->set_manifold_id(cell->manifold_id());
5501 first_child->set_subdomain_id(subdomainid);
5502 if (dim == spacedim - 1)
5503 first_child->set_direction_flag(cell->direction_flag());
5504
5505 first_child->set_parent(cell->index());
5506
5507 // Set manifold id of the right face. Only do this
5508 // on the first child.
5509 first_child->face(1)->set_manifold_id(cell->manifold_id());
5510
5511 // reset neighborship info (refer to
5512 // internal::TriangulationImplementation::TriaLevel<0> for
5513 // details)
5514 first_child->set_neighbor(1, second_child);
5515 if (cell->neighbor(0).state() != IteratorState::valid)
5516 first_child->set_neighbor(0, cell->neighbor(0));
5517 else if (cell->neighbor(0)->is_active())
5518 {
5519 // since the neighbors level is always <=level,
5520 // if the cell is active, then there are no
5521 // cells to the left which may want to know
5522 // about this new child cell.
5523 Assert(cell->neighbor(0)->level() <= cell->level(),
5525 first_child->set_neighbor(0, cell->neighbor(0));
5526 }
5527 else
5528 // left neighbor is refined
5529 {
5530 // set neighbor to cell on same level
5531 const unsigned int nbnb = cell->neighbor_of_neighbor(0);
5532 first_child->set_neighbor(0,
5533 cell->neighbor(0)->child(nbnb));
5534
5535 // reset neighbor info of all right descendant
5536 // of the left neighbor of cell
5538 left_neighbor = cell->neighbor(0);
5539 while (left_neighbor->has_children())
5540 {
5541 left_neighbor = left_neighbor->child(nbnb);
5542 left_neighbor->set_neighbor(nbnb, first_child);
5543 }
5544 }
5545
5546 // insert second child
5547 second_child->clear_children();
5548 second_child->set_bounding_object_indices(
5549 {next_unused_vertex, cell->vertex_index(1)});
5550 second_child->set_neighbor(0, first_child);
5551 second_child->set_material_id(cell->material_id());
5552 second_child->set_manifold_id(cell->manifold_id());
5553 second_child->set_subdomain_id(subdomainid);
5554 if (dim == spacedim - 1)
5555 second_child->set_direction_flag(cell->direction_flag());
5556
5557 if (cell->neighbor(1).state() != IteratorState::valid)
5558 second_child->set_neighbor(1, cell->neighbor(1));
5559 else if (cell->neighbor(1)->is_active())
5560 {
5561 Assert(cell->neighbor(1)->level() <= cell->level(),
5563 second_child->set_neighbor(1, cell->neighbor(1));
5564 }
5565 else
5566 // right neighbor is refined same as above
5567 {
5568 const unsigned int nbnb = cell->neighbor_of_neighbor(1);
5569 second_child->set_neighbor(
5570 1, cell->neighbor(1)->child(nbnb));
5571
5573 right_neighbor = cell->neighbor(1);
5574 while (right_neighbor->has_children())
5575 {
5576 right_neighbor = right_neighbor->child(nbnb);
5577 right_neighbor->set_neighbor(nbnb, second_child);
5578 }
5579 }
5580 // inform all listeners that cell refinement is done
5581 triangulation.signals.post_refinement_on_cell(cell);
5582 }
5583 }
5584
5585 // in 1d, we can not have distorted children unless the parent
5586 // was already distorted (that is because we don't use
5587 // boundary information for 1d triangulations). so return an
5588 // empty list
5590 }
5591
5592
5597 template <int spacedim>
5600 const bool check_for_distorted_cells)
5601 {
5602 const unsigned int dim = 2;
5603
5604 // First check whether we can get away with isotropic refinement, or
5605 // whether we need to run through the full anisotropic algorithm
5606 {
5607 bool do_isotropic_refinement = true;
5608 for (const auto &cell : triangulation.active_cell_iterators())
5609 if (cell->refine_flag_set() == RefinementCase<dim>::cut_x ||
5610 cell->refine_flag_set() == RefinementCase<dim>::cut_y)
5611 {
5612 do_isotropic_refinement = false;
5613 break;
5614 }
5615
5616 if (do_isotropic_refinement)
5617 return execute_refinement_isotropic(triangulation,
5618 check_for_distorted_cells);
5619 }
5620
5621 // If we get here, we are doing anisotropic refinement.
5622
5623 // Check whether a new level is needed. We have to check for
5624 // this on the highest level only
5625 for (const auto &cell : triangulation.active_cell_iterators_on_level(
5626 triangulation.levels.size() - 1))
5627 if (cell->refine_flag_set())
5628 {
5629 triangulation.levels.push_back(
5630 std::make_unique<
5632 break;
5633 }
5634
5635 // TODO[WB]: we clear user flags and pointers of lines; we're going
5636 // to use them to flag which lines need refinement
5639 line != triangulation.end_line();
5640 ++line)
5641 {
5642 line->clear_user_flag();
5643 line->clear_user_data();
5644 }
5645 // running over all cells and lines count the number
5646 // n_single_lines of lines which can be stored as single
5647 // lines, e.g. inner lines
5648 unsigned int n_single_lines = 0;
5649
5650 // New lines to be created: number lines which are stored in
5651 // pairs (the children of lines must be stored in pairs)
5652 unsigned int n_lines_in_pairs = 0;
5653
5654 // check how much space is needed on every level. We need not
5655 // check the highest level since either - on the highest level
5656 // no cells are flagged for refinement - there are, but
5657 // prepare_refinement added another empty level
5658 unsigned int needed_vertices = 0;
5659 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5660 {
5661 // count number of flagged cells on this level and compute
5662 // how many new vertices and new lines will be needed
5663 unsigned int needed_cells = 0;
5664
5665 for (const auto &cell :
5666 triangulation.active_cell_iterators_on_level(level))
5667 if (cell->refine_flag_set())
5668 {
5669 if (cell->refine_flag_set() == RefinementCase<dim>::cut_xy)
5670 {
5671 needed_cells += 4;
5672
5673 // new vertex at center of cell is needed in any
5674 // case
5675 ++needed_vertices;
5676
5677 // the four inner lines can be stored as singles
5678 n_single_lines += 4;
5679 }
5680 else // cut_x || cut_y
5681 {
5682 // set the flag showing that anisotropic
5683 // refinement is used for at least one cell
5684 triangulation.anisotropic_refinement = true;
5685
5686 needed_cells += 2;
5687 // no vertex at center
5688
5689 // the inner line can be stored as single
5690 n_single_lines += 1;
5691 }
5692
5693 // mark all faces (lines) for refinement; checking
5694 // locally whether the neighbor would also like to
5695 // refine them is rather difficult for lines so we
5696 // only flag them and after visiting all cells, we
5697 // decide which lines need refinement;
5698 for (const unsigned int line_no :
5700 {
5702 cell->refine_flag_set(), line_no) ==
5704 {
5706 line = cell->line(line_no);
5707 if (line->has_children() == false)
5708 line->set_user_flag();
5709 }
5710 }
5711 }
5712
5713
5714 // count number of used cells on the next higher level
5715 const unsigned int used_cells =
5716 std::count(triangulation.levels[level + 1]->cells.used.begin(),
5717 triangulation.levels[level + 1]->cells.used.end(),
5718 true);
5719
5720
5721 // reserve space for the used_cells cells already existing
5722 // on the next higher level as well as for the
5723 // needed_cells that will be created on that level
5724 reserve_space(*triangulation.levels[level + 1],
5725 used_cells + needed_cells,
5726 2,
5727 spacedim);
5728
5729 // reserve space for needed_cells new quads on the next
5730 // higher level
5731 reserve_space(triangulation.levels[level + 1]->cells,
5732 needed_cells,
5733 0);
5734 }
5735
5736 // now count the lines which were flagged for refinement
5739 line != triangulation.end_line();
5740 ++line)
5741 if (line->user_flag_set())
5742 {
5743 Assert(line->has_children() == false, ExcInternalError());
5744 n_lines_in_pairs += 2;
5745 needed_vertices += 1;
5746 }
5747 // reserve space for n_lines_in_pairs new lines. note, that
5748 // we can't reserve space for the single lines here as well,
5749 // as all the space reserved for lines in pairs would be
5750 // counted as unused and we would end up with too little space
5751 // to store all lines. memory reservation for n_single_lines
5752 // can only be done AFTER we refined the lines of the current
5753 // cells
5754 reserve_space(triangulation.faces->lines, n_lines_in_pairs, 0);
5755
5756 // add to needed vertices how many vertices are already in use
5757 needed_vertices += std::count(triangulation.vertices_used.begin(),
5758 triangulation.vertices_used.end(),
5759 true);
5760 // if we need more vertices: create them, if not: leave the
5761 // array as is, since shrinking is not really possible because
5762 // some of the vertices at the end may be in use
5763 if (needed_vertices > triangulation.vertices.size())
5764 {
5765 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
5766 triangulation.vertices_used.resize(needed_vertices, false);
5767 }
5768
5769
5770 // Do REFINEMENT on every level; exclude highest level as
5771 // above
5772
5773 // index of next unused vertex
5774 unsigned int next_unused_vertex = 0;
5775
5776 // first the refinement of lines. children are stored
5777 // pairwise
5778 {
5779 // only active objects can be refined further
5782 endl = triangulation.end_line();
5784 next_unused_line = triangulation.begin_raw_line();
5785
5786 for (; line != endl; ++line)
5787 if (line->user_flag_set())
5788 {
5789 // this line needs to be refined
5790
5791 // find the next unused vertex and set it
5792 // appropriately
5793 while (triangulation.vertices_used[next_unused_vertex] == true)
5794 ++next_unused_vertex;
5795 Assert(
5796 next_unused_vertex < triangulation.vertices.size(),
5797 ExcMessage(
5798 "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."));
5799 triangulation.vertices_used[next_unused_vertex] = true;
5800
5801 triangulation.vertices[next_unused_vertex] = line->center(true);
5802
5803 // now that we created the right point, make up the
5804 // two child lines. To this end, find a pair of
5805 // unused lines
5806 bool pair_found = false;
5807 (void)pair_found;
5808 for (; next_unused_line != endl; ++next_unused_line)
5809 if (!next_unused_line->used() &&
5810 !(++next_unused_line)->used())
5811 {
5812 // go back to the first of the two unused
5813 // lines
5814 --next_unused_line;
5815 pair_found = true;
5816 break;
5817 }
5818 Assert(pair_found, ExcInternalError());
5819
5820 // there are now two consecutive unused lines, such
5821 // that the children of a line will be consecutive.
5822 // then set the child pointer of the present line
5823 line->set_children(0, next_unused_line->index());
5824
5825 // set the two new lines
5827 children[2] = {next_unused_line, ++next_unused_line};
5828 // some tests; if any of the iterators should be
5829 // invalid, then already dereferencing will fail
5830 AssertIsNotUsed(children[0]);
5831 AssertIsNotUsed(children[1]);
5832
5833 children[0]->set_bounding_object_indices(
5834 {line->vertex_index(0), next_unused_vertex});
5835 children[1]->set_bounding_object_indices(
5836 {next_unused_vertex, line->vertex_index(1)});
5837
5838 children[0]->set_used_flag();
5839 children[1]->set_used_flag();
5840 children[0]->clear_children();
5841 children[1]->clear_children();
5842 children[0]->clear_user_data();
5843 children[1]->clear_user_data();
5844 children[0]->clear_user_flag();
5845 children[1]->clear_user_flag();
5846
5847
5848 children[0]->set_boundary_id_internal(line->boundary_id());
5849 children[1]->set_boundary_id_internal(line->boundary_id());
5850
5851 children[0]->set_manifold_id(line->manifold_id());
5852 children[1]->set_manifold_id(line->manifold_id());
5853
5854 // finally clear flag indicating the need for
5855 // refinement
5856 line->clear_user_flag();
5857 }
5858 }
5859
5860
5861 // Now set up the new cells
5862
5863 // reserve space for inner lines (can be stored as single
5864 // lines)
5865 reserve_space(triangulation.faces->lines, 0, n_single_lines);
5866
5868 cells_with_distorted_children;
5869
5870 // reset next_unused_line, as now also single empty places in
5871 // the vector can be used
5873 next_unused_line = triangulation.begin_raw_line();
5874
5875 for (int level = 0;
5876 level < static_cast<int>(triangulation.levels.size()) - 1;
5877 ++level)
5878 {
5880 next_unused_cell = triangulation.begin_raw(level + 1);
5881
5882 for (const auto &cell :
5883 triangulation.active_cell_iterators_on_level(level))
5884 if (cell->refine_flag_set())
5885 {
5886 // actually set up the children and update neighbor
5887 // information
5888 create_children(triangulation,
5889 next_unused_vertex,
5890 next_unused_line,
5891 next_unused_cell,
5892 cell);
5893
5894 if (check_for_distorted_cells &&
5895 has_distorted_children<dim, spacedim>(cell))
5896 cells_with_distorted_children.distorted_cells.push_back(
5897 cell);
5898 // inform all listeners that cell refinement is done
5899 triangulation.signals.post_refinement_on_cell(cell);
5900 }
5901 }
5902
5903 return cells_with_distorted_children;
5904 }
5905
5906
5907 template <int spacedim>
5910 const bool check_for_distorted_cells)
5911 {
5912 static const int dim = 3;
5913 static const unsigned int X = numbers::invalid_unsigned_int;
5914 using raw_line_iterator =
5916 using raw_quad_iterator =
5918
5919 Assert(spacedim == 3, ExcNotImplemented());
5920
5921 Assert(triangulation.vertices.size() ==
5922 triangulation.vertices_used.size(),
5924
5925 // Check whether a new level is needed. We have to check for
5926 // this on the highest level only
5927 for (const auto &cell : triangulation.active_cell_iterators_on_level(
5928 triangulation.levels.size() - 1))
5929 if (cell->refine_flag_set())
5930 {
5931 triangulation.levels.push_back(
5932 std::make_unique<
5934 break;
5935 }
5936
5937 // first clear user flags for quads and lines; we're going to
5938 // use them to flag which lines and quads need refinement
5939 triangulation.faces->quads.clear_user_data();
5940 triangulation.faces->lines.clear_user_flags();
5941 triangulation.faces->quads.clear_user_flags();
5942
5943 // check how much space is needed on every level. We need not
5944 // check the highest level since either
5945 // - on the highest level no cells are flagged for refinement
5946 // - there are, but prepare_refinement added another empty
5947 // level which then is the highest level
5948
5949 // variables to hold the number of newly to be created
5950 // vertices, lines and quads. as these are stored globally,
5951 // declare them outside the loop over al levels. we need lines
5952 // and quads in pairs for refinement of old ones and lines and
5953 // quads, that can be stored as single ones, as they are newly
5954 // created in the inside of an existing cell
5955 unsigned int needed_vertices = 0;
5956 unsigned int needed_lines_single = 0;
5957 unsigned int needed_quads_single = 0;
5958 unsigned int needed_lines_pair = 0;
5959 unsigned int needed_quads_pair = 0;
5960 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5961 {
5962 unsigned int new_cells = 0;
5963
5964 for (const auto &cell :
5965 triangulation.active_cell_iterators_on_level(level))
5966 if (cell->refine_flag_set())
5967 {
5968 // Only support isotropic refinement
5969 Assert(cell->refine_flag_set() ==
5972
5973 // Now count up how many new cells, faces, edges, and vertices
5974 // we will need to allocate to do this refinement.
5975 new_cells += cell->reference_cell().n_isotropic_children();
5976
5977 if (cell->reference_cell() == ReferenceCells::Hexahedron)
5978 {
5979 ++needed_vertices;
5980 needed_lines_single += 6;
5981 needed_quads_single += 12;
5982 }
5983 else if (cell->reference_cell() ==
5985 {
5986 needed_lines_single += 1;
5987 needed_quads_single += 8;
5988 }
5989 else
5990 {
5992 }
5993
5994 // Also check whether we have to refine any of the faces and
5995 // edges that bound this cell. They may of course already be
5996 // refined, so we only *mark* them for refinement by setting
5997 // the user flags
5998 for (const auto face : cell->face_indices())
5999 if (cell->face(face)->n_children() == 0)
6000 cell->face(face)->set_user_flag();
6001 else
6002 Assert(cell->face(face)->n_children() ==
6003 cell->reference_cell()
6004 .face_reference_cell(face)
6005 .n_isotropic_children(),
6007
6008 for (const auto line : cell->line_indices())
6009 if (cell->line(line)->has_children() == false)
6010 cell->line(line)->set_user_flag();
6011 else
6012 Assert(cell->line(line)->n_children() == 2,
6014 }
6015
6016 const unsigned int used_cells =
6017 std::count(triangulation.levels[level + 1]->cells.used.begin(),
6018 triangulation.levels[level + 1]->cells.used.end(),
6019 true);
6020
6021 reserve_space(*triangulation.levels[level + 1],
6022 used_cells + new_cells,
6023 3,
6024 spacedim);
6025
6026 reserve_space(triangulation.levels[level + 1]->cells, new_cells);
6027 }
6028
6029 // now count the quads and lines which were flagged for
6030 // refinement
6033 quad != triangulation.end_quad();
6034 ++quad)
6035 {
6036 if (quad->user_flag_set() == false)
6037 continue;
6038
6039 if (quad->reference_cell() == ReferenceCells::Quadrilateral)
6040 {
6041 needed_quads_pair += 4;
6042 needed_lines_pair += 4;
6043 needed_vertices += 1;
6044 }
6045 else if (quad->reference_cell() == ReferenceCells::Triangle)
6046 {
6047 needed_quads_pair += 4;
6048 needed_lines_single += 3;
6049 }
6050 else
6051 {
6053 }
6054 }
6055
6058 line != triangulation.end_line();
6059 ++line)
6060 {
6061 if (line->user_flag_set() == false)
6062 continue;
6063
6064 needed_lines_pair += 2;
6065 needed_vertices += 1;
6066 }
6067
6068 reserve_space(triangulation.faces->lines,
6069 needed_lines_pair,
6070 needed_lines_single);
6072 needed_quads_pair,
6073 needed_quads_single);
6074 reserve_space(triangulation.faces->quads,
6075 needed_quads_pair,
6076 needed_quads_single);
6077
6078
6079 // add to needed vertices how many vertices are already in use
6080 needed_vertices += std::count(triangulation.vertices_used.begin(),
6081 triangulation.vertices_used.end(),
6082 true);
6083
6084 if (needed_vertices > triangulation.vertices.size())
6085 {
6086 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
6087 triangulation.vertices_used.resize(needed_vertices, false);
6088 }
6089
6090 //-----------------------------------------
6091 // Before we start with the actual refinement, we do some
6092 // sanity checks if in debug mode. especially, we try to catch
6093 // the notorious problem with lines being twice refined,
6094 // i.e. there are cells adjacent at one line ("around the
6095 // edge", but not at a face), with two cells differing by more
6096 // than one refinement level
6097 //
6098 // this check is very simple to implement here, since we have
6099 // all lines flagged if they shall be refined
6100#ifdef DEBUG
6101 for (const auto &cell : triangulation.active_cell_iterators())
6102 if (!cell->refine_flag_set())
6103 for (unsigned int line_n = 0; line_n < cell->n_lines(); ++line_n)
6104 if (cell->line(line_n)->has_children())
6105 for (unsigned int c = 0; c < 2; ++c)
6106 Assert(cell->line(line_n)->child(c)->user_flag_set() == false,
6108#endif
6109
6110 unsigned int current_vertex = 0;
6111
6112 // helper function - find the next available vertex number and mark it
6113 // as used.
6114 auto get_next_unused_vertex = [](const unsigned int current_vertex,
6115 std::vector<bool> &vertices_used) {
6116 unsigned int next_vertex = current_vertex;
6117 while (next_vertex < vertices_used.size() &&
6118 vertices_used[next_vertex] == true)
6119 ++next_vertex;
6120 Assert(next_vertex < vertices_used.size(), ExcInternalError());
6121 vertices_used[next_vertex] = true;
6122
6123 return next_vertex;
6124 };
6125
6126 // LINES
6127 {
6130 endl = triangulation.end_line();
6131 raw_line_iterator next_unused_line = triangulation.begin_raw_line();
6132
6133 for (; line != endl; ++line)
6134 {
6135 if (line->user_flag_set() == false)
6136 continue;
6137
6138 next_unused_line =
6139 triangulation.faces->lines.template next_free_pair_object<1>(
6141 Assert(next_unused_line.state() == IteratorState::valid,
6143
6144 // now we found two consecutive unused lines, such
6145 // that the children of a line will be consecutive.
6146 // then set the child pointer of the present line
6147 line->set_children(0, next_unused_line->index());
6148
6149 const std::array<raw_line_iterator, 2> children{
6150 {next_unused_line, ++next_unused_line}};
6151
6152 AssertIsNotUsed(children[0]);
6153 AssertIsNotUsed(children[1]);
6154
6155 current_vertex =
6156 get_next_unused_vertex(current_vertex,
6157 triangulation.vertices_used);
6158 triangulation.vertices[current_vertex] = line->center(true);
6159
6160 children[0]->set_bounding_object_indices(
6161 {line->vertex_index(0), current_vertex});
6162 children[1]->set_bounding_object_indices(
6163 {current_vertex, line->vertex_index(1)});
6164
6165 const auto manifold_id = line->manifold_id();
6166 const auto boundary_id = line->boundary_id();
6167 for (const auto &child : children)
6168 {
6169 child->set_used_flag();
6170 child->clear_children();
6171 child->clear_user_data();
6172 child->clear_user_flag();
6173 child->set_boundary_id_internal(boundary_id);
6174 child->set_manifold_id(manifold_id);
6175 }
6176
6177 line->clear_user_flag();
6178 }
6179 }
6180
6181 // QUADS
6182 {
6184 quad = triangulation.begin_quad(),
6185 endq = triangulation.end_quad();
6186
6187 for (; quad != endq; ++quad)
6188 {
6189 if (quad->user_flag_set() == false)
6190 continue;
6191
6192 const auto reference_face_type = quad->reference_cell();
6193
6194 // 1) create new lines (property is set later)
6195 // maximum of 4 new lines (4 quadrilateral, 3 triangle)
6196 std::array<raw_line_iterator, 4> new_lines;
6197 if (reference_face_type == ReferenceCells::Quadrilateral)
6198 {
6199 for (unsigned int l = 0; l < 2; ++l)
6200 {
6201 auto next_unused_line =
6202 triangulation.faces->lines
6203 .template next_free_pair_object<1>(triangulation);
6204 new_lines[2 * l] = next_unused_line;
6205 new_lines[2 * l + 1] = ++next_unused_line;
6206 }
6207 }
6208 else if (reference_face_type == ReferenceCells::Triangle)
6209 {
6210 for (unsigned int l = 0; l < 3; ++l)
6211 new_lines[l] =
6212 triangulation.faces->lines
6213 .template next_free_single_object<1>(triangulation);
6214 }
6215 else
6216 {
6218 }
6219
6220 for (const unsigned int line : quad->line_indices())
6221 {
6222 AssertIsNotUsed(new_lines[line]);
6223 (void)line;
6224 }
6225
6226 // 2) create new quads (properties are set below). Both triangles
6227 // and quads are divided in four.
6228 std::array<raw_quad_iterator, 4> new_quads;
6229 for (unsigned int q = 0; q < 2; ++q)
6230 {
6231 auto next_unused_quad =
6232 triangulation.faces->quads
6233 .template next_free_pair_object<2>(triangulation);
6234
6235 new_quads[2 * q] = next_unused_quad;
6236 new_quads[2 * q + 1] = ++next_unused_quad;
6237
6238 quad->set_children(2 * q, new_quads[2 * q]->index());
6239 }
6240 quad->set_refinement_case(RefinementCase<2>::cut_xy);
6241
6242 for (const auto &quad : new_quads)
6243 {
6244 AssertIsNotUsed(quad);
6245 (void)quad;
6246 }
6247
6248 // 3) set vertex indices and set new vertex
6249
6250 // Maximum of 9 vertices per refined quad (9 for Quadrilateral, 6
6251 // for Triangle)
6252 std::array<unsigned int, 9> vertex_indices = {};
6253 unsigned int k = 0;
6254 for (const auto i : quad->vertex_indices())
6255 vertex_indices[k++] = quad->vertex_index(i);
6256
6257 for (const auto i : quad->line_indices())
6258 vertex_indices[k++] = quad->line(i)->child(0)->vertex_index(1);
6259
6260 if (reference_face_type == ReferenceCells::Quadrilateral)
6261 {
6262 current_vertex =
6263 get_next_unused_vertex(current_vertex,
6264 triangulation.vertices_used);
6265 vertex_indices[k++] = current_vertex;
6266
6267 triangulation.vertices[current_vertex] =
6268 quad->center(true, true);
6269 }
6270
6271 // 4) set new lines on quads and their properties
6272 std::array<raw_line_iterator, 12> lines;
6273 unsigned int n_lines = 0;
6274 for (unsigned int l = 0; l < quad->n_lines(); ++l)
6275 for (unsigned int c = 0; c < 2; ++c)
6276 {
6277 static constexpr ::ndarray<unsigned int, 2, 2> index =
6278 {{// child 0, line_orientation=false and true
6279 {{1, 0}},
6280 // child 1, line_orientation=false and true
6281 {{0, 1}}}};
6282
6283 lines[n_lines++] =
6284 quad->line(l)->child(index[c][quad->line_orientation(l)]);
6285 }
6286
6287 for (unsigned int l = 0; l < quad->n_lines(); ++l)
6288 lines[n_lines++] = new_lines[l];
6289
6290 std::array<int, 12> line_indices;
6291 for (unsigned int i = 0; i < n_lines; ++i)
6292 line_indices[i] = lines[i]->index();
6293
6294 static constexpr ::ndarray<unsigned int, 12, 2>
6295 line_vertices_quad{{{{0, 4}},
6296 {{4, 2}},
6297 {{1, 5}},
6298 {{5, 3}},
6299 {{0, 6}},
6300 {{6, 1}},
6301 {{2, 7}},
6302 {{7, 3}},
6303 {{6, 8}},
6304 {{8, 7}},
6305 {{4, 8}},
6306 {{8, 5}}}};
6307
6308 static constexpr ::ndarray<unsigned int, 4, 4>
6309 quad_lines_quad{{{{0, 8, 4, 10}},
6310 {{8, 2, 5, 11}},
6311 {{1, 9, 10, 6}},
6312 {{9, 3, 11, 7}}}};
6313
6314 static constexpr ::ndarray<unsigned int, 12, 2>
6315 line_vertices_tri{{{{0, 3}},
6316 {{3, 1}},
6317 {{1, 4}},
6318 {{4, 2}},
6319 {{2, 5}},
6320 {{5, 0}},
6321 {{3, 4}},
6322 {{4, 5}},
6323 {{3, 5}},
6324 {{X, X}},
6325 {{X, X}},
6326 {{X, X}}}};
6327
6328 static constexpr ::ndarray<unsigned int, 4, 4>
6329 quad_lines_tri{{{{0, 8, 5, X}},
6330 {{1, 2, 6, X}},
6331 {{7, 3, 4, X}},
6332 {{6, 7, 8, X}}}};
6333
6334 static constexpr ::ndarray<unsigned int, 4, 4, 2>
6335 quad_line_vertices_tri{
6336 {{{{{0, 3}}, {{3, 5}}, {{5, 0}}, {{X, X}}}},
6337 {{{{3, 1}}, {{1, 4}}, {{4, 3}}, {{X, X}}}},
6338 {{{{5, 4}}, {{4, 2}}, {{2, 5}}, {{X, X}}}},
6339 {{{{3, 4}}, {{4, 5}}, {{5, 3}}, {{X, X}}}}}};
6340
6341 const auto &line_vertices =
6342 (reference_face_type == ReferenceCells::Quadrilateral) ?
6343 line_vertices_quad :
6344 line_vertices_tri;
6345 const auto &quad_lines =
6346 (reference_face_type == ReferenceCells::Quadrilateral) ?
6347 quad_lines_quad :
6348 quad_lines_tri;
6349
6350 for (unsigned int i = 0, j = 2 * quad->n_lines();
6351 i < quad->n_lines();
6352 ++i, ++j)
6353 {
6354 auto &new_line = new_lines[i];
6355 new_line->set_bounding_object_indices(
6356 {vertex_indices[line_vertices[j][0]],
6357 vertex_indices[line_vertices[j][1]]});
6358 new_line->set_used_flag();
6359 new_line->clear_user_flag();
6360 new_line->clear_user_data();
6361 new_line->clear_children();
6362 new_line->set_boundary_id_internal(quad->boundary_id());
6363 new_line->set_manifold_id(quad->manifold_id());
6364 }
6365
6366 // 5) set properties of quads
6367 for (unsigned int i = 0; i < new_quads.size(); ++i)
6368 {
6369 auto &new_quad = new_quads[i];
6370
6371 // TODO: we assume here that all children have the same type
6372 // as the parent
6373 triangulation.faces->set_quad_type(new_quad->index(),
6374 reference_face_type);
6375
6376 if (reference_face_type == ReferenceCells::Triangle)
6377 new_quad->set_bounding_object_indices(
6378 {line_indices[quad_lines[i][0]],
6379 line_indices[quad_lines[i][1]],
6380 line_indices[quad_lines[i][2]]});
6381 else if (reference_face_type == ReferenceCells::Quadrilateral)
6382 new_quad->set_bounding_object_indices(
6383 {line_indices[quad_lines[i][0]],
6384 line_indices[quad_lines[i][1]],
6385 line_indices[quad_lines[i][2]],
6386 line_indices[quad_lines[i][3]]});
6387 else
6389
6390 new_quad->set_used_flag();
6391 new_quad->clear_user_flag();
6392 new_quad->clear_user_data();
6393 new_quad->clear_children();
6394 new_quad->set_boundary_id_internal(quad->boundary_id());
6395 new_quad->set_manifold_id(quad->manifold_id());
6396
6397#ifdef DEBUG
6398 std::set<unsigned int> s;
6399#endif
6400
6401 // ... and fix orientation of lines of face for triangles,
6402 // using an expensive algorithm, quadrilaterals are treated
6403 // a few lines below by a cheaper algorithm
6404 if (reference_face_type == ReferenceCells::Triangle)
6405 {
6406 for (const auto f : new_quad->line_indices())
6407 {
6408 const std::array<unsigned int, 2> vertices_0 = {
6409 {lines[quad_lines[i][f]]->vertex_index(0),
6410 lines[quad_lines[i][f]]->vertex_index(1)}};
6411
6412 const std::array<unsigned int, 2> vertices_1 = {
6413 {vertex_indices[quad_line_vertices_tri[i][f][0]],
6414 vertex_indices[quad_line_vertices_tri[i][f][1]]}};
6415
6416 const auto orientation =
6418 make_array_view(vertices_0),
6419 make_array_view(vertices_1));
6420
6421#ifdef DEBUG
6422 for (const auto i : vertices_0)
6423 s.insert(i);
6424 for (const auto i : vertices_1)
6425 s.insert(i);
6426#endif
6427
6428 new_quad->set_line_orientation(
6429 f,
6430 orientation ==
6432 default_combined_face_orientation());
6433 }
6434#ifdef DEBUG
6435 AssertDimension(s.size(), 3);
6436#endif
6437 }
6438 }
6439
6440 // fix orientation of lines of faces for quadrilaterals with
6441 // cheap algorithm
6442 if (reference_face_type == ReferenceCells::Quadrilateral)
6443 {
6444 static constexpr ::ndarray<unsigned int, 4, 2>
6445 quad_child_boundary_lines{
6446 {{{0, 2}}, {{1, 3}}, {{0, 1}}, {{2, 3}}}};
6447
6448 for (unsigned int i = 0; i < 4; ++i)
6449 for (unsigned int j = 0; j < 2; ++j)
6450 new_quads[quad_child_boundary_lines[i][j]]
6451 ->set_line_orientation(i, quad->line_orientation(i));
6452 }
6453
6454 quad->clear_user_flag();
6455 }
6456 }
6457
6459 cells_with_distorted_children;
6460
6463 for (unsigned int level = 0; level != triangulation.levels.size() - 1;
6464 ++level)
6465 {
6467 next_unused_hex = triangulation.begin_raw_hex(level + 1);
6468 Assert(hex == triangulation.end() ||
6469 hex->level() >= static_cast<int>(level),
6471
6472 for (; hex != triangulation.end() &&
6473 hex->level() == static_cast<int>(level);
6474 ++hex)
6475 {
6476 if (hex->refine_flag_set() ==
6478 continue;
6479
6480 const auto &reference_cell_type = hex->reference_cell();
6481
6482 const RefinementCase<dim> ref_case = hex->refine_flag_set();
6483 hex->clear_refine_flag();
6484 hex->set_refinement_case(ref_case);
6485
6486 unsigned int n_new_lines = 0;
6487 unsigned int n_new_quads = 0;
6488 unsigned int n_new_hexes = 0;
6489
6490 if (reference_cell_type == ReferenceCells::Hexahedron)
6491 {
6492 n_new_lines = 6;
6493 n_new_quads = 12;
6494 n_new_hexes = 8;
6495 }
6496 else if (reference_cell_type == ReferenceCells::Tetrahedron)
6497 {
6498 n_new_lines = 1;
6499 n_new_quads = 8;
6500 n_new_hexes = 8;
6501 }
6502 else
6504
6505 std::array<raw_line_iterator, 6> new_lines;
6506 for (unsigned int i = 0; i < n_new_lines; ++i)
6507 {
6508 new_lines[i] =
6509 triangulation.faces->lines
6510 .template next_free_single_object<1>(triangulation);
6511
6512 AssertIsNotUsed(new_lines[i]);
6513 new_lines[i]->set_used_flag();
6514 new_lines[i]->clear_user_flag();
6515 new_lines[i]->clear_user_data();
6516 new_lines[i]->clear_children();
6517 new_lines[i]->set_boundary_id_internal(
6519 new_lines[i]->set_manifold_id(hex->manifold_id());
6520 }
6521
6522 std::array<raw_quad_iterator, 12> new_quads;
6523 for (unsigned int i = 0; i < n_new_quads; ++i)
6524 {
6525 new_quads[i] =
6526 triangulation.faces->quads
6527 .template next_free_single_object<2>(triangulation);
6528
6529 auto &new_quad = new_quads[i];
6530
6531 // TODO: faces of children have the same type as the faces
6532 // of the parent
6533 triangulation.faces->set_quad_type(
6534 new_quad->index(),
6535 reference_cell_type.face_reference_cell(0));
6536
6537 AssertIsNotUsed(new_quad);
6538 new_quad->set_used_flag();
6539 new_quad->clear_user_flag();
6540 new_quad->clear_user_data();
6541 new_quad->clear_children();
6542 new_quad->set_boundary_id_internal(
6544 new_quad->set_manifold_id(hex->manifold_id());
6545 for (const auto j : new_quads[i]->line_indices())
6546 new_quad->set_line_orientation(j, true);
6547 }
6548
6549 // we always get 8 children per refined cell
6550 std::array<
6552 8>
6553 new_hexes;
6554 {
6555 for (unsigned int i = 0; i < n_new_hexes; ++i)
6556 {
6557 if (i % 2 == 0)
6558 next_unused_hex =
6559 triangulation.levels[level + 1]->cells.next_free_hex(
6560 triangulation, level + 1);
6561 else
6562 ++next_unused_hex;
6563
6564 new_hexes[i] = next_unused_hex;
6565
6566 auto &new_hex = new_hexes[i];
6567
6568 // children have the same type as the parent
6569 triangulation.levels[new_hex->level()]
6570 ->reference_cell[new_hex->index()] =
6571 reference_cell_type;
6572
6573 AssertIsNotUsed(new_hex);
6574 new_hex->set_used_flag();
6575 new_hex->clear_user_flag();
6576 new_hex->clear_user_data();
6577 new_hex->clear_children();
6578 new_hex->set_material_id(hex->material_id());
6579 new_hex->set_manifold_id(hex->manifold_id());
6580 new_hex->set_subdomain_id(hex->subdomain_id());
6581
6582 if (i % 2)
6583 new_hex->set_parent(hex->index());
6584
6585 // set the orientation flag to its default state for all
6586 // faces initially. later on go the other way round and
6587 // reset faces that are at the boundary of the mother cube
6588 for (const auto f : new_hex->face_indices())
6589 new_hex->set_combined_face_orientation(
6590 f,
6592 }
6593 for (unsigned int i = 0; i < n_new_hexes / 2; ++i)
6594 hex->set_children(2 * i, new_hexes[2 * i]->index());
6595 }
6596
6597 {
6598 // load vertex indices
6599 std::array<unsigned int, 27> vertex_indices = {};
6600
6601 {
6602 unsigned int k = 0;
6603
6604 // avoid a compiler warning by fixing the max number of
6605 // loop iterations to 8
6606 const unsigned int n_vertices =
6607 std::min(hex->n_vertices(), 8u);
6608 for (unsigned int i = 0; i < n_vertices; ++i)
6609 vertex_indices[k++] = hex->vertex_index(i);
6610
6611 const std::array<unsigned int, 12> line_indices =
6612 TriaAccessorImplementation::Implementation::
6613 get_line_indices_of_cell(*hex);
6614
6615 // For the tetrahedron the parent consists of the vertices
6616 // 0,1,2,3, the new vertices 4-9 are defined as the
6617 // midpoints of the edges: 4 -> (0,1), 5 -> (1,2), 6 ->
6618 // (2,0), 7 -> (0,3), 8 -> (1,3), 9 -> (2,3).
6619 // Order is defined by the reference cell, see
6620 // https://dealii.org/developer/doxygen/deal.II/group__simplex.html#simplex_reference_cells.
6621
6622 // Avoid a compiler warning by fixing the max number of loop
6623 // iterations to 12
6624 const unsigned int n_lines = std::min(hex->n_lines(), 12u);
6625 for (unsigned int l = 0; l < n_lines; ++l)
6626 {
6627 raw_line_iterator line(&triangulation,
6628 0,
6629 line_indices[l]);
6630 vertex_indices[k++] = line->child(0)->vertex_index(1);
6631 }
6632
6633 if (reference_cell_type == ReferenceCells::Hexahedron)
6634 {
6635 for (const unsigned int i : hex->face_indices())
6636 vertex_indices[k++] =
6637 hex->face(i)->child(0)->vertex_index(3);
6638
6639 // Set single new vertex in the center
6640 current_vertex =
6641 get_next_unused_vertex(current_vertex,
6642 triangulation.vertices_used);
6643 vertex_indices[k++] = current_vertex;
6644
6645 triangulation.vertices[current_vertex] =
6646 hex->center(true, true);
6647 }
6648 }
6649
6650 unsigned int chosen_line_tetrahedron = 0;
6651 // set up new lines
6652 if (reference_cell_type == ReferenceCells::Hexahedron)
6653 {
6654 static constexpr ::ndarray<unsigned int, 6, 2>
6655 new_line_vertices = {{{{22, 26}},
6656 {{26, 23}},
6657 {{20, 26}},
6658 {{26, 21}},
6659 {{24, 26}},
6660 {{26, 25}}}};
6661 for (unsigned int i = 0; i < n_new_lines; ++i)
6662 new_lines[i]->set_bounding_object_indices(
6663 {vertex_indices[new_line_vertices[i][0]],
6664 vertex_indices[new_line_vertices[i][1]]});
6665 }
6666 else if (reference_cell_type == ReferenceCells::Tetrahedron)
6667 {
6668 // in the tetrahedron case, we have the three
6669 // possibilities (6,8), (5,7), (4,9) -> pick the
6670 // shortest line to guarantee the best possible aspect
6671 // ratios
6672 static constexpr ::ndarray<unsigned int, 3, 2>
6673 new_line_vertices = {{{{6, 8}}, {{5, 7}}, {{4, 9}}}};
6674
6675 const auto &vertices = triangulation.get_vertices();
6676 double min_distance =
6677 std::numeric_limits<double>::infinity();
6678 for (unsigned int i = 0; i < new_line_vertices.size();
6679 ++i)
6680 {
6681 const double current_distance =
6682 vertices[vertex_indices[new_line_vertices[i][0]]]
6683 .distance(
6684 vertices
6685 [vertex_indices[new_line_vertices[i][1]]]);
6686 if (current_distance < min_distance)
6687 {
6688 chosen_line_tetrahedron = i;
6689 min_distance = current_distance;
6690 }
6691 }
6692
6693 new_lines[0]->set_bounding_object_indices(
6695 [new_line_vertices[chosen_line_tetrahedron][0]],
6697 [new_line_vertices[chosen_line_tetrahedron][1]]});
6698 }
6699
6700 // set up new quads
6701 {
6702 boost::container::small_vector<raw_line_iterator, 30>
6703 relevant_lines;
6704
6705 if (reference_cell_type == ReferenceCells::Hexahedron)
6706 {
6707 relevant_lines.resize(30);
6708 for (unsigned int f = 0, k = 0; f < 6; ++f)
6709 for (unsigned int c = 0; c < 4; ++c, ++k)
6710 {
6711 static constexpr ::
6712 ndarray<unsigned int, 4, 2>
6713 temp = {
6714 {{{0, 1}}, {{3, 0}}, {{0, 3}}, {{3, 2}}}};
6715
6716 relevant_lines[k] =
6717 hex->face(f)
6718 ->isotropic_child(
6720 standard_to_real_face_vertex(
6721 temp[c][0],
6722 hex->face_orientation(f),
6723 hex->face_flip(f),
6724 hex->face_rotation(f)))
6725 ->line(GeometryInfo<dim>::
6726 standard_to_real_face_line(
6727 temp[c][1],
6728 hex->face_orientation(f),
6729 hex->face_flip(f),
6730 hex->face_rotation(f)));
6731 }
6732
6733 for (unsigned int i = 0, k = 24; i < 6; ++i, ++k)
6734 relevant_lines[k] = new_lines[i];
6735 }
6736 else if (reference_cell_type == ReferenceCells::Tetrahedron)
6737 {
6738 // The order of the lines is defined by the ordering
6739 // of the faces of the reference cell and the ordering
6740 // of the lines within a face.
6741 // Each face is split into 4 child triangles, the
6742 // relevant lines are defined by the vertices of the
6743 // center triangles: 0 -> (4,5), 1 -> (5,6), 2 -> (4,6),
6744 // 3 -> (4,7), 4 -> (7,8), 5 -> (4,8), 6 -> (6,9), 7 ->
6745 // (9,7), 8 -> (6,7), 9 -> (5,8), 10 -> (8,9), 11 ->
6746 // (5,9), Line 12 is determined by
6747 // chosen_line_tetrahedron i.e. (6,8), (5,7) or (4,9)
6748
6749 relevant_lines.resize(13);
6750
6751 unsigned int k = 0;
6752 for (unsigned int f = 0; f < 4; ++f)
6753 for (unsigned int l = 0; l < 3; ++l, ++k)
6754 {
6755 // TODO: add comment
6756 static const std::
6757 array<std::array<unsigned int, 3>, 6>
6758 table = {{{{1, 0, 2}}, // 0
6759 {{0, 1, 2}},
6760 {{0, 2, 1}}, // 2
6761 {{1, 2, 0}},
6762 {{2, 1, 0}}, // 4
6763 {{2, 0, 1}}}};
6764
6765 const unsigned char combined_orientation =
6766 hex->combined_face_orientation(f);
6767 relevant_lines[k] =
6768 hex->face(f)
6769 ->child(3 /*center triangle*/)
6770 ->line(table[combined_orientation][l]);
6771 }
6772
6773 relevant_lines[k++] = new_lines[0];
6774 AssertDimension(k, 13);
6775 }
6776 else
6778
6779 boost::container::small_vector<unsigned int, 30>
6780 relevant_line_indices(relevant_lines.size());
6781 for (unsigned int i = 0; i < relevant_line_indices.size();
6782 ++i)
6783 relevant_line_indices[i] = relevant_lines[i]->index();
6784
6785 static constexpr ::ndarray<unsigned int, 12, 4>
6786 new_quad_lines_hex = {{{{10, 28, 16, 24}},
6787 {{28, 14, 17, 25}},
6788 {{11, 29, 24, 20}},
6789 {{29, 15, 25, 21}},
6790 {{18, 26, 0, 28}},
6791 {{26, 22, 1, 29}},
6792 {{19, 27, 28, 4}},
6793 {{27, 23, 29, 5}},
6794 {{2, 24, 8, 26}},
6795 {{24, 6, 9, 27}},
6796 {{3, 25, 26, 12}},
6797 {{25, 7, 27, 13}}}};
6798
6799 // It is easierst to start at table cell_vertices_tet,
6800 // there the vertices are listed which build up the
6801 // 8 child tets. To build the child tets, 8 new faces are
6802 // needed. The the vertices, which define the lines of these
6803 // new faces are listed in table_tet. Now only the
6804 // corresponding index of the lines and quads have to be
6805 // listed in new_quad_lines_tet and cell_quads_tet.
6806
6807 // The first 4 define the faces which cut off the
6808 // parent tetrahedron at the edges. the numbers are the
6809 // index of the relevant_lines defined above the last 4
6810 // faces cut apart the remaining octahedron, such that all
6811 // of these contain line number 12. the ordering of the
6812 // faces is arbitrary, the ordering within the faces has to
6813 // follow the righthand convention for triangles
6814 static constexpr ::ndarray<unsigned int, 3, 12, 4>
6815 new_quad_lines_tet = {{// new line is (6,8)
6816 {{{{2, 3, 8, X}},
6817 {{0, 9, 5, X}},
6818 {{1, 6, 11, X}},
6819 {{4, 10, 7, X}},
6820 {{2, 12, 5, X}},
6821 {{1, 9, 12, X}},
6822 {{4, 8, 12, X}},
6823 {{6, 12, 10, X}},
6824 {{X, X, X, X}},
6825 {{X, X, X, X}},
6826 {{X, X, X, X}},
6827 {{X, X, X, X}}}},
6828 // new line is (5,7)
6829 {{{{2, 3, 8, X}},
6830 {{0, 9, 5, X}},
6831 {{1, 6, 11, X}},
6832 {{4, 10, 7, X}},
6833 {{0, 3, 12, X}},
6834 {{1, 12, 8, X}},
6835 {{4, 12, 9, X}},
6836 {{7, 11, 12, X}},
6837 {{X, X, X, X}},
6838 {{X, X, X, X}},
6839 {{X, X, X, X}},
6840 {{X, X, X, X}}}},
6841 // new line is (4,9)
6842 {{{{2, 3, 8, X}},
6843 {{0, 9, 5, X}},
6844 {{1, 6, 11, X}},
6845 {{4, 10, 7, X}},
6846 {{0, 12, 11, X}},
6847 {{2, 6, 12, X}},
6848 {{3, 12, 7, X}},
6849 {{5, 10, 12, X}},
6850 {{X, X, X, X}},
6851 {{X, X, X, X}},
6852 {{X, X, X, X}},
6853 {{X, X, X, X}}}}}};
6854
6855 static constexpr ::ndarray<unsigned int, 12, 4, 2>
6856 table_hex = {
6857 {{{{{10, 22}}, {{24, 26}}, {{10, 24}}, {{22, 26}}}},
6858 {{{{24, 26}}, {{11, 23}}, {{24, 11}}, {{26, 23}}}},
6859 {{{{22, 14}}, {{26, 25}}, {{22, 26}}, {{14, 25}}}},
6860 {{{{26, 25}}, {{23, 15}}, {{26, 23}}, {{25, 15}}}},
6861 {{{{8, 24}}, {{20, 26}}, {{8, 20}}, {{24, 26}}}},
6862 {{{{20, 26}}, {{12, 25}}, {{20, 12}}, {{26, 25}}}},
6863 {{{{24, 9}}, {{26, 21}}, {{24, 26}}, {{9, 21}}}},
6864 {{{{26, 21}}, {{25, 13}}, {{26, 25}}, {{21, 13}}}},
6865 {{{{16, 20}}, {{22, 26}}, {{16, 22}}, {{20, 26}}}},
6866 {{{{22, 26}}, {{17, 21}}, {{22, 17}}, {{26, 21}}}},
6867 {{{{20, 18}}, {{26, 23}}, {{20, 26}}, {{18, 23}}}},
6868 {{{{26, 23}}, {{21, 19}}, {{26, 21}}, {{23, 19}}}}}};
6869
6870 // The table defines the vertices of the lines above
6871 // see relevant_lines for mapping between line indices and
6872 // vertex numbering
6873 static constexpr ::ndarray<unsigned int, 3, 12, 4, 2>
6874 table_tet = {
6875 {// new line is (6, 8)
6876 {{{{{{6, 4}}, {{4, 7}}, {{7, 6}}, {{X, X}}}},
6877 {{{{4, 5}}, {{5, 8}}, {{8, 4}}, {{X, X}}}},
6878 {{{{5, 6}}, {{6, 9}}, {{9, 5}}, {{X, X}}}},
6879 {{{{7, 8}}, {{8, 9}}, {{9, 7}}, {{X, X}}}},
6880 {{{{4, 6}}, {{6, 8}}, {{8, 4}}, {{X, X}}}},
6881 {{{{6, 5}}, {{5, 8}}, {{8, 6}}, {{X, X}}}},
6882 {{{{8, 7}}, {{7, 6}}, {{6, 8}}, {{X, X}}}},
6883 {{{{9, 6}}, {{6, 8}}, {{8, 9}}, {{X, X}}}},
6884 {{{{X, X}}, {{X, X}}, {{X, X}}, {{X, X}}}},
6885 {{{{X, X}}, {{X, X}}, {{X, X}}, {{X, X}}}},
6886 {{{{X, X}}, {{X, X}}, {{X, X}}, {{X, X}}}},
6887 {{{{X, X}}, {{X, X}}, {{X, X}}, {{X, X}}}}}},
6888 // new line is (5, 7)
6889 {{{{{{6, 4}}, {{4, 7}}, {{7, 6}}, {{X, X}}}},
6890 {{{{4, 5}}, {{5, 8}}, {{8, 4}}, {{X, X}}}},
6891 {{{{5, 6}}, {{6, 9}}, {{9, 5}}, {{X, X}}}},
6892 {{{{7, 8}}, {{8, 9}}, {{9, 7}}, {{X, X}}}},
6893 {{{{5, 4}}, {{4, 7}}, {{7, 5}}, {{X, X}}}},
6894 {{{{6, 5}}, {{5, 7}}, {{7, 6}}, {{X, X}}}},
6895 {{{{8, 7}}, {{7, 5}}, {{5, 8}}, {{X, X}}}},
6896 {{{{7, 9}}, {{9, 5}}, {{5, 7}}, {{X, X}}}},
6897 {{{{X, X}}, {{X, X}}, {{X, X}}, {{X, X}}}},
6898 {{{{X, X}}, {{X, X}}, {{X, X}}, {{X, X}}}},
6899 {{{{X, X}}, {{X, X}}, {{X, X}}, {{X, X}}}},
6900 {{{{X, X}}, {{X, X}}, {{X, X}}, {{X, X}}}}}},
6901 // new line is (4, 9)
6902 {{{{{{6, 4}}, {{4, 7}}, {{7, 6}}, {{X, X}}}},
6903 {{{{4, 5}}, {{5, 8}}, {{8, 4}}, {{X, X}}}},
6904 {{{{5, 6}}, {{6, 9}}, {{9, 5}}, {{X, X}}}},
6905 {{{{7, 8}}, {{8, 9}}, {{9, 7}}, {{X, X}}}},
6906 {{{{5, 4}}, {{4, 9}}, {{9, 5}}, {{X, X}}}},
6907 {{{{4, 6}}, {{6, 9}}, {{9, 4}}, {{X, X}}}},
6908 {{{{7, 4}}, {{4, 9}}, {{9, 7}}, {{X, X}}}},
6909 {{{{4, 8}}, {{8, 9}}, {{9, 4}}, {{X, X}}}},
6910 {{{{X, X}}, {{X, X}}, {{X, X}}, {{X, X}}}},
6911 {{{{X, X}}, {{X, X}}, {{X, X}}, {{X, X}}}},
6912 {{{{X, X}}, {{X, X}}, {{X, X}}, {{X, X}}}},
6913 {{{{X, X}}, {{X, X}}, {{X, X}}, {{X, X}}}}}}}};
6914
6915 const auto &new_quad_lines =
6916 (reference_cell_type == ReferenceCells::Hexahedron) ?
6917 new_quad_lines_hex :
6918 new_quad_lines_tet[chosen_line_tetrahedron];
6919
6920 const auto &table =
6921 (reference_cell_type == ReferenceCells::Hexahedron) ?
6922 table_hex :
6923 table_tet[chosen_line_tetrahedron];
6924
6925 static constexpr ::ndarray<unsigned int, 4, 2>
6926 representative_lines{
6927 {{{0, 2}}, {{2, 0}}, {{3, 3}}, {{1, 1}}}};
6928
6929 for (unsigned int q = 0; q < n_new_quads; ++q)
6930 {
6931 auto &new_quad = new_quads[q];
6932
6933 if (new_quad->n_lines() == 3)
6934 new_quad->set_bounding_object_indices(
6935 {relevant_line_indices[new_quad_lines[q][0]],
6936 relevant_line_indices[new_quad_lines[q][1]],
6937 relevant_line_indices[new_quad_lines[q][2]]});
6938 else if (new_quad->n_lines() == 4)
6939 new_quad->set_bounding_object_indices(
6940 {relevant_line_indices[new_quad_lines[q][0]],
6941 relevant_line_indices[new_quad_lines[q][1]],
6942 relevant_line_indices[new_quad_lines[q][2]],
6943 relevant_line_indices[new_quad_lines[q][3]]});
6944 else
6946
6947 // On hexes, we must only determine a single line
6948 // according to the representative_lines array above
6949 // (this saves expensive operations), for tets we do
6950 // all lines manually
6951 const unsigned int n_compute_lines =
6952 reference_cell_type == ReferenceCells::Hexahedron ?
6953 1 :
6954 new_quad->n_lines();
6955 for (unsigned int line = 0; line < n_compute_lines;
6956 ++line)
6957 {
6958 const unsigned int l =
6959 (reference_cell_type ==
6961 representative_lines[q % 4][0] :
6962 line;
6963
6964 const std::array<unsigned int, 2> vertices_0 = {
6965 {relevant_lines[new_quad_lines[q][l]]
6966 ->vertex_index(0),
6967 relevant_lines[new_quad_lines[q][l]]
6968 ->vertex_index(1)}};
6969
6970 const std::array<unsigned int, 2> vertices_1 = {
6971 {vertex_indices[table[q][l][0]],
6972 vertex_indices[table[q][l][1]]}};
6973
6974 const auto orientation =
6976 make_array_view(vertices_0),
6977 make_array_view(vertices_1));
6978
6979 new_quad->set_line_orientation(
6980 l,
6981 orientation ==
6983 default_combined_face_orientation());
6984
6985 // on a hex, inject the status of the current line
6986 // also to the line on the other quad along the
6987 // same direction
6988 if (reference_cell_type ==
6990 new_quads[representative_lines[q % 4][1] + q -
6991 (q % 4)]
6992 ->set_line_orientation(
6993 l,
6994 orientation ==
6996 default_combined_face_orientation());
6997 }
6998 }
6999 }
7000
7001 // set up new hex
7002 {
7003 std::array<int, 36> quad_indices;
7004
7005 if (reference_cell_type == ReferenceCells::Hexahedron)
7006 {
7007 for (unsigned int i = 0; i < n_new_quads; ++i)
7008 quad_indices[i] = new_quads[i]->index();
7009
7010 for (unsigned int f = 0, k = n_new_quads; f < 6; ++f)
7011 for (unsigned int c = 0; c < 4; ++c, ++k)
7012 quad_indices[k] =
7013 hex->face(f)->isotropic_child_index(
7015 c,
7016 hex->face_orientation(f),
7017 hex->face_flip(f),
7018 hex->face_rotation(f)));
7019 }
7020 else if (reference_cell_type == ReferenceCells::Tetrahedron)
7021 {
7022 // list of the indices of the surfaces which define the
7023 // 8 new tets. the indices 0-7 are the new quads defined
7024 // above (so 0-3 cut off the corners and 4-7 separate
7025 // the remaining octahedral), the indices between 8-11
7026 // are the children of the first face, from 12-15 of the
7027 // second, etc.
7028 for (unsigned int i = 0; i < n_new_quads; ++i)
7029 quad_indices[i] = new_quads[i]->index();
7030
7031 for (unsigned int f = 0, k = n_new_quads; f < 4; ++f)
7032 for (unsigned int c = 0; c < 4; ++c, ++k)
7033 {
7034 const unsigned char combined_orientation =
7035 hex->combined_face_orientation(f);
7036 quad_indices[k] = hex->face(f)->child_index(
7037 (c == 3) ? 3 :
7038 reference_cell_type
7039 .standard_to_real_face_vertex(
7040 c, f, combined_orientation));
7041 }
7042 }
7043 else
7044 {
7046 }
7047
7048 static constexpr ::ndarray<unsigned int, 8, 6>
7049 cell_quads_hex = {{
7050 {{12, 0, 20, 4, 28, 8}}, // bottom children
7051 {{0, 16, 22, 6, 29, 9}}, //
7052 {{13, 1, 4, 24, 30, 10}}, //
7053 {{1, 17, 6, 26, 31, 11}}, //
7054 {{14, 2, 21, 5, 8, 32}}, // top children
7055 {{2, 18, 23, 7, 9, 33}}, //
7056 {{15, 3, 5, 25, 10, 34}}, //
7057 {{3, 19, 7, 27, 11, 35}} //
7058 }};
7059
7060 // indices of the faces which define the new tets
7061 // the ordering of the tets is arbitrary
7062 // the first 4 determine the tets cutting of the corners
7063 // the last 4 are ordered after their appearance in the
7064 // faces.
7065 // the ordering within the faces is determined by
7066 // convention for the tetrahedron unit cell, see
7067 // cell_vertices_tet below
7068 static constexpr ::ndarray<unsigned int, 3, 8, 6>
7069 cell_quads_tet = {{// new line is (6, 8)
7070 {{{{8, 13, 16, 0, X, X}},
7071 {{9, 12, 1, 21, X, X}},
7072 {{10, 2, 17, 20, X, X}},
7073 {{3, 14, 18, 22, X, X}},
7074 {{11, 1, 4, 5, X, X}},
7075 {{15, 0, 4, 6, X, X}},
7076 {{19, 7, 6, 3, X, X}},
7077 {{23, 5, 2, 7, X, X}}}},
7078 // new line is (5, 7)
7079 {{
7080 {{8, 13, 16, 0, X, X}},
7081 {{9, 12, 1, 21, X, X}},
7082 {{10, 2, 17, 20, X, X}},
7083 {{3, 14, 18, 22, X, X}},
7084 {{11, 4, 0, 5, X, X}},
7085 {{15, 4, 1, 6, X, X}},
7086 {{19, 2, 5, 7, X, X}},
7087 {{23, 6, 7, 3, X, X}},
7088 }},
7089 // new line is (4, 9)
7090 {{
7091 {{8, 13, 16, 0, X, X}},
7092 {{9, 12, 1, 21, X, X}},
7093 {{10, 2, 17, 20, X, X}},
7094 {{3, 14, 18, 22, X, X}},
7095 {{11, 4, 5, 2, X, X}},
7096 {{15, 6, 7, 3, X, X}},
7097 {{19, 5, 0, 6, X, X}},
7098 {{23, 1, 4, 7, X, X}},
7099 }}}};
7100
7101 // the 4 faces of the reference tet are defined by 3
7102 // vertices each and follow the order of the unit cell
7103 static constexpr ::ndarray<unsigned int, 4, 3>
7104 reference_cell_face_vertices = {
7105 {{{0, 1, 2}}, {{1, 0, 3}}, {{0, 2, 3}}, {{2, 1, 3}}}};
7106
7107 // the 8 child tets are each defined by 4 vertices
7108 // the ordering of the tets has to be consistent with above
7109 // the ordering within the tets is given by the reference
7110 // tet i.e. looking at the fifth line the first 3 vertices
7111 // are given by face 11, the last vertex is the remaining of
7112 // the tet
7113 static constexpr ::ndarray<unsigned int, 3, 8, 4>
7114 cell_vertices_tet = {{// new line is (6,8)
7115 {{{{0, 4, 6, 7}},
7116 {{4, 1, 5, 8}},
7117 {{6, 5, 2, 9}},
7118 {{7, 8, 9, 3}},
7119 {{4, 5, 6, 8}},
7120 {{4, 7, 8, 6}},
7121 {{6, 9, 7, 8}},
7122 {{5, 8, 9, 6}}}},
7123 // new line is (5,7)
7124 {{{{0, 4, 6, 7}},
7125 {{4, 1, 5, 8}},
7126 {{6, 5, 2, 9}},
7127 {{7, 8, 9, 3}},
7128 {{4, 5, 6, 7}},
7129 {{4, 7, 8, 5}},
7130 {{6, 9, 7, 5}},
7131 {{5, 8, 9, 7}}}},
7132 // new line is (4,9)
7133 {{{{0, 4, 6, 7}},
7134 {{4, 1, 5, 8}},
7135 {{6, 5, 2, 9}},
7136 {{7, 8, 9, 3}},
7137 {{4, 5, 6, 9}},
7138 {{4, 7, 8, 9}},
7139 {{6, 9, 7, 4}},
7140 {{5, 8, 9, 4}}}}}};
7141
7142
7143 const auto &cell_quads =
7144 (reference_cell_type == ReferenceCells::Hexahedron) ?
7145 cell_quads_hex :
7146 cell_quads_tet[chosen_line_tetrahedron];
7147
7148 for (unsigned int c = 0;
7149 c < GeometryInfo<dim>::max_children_per_cell;
7150 ++c)
7151 {
7152 auto &new_hex = new_hexes[c];
7153
7154 if (new_hex->n_faces() == 4)
7155 {
7156 new_hex->set_bounding_object_indices(
7157 {quad_indices[cell_quads[c][0]],
7158 quad_indices[cell_quads[c][1]],
7159 quad_indices[cell_quads[c][2]],
7160 quad_indices[cell_quads[c][3]]});
7161
7162
7163 // for tets, we need to go through the faces and
7164 // figure the orientation out the hard way
7165 for (const auto f : new_hex->face_indices())
7166 {
7167 const auto &face = new_hex->face(f);
7168
7169 Assert(face->n_vertices() == 3,
7171
7172 const std::array<unsigned int, 3> vertices_0 = {
7173 {face->vertex_index(0),
7174 face->vertex_index(1),
7175 face->vertex_index(2)}};
7176
7177 const auto &new_hex_vertices =
7178 cell_vertices_tet[chosen_line_tetrahedron][c];
7179 const auto face_f_vertices =
7180 reference_cell_face_vertices[f];
7181
7182 const std::array<unsigned int, 3> vertices_1 = {
7183 {
7185 [new_hex_vertices[face_f_vertices[0]]],
7187 [new_hex_vertices[face_f_vertices[1]]],
7189 [new_hex_vertices[face_f_vertices[2]]],
7190 }};
7191
7192 new_hex->set_combined_face_orientation(
7193 f,
7194 face->reference_cell()
7195 .get_combined_orientation(
7196 make_array_view(vertices_1),
7197 make_array_view(vertices_0)));
7198 }
7199 }
7200 else if (new_hex->n_faces() == 6)
7201 new_hex->set_bounding_object_indices(
7202 {quad_indices[cell_quads[c][0]],
7203 quad_indices[cell_quads[c][1]],
7204 quad_indices[cell_quads[c][2]],
7205 quad_indices[cell_quads[c][3]],
7206 quad_indices[cell_quads[c][4]],
7207 quad_indices[cell_quads[c][5]]});
7208 else
7210 }
7211
7212 // for hexes, we can simply inherit the orientation values
7213 // from the parent on the outer faces; the inner faces can
7214 // be skipped as their orientation is always the default
7215 // one set above
7216 static constexpr ::ndarray<unsigned int, 6, 4>
7217 face_to_child_indices_hex{{{{0, 2, 4, 6}},
7218 {{1, 3, 5, 7}},
7219 {{0, 1, 4, 5}},
7220 {{2, 3, 6, 7}},
7221 {{0, 1, 2, 3}},
7222 {{4, 5, 6, 7}}}};
7223 if (hex->n_faces() == 6)
7224 for (const auto f : hex->face_indices())
7225 {
7226 const unsigned char combined_orientation =
7227 hex->combined_face_orientation(f);
7228 for (unsigned int c = 0; c < 4; ++c)
7229 new_hexes[face_to_child_indices_hex[f][c]]
7230 ->set_combined_face_orientation(
7231 f, combined_orientation);
7232 }
7233 }
7234 }
7235
7236 if (check_for_distorted_cells &&
7237 has_distorted_children<dim, spacedim>(hex))
7238 cells_with_distorted_children.distorted_cells.push_back(hex);
7239
7240 triangulation.signals.post_refinement_on_cell(hex);
7241 }
7242 }
7243
7244 triangulation.faces->quads.clear_user_data();
7245
7246 return cells_with_distorted_children;
7247 }
7248
7253 template <int spacedim>
7256 const bool check_for_distorted_cells)
7257 {
7258 const unsigned int dim = 3;
7259
7260 {
7261 bool flag_isotropic_mesh = true;
7263 cell = triangulation.begin(),
7264 endc = triangulation.end();
7265 for (; cell != endc; ++cell)
7266 if (cell->used())
7267 if (triangulation.get_anisotropic_refinement_flag() ||
7268 cell->refine_flag_set() == RefinementCase<dim>::cut_x ||
7269 cell->refine_flag_set() == RefinementCase<dim>::cut_y ||
7270 cell->refine_flag_set() == RefinementCase<dim>::cut_z ||
7271 cell->refine_flag_set() == RefinementCase<dim>::cut_xy ||
7272 cell->refine_flag_set() == RefinementCase<dim>::cut_xz ||
7273 cell->refine_flag_set() == RefinementCase<dim>::cut_yz)
7274 {
7275 flag_isotropic_mesh = false;
7276 break;
7277 }
7278
7279 if (flag_isotropic_mesh)
7280 return execute_refinement_isotropic(triangulation,
7281 check_for_distorted_cells);
7282 }
7283
7284 // this function probably also works for spacedim>3 but it
7285 // isn't tested. it will probably be necessary to pull new
7286 // vertices onto the manifold just as we do for the other
7287 // functions above.
7288 Assert(spacedim == 3, ExcNotImplemented());
7289
7290 // Check whether a new level is needed. We have to check for
7291 // this on the highest level only
7292 for (const auto &cell : triangulation.active_cell_iterators_on_level(
7293 triangulation.levels.size() - 1))
7294 if (cell->refine_flag_set())
7295 {
7296 triangulation.levels.push_back(
7297 std::make_unique<
7299 break;
7300 }
7301
7302
7303 // first clear user flags for quads and lines; we're going to
7304 // use them to flag which lines and quads need refinement
7305 triangulation.faces->quads.clear_user_data();
7306
7309 line != triangulation.end_line();
7310 ++line)
7311 line->clear_user_flag();
7314 quad != triangulation.end_quad();
7315 ++quad)
7316 quad->clear_user_flag();
7317
7318 // create an array of face refine cases. User indices of faces
7319 // will be set to values corresponding with indices in this
7320 // array.
7321 const RefinementCase<dim - 1> face_refinement_cases[4] = {
7322 RefinementCase<dim - 1>::no_refinement,
7323 RefinementCase<dim - 1>::cut_x,
7324 RefinementCase<dim - 1>::cut_y,
7325 RefinementCase<dim - 1>::cut_xy};
7326
7327 // check how much space is needed on every level. We need not
7328 // check the highest level since either
7329 // - on the highest level no cells are flagged for refinement
7330 // - there are, but prepare_refinement added another empty
7331 // level which then is the highest level
7332
7333 // variables to hold the number of newly to be created
7334 // vertices, lines and quads. as these are stored globally,
7335 // declare them outside the loop over al levels. we need lines
7336 // and quads in pairs for refinement of old ones and lines and
7337 // quads, that can be stored as single ones, as they are newly
7338 // created in the inside of an existing cell
7339 unsigned int needed_vertices = 0;
7340 unsigned int needed_lines_single = 0;
7341 unsigned int needed_quads_single = 0;
7342 unsigned int needed_lines_pair = 0;
7343 unsigned int needed_quads_pair = 0;
7344 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
7345 {
7346 // count number of flagged cells on this level and compute
7347 // how many new vertices and new lines will be needed
7348 unsigned int new_cells = 0;
7349
7350 for (const auto &acell :
7351 triangulation.active_cell_iterators_on_level(level))
7352 if (acell->refine_flag_set())
7353 {
7354 RefinementCase<dim> ref_case = acell->refine_flag_set();
7355
7356 // now for interior vertices, lines and quads, which
7357 // are needed in any case
7358 if (ref_case == RefinementCase<dim>::cut_x ||
7359 ref_case == RefinementCase<dim>::cut_y ||
7360 ref_case == RefinementCase<dim>::cut_z)
7361 {
7362 ++needed_quads_single;
7363 new_cells += 2;
7364 triangulation.anisotropic_refinement = true;
7365 }
7366 else if (ref_case == RefinementCase<dim>::cut_xy ||
7367 ref_case == RefinementCase<dim>::cut_xz ||
7368 ref_case == RefinementCase<dim>::cut_yz)
7369 {
7370 ++needed_lines_single;
7371 needed_quads_single += 4;
7372 new_cells += 4;
7373 triangulation.anisotropic_refinement = true;
7374 }
7375 else if (ref_case == RefinementCase<dim>::cut_xyz)
7376 {
7377 ++needed_vertices;
7378 needed_lines_single += 6;
7379 needed_quads_single += 12;
7380 new_cells += 8;
7381 }
7382 else
7383 {
7384 // we should never get here
7386 }
7387
7388 // mark all faces for refinement; checking locally
7389 // if and how the neighbor would like to refine
7390 // these is difficult so we only flag them and after
7391 // visiting all cells, we decide which faces need
7392 // which refinement;
7393 for (const unsigned int face :
7395 {
7397 aface = acell->face(face);
7398 // get the RefineCase this faces has for the
7399 // given RefineCase of the cell
7400 RefinementCase<dim - 1> face_ref_case =
7402 ref_case,
7403 face,
7404 acell->face_orientation(face),
7405 acell->face_flip(face),
7406 acell->face_rotation(face));
7407 // only do something, if this face has to be
7408 // refined
7409 if (face_ref_case)
7410 {
7411 if (face_ref_case ==
7413 {
7414 if (aface->n_active_descendants() < 4)
7415 // we use user_flags to denote needed
7416 // isotropic refinement
7417 aface->set_user_flag();
7418 }
7419 else if (aface->refinement_case() != face_ref_case)
7420 // we use user_indices to denote needed
7421 // anisotropic refinement. note, that we
7422 // can have at most one anisotropic
7423 // refinement case for this face, as
7424 // otherwise prepare_refinement() would
7425 // have changed one of the cells to yield
7426 // isotropic refinement at this
7427 // face. therefore we set the user_index
7428 // uniquely
7429 {
7430 Assert(aface->refinement_case() ==
7432 dim - 1>::isotropic_refinement ||
7433 aface->refinement_case() ==
7436 aface->set_user_index(face_ref_case);
7437 }
7438 }
7439 } // for all faces
7440
7441 // flag all lines, that have to be refined
7442 for (unsigned int line = 0;
7443 line < GeometryInfo<dim>::lines_per_cell;
7444 ++line)
7446 line) &&
7447 !acell->line(line)->has_children())
7448 acell->line(line)->set_user_flag();
7449
7450 } // if refine_flag set and for all cells on this level
7451
7452
7453 // count number of used cells on the next higher level
7454 const unsigned int used_cells =
7455 std::count(triangulation.levels[level + 1]->cells.used.begin(),
7456 triangulation.levels[level + 1]->cells.used.end(),
7457 true);
7458
7459
7460 // reserve space for the used_cells cells already existing
7461 // on the next higher level as well as for the
7462 // 8*flagged_cells that will be created on that level
7463 reserve_space(*triangulation.levels[level + 1],
7464 used_cells + new_cells,
7465 3,
7466 spacedim);
7467 // reserve space for 8*flagged_cells new hexes on the next
7468 // higher level
7469 reserve_space(triangulation.levels[level + 1]->cells, new_cells);
7470 } // for all levels
7471 // now count the quads and lines which were flagged for
7472 // refinement
7475 quad != triangulation.end_quad();
7476 ++quad)
7477 {
7478 if (quad->user_flag_set())
7479 {
7480 // isotropic refinement: 1 interior vertex, 4 quads
7481 // and 4 interior lines. we store the interior lines
7482 // in pairs in case the face is already or will be
7483 // refined anisotropically
7484 needed_quads_pair += 4;
7485 needed_lines_pair += 4;
7486 needed_vertices += 1;
7487 }
7488 if (quad->user_index())
7489 {
7490 // anisotropic refinement: 1 interior
7491 // line and two quads
7492 needed_quads_pair += 2;
7493 needed_lines_single += 1;
7494 // there is a kind of complicated situation here which
7495 // requires our attention. if the quad is refined
7496 // isotropcally, two of the interior lines will get a
7497 // new mother line - the interior line of our
7498 // anisotropically refined quad. if those two lines
7499 // are not consecutive, we cannot do so and have to
7500 // replace them by two lines that are consecutive. we
7501 // try to avoid that situation, but it may happen
7502 // nevertheless through repeated refinement and
7503 // coarsening. thus we have to check here, as we will
7504 // need some additional space to store those new lines
7505 // in case we need them...
7506 if (quad->has_children())
7507 {
7508 Assert(quad->refinement_case() ==
7511 if ((face_refinement_cases[quad->user_index()] ==
7513 (quad->child(0)->line_index(1) + 1 !=
7514 quad->child(2)->line_index(1))) ||
7515 (face_refinement_cases[quad->user_index()] ==
7517 (quad->child(0)->line_index(3) + 1 !=
7518 quad->child(1)->line_index(3))))
7519 needed_lines_pair += 2;
7520 }
7521 }
7522 }
7523
7526 line != triangulation.end_line();
7527 ++line)
7528 if (line->user_flag_set())
7529 {
7530 needed_lines_pair += 2;
7531 needed_vertices += 1;
7532 }
7533
7534 // reserve space for needed_lines new lines stored in pairs
7535 reserve_space(triangulation.faces->lines,
7536 needed_lines_pair,
7537 needed_lines_single);
7538 // reserve space for needed_quads new quads stored in pairs
7540 needed_quads_pair,
7541 needed_quads_single);
7542 reserve_space(triangulation.faces->quads,
7543 needed_quads_pair,
7544 needed_quads_single);
7545
7546
7547 // add to needed vertices how many vertices are already in use
7548 needed_vertices += std::count(triangulation.vertices_used.begin(),
7549 triangulation.vertices_used.end(),
7550 true);
7551 // if we need more vertices: create them, if not: leave the
7552 // array as is, since shrinking is not really possible because
7553 // some of the vertices at the end may be in use
7554 if (needed_vertices > triangulation.vertices.size())
7555 {
7556 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
7557 triangulation.vertices_used.resize(needed_vertices, false);
7558 }
7559
7560
7561 //-----------------------------------------
7562 // Before we start with the actual refinement, we do some
7563 // sanity checks if in debug mode. especially, we try to catch
7564 // the notorious problem with lines being twice refined,
7565 // i.e. there are cells adjacent at one line ("around the
7566 // edge", but not at a face), with two cells differing by more
7567 // than one refinement level
7568 //
7569 // this check is very simple to implement here, since we have
7570 // all lines flagged if they shall be refined
7571#ifdef DEBUG
7572 for (const auto &cell : triangulation.active_cell_iterators())
7573 if (!cell->refine_flag_set())
7574 for (unsigned int line = 0;
7575 line < GeometryInfo<dim>::lines_per_cell;
7576 ++line)
7577 if (cell->line(line)->has_children())
7578 for (unsigned int c = 0; c < 2; ++c)
7579 Assert(cell->line(line)->child(c)->user_flag_set() == false,
7581#endif
7582
7583 //-----------------------------------------
7584 // Do refinement on every level
7585 //
7586 // To make life a bit easier, we first refine those lines and
7587 // quads that were flagged for refinement and then compose the
7588 // newly to be created cells.
7589 //
7590 // index of next unused vertex
7591 unsigned int next_unused_vertex = 0;
7592
7593 // first for lines
7594 {
7595 // only active objects can be refined further
7598 endl = triangulation.end_line();
7600 next_unused_line = triangulation.begin_raw_line();
7601
7602 for (; line != endl; ++line)
7603 if (line->user_flag_set())
7604 {
7605 // this line needs to be refined
7606
7607 // find the next unused vertex and set it
7608 // appropriately
7609 while (triangulation.vertices_used[next_unused_vertex] == true)
7610 ++next_unused_vertex;
7611 Assert(
7612 next_unused_vertex < triangulation.vertices.size(),
7613 ExcMessage(
7614 "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."));
7615 triangulation.vertices_used[next_unused_vertex] = true;
7616
7617 triangulation.vertices[next_unused_vertex] = line->center(true);
7618
7619 // now that we created the right point, make up the
7620 // two child lines (++ takes care of the end of the
7621 // vector)
7622 next_unused_line =
7623 triangulation.faces->lines.template next_free_pair_object<1>(
7625 Assert(next_unused_line.state() == IteratorState::valid,
7627
7628 // now we found two consecutive unused lines, such
7629 // that the children of a line will be consecutive.
7630 // then set the child pointer of the present line
7631 line->set_children(0, next_unused_line->index());
7632
7633 // set the two new lines
7635 children[2] = {next_unused_line, ++next_unused_line};
7636
7637 // some tests; if any of the iterators should be
7638 // invalid, then already dereferencing will fail
7639 AssertIsNotUsed(children[0]);
7640 AssertIsNotUsed(children[1]);
7641
7642 children[0]->set_bounding_object_indices(
7643 {line->vertex_index(0), next_unused_vertex});
7644 children[1]->set_bounding_object_indices(
7645 {next_unused_vertex, line->vertex_index(1)});
7646
7647 children[0]->set_used_flag();
7648 children[1]->set_used_flag();
7649 children[0]->clear_children();
7650 children[1]->clear_children();
7651 children[0]->clear_user_data();
7652 children[1]->clear_user_data();
7653 children[0]->clear_user_flag();
7654 children[1]->clear_user_flag();
7655
7656 children[0]->set_boundary_id_internal(line->boundary_id());
7657 children[1]->set_boundary_id_internal(line->boundary_id());
7658
7659 children[0]->set_manifold_id(line->manifold_id());
7660 children[1]->set_manifold_id(line->manifold_id());
7661
7662 // finally clear flag
7663 // indicating the need
7664 // for refinement
7665 line->clear_user_flag();
7666 }
7667 }
7668
7669
7670 //-------------------------------------
7671 // now refine marked quads
7672 //-------------------------------------
7673
7674 // here we encounter several cases:
7675
7676 // a) the quad is unrefined and shall be refined isotropically
7677
7678 // b) the quad is unrefined and shall be refined
7679 // anisotropically
7680
7681 // c) the quad is unrefined and shall be refined both
7682 // anisotropically and isotropically (this is reduced to case
7683 // b) and then case b) for the children again)
7684
7685 // d) the quad is refined anisotropically and shall be refined
7686 // isotropically (this is reduced to case b) for the
7687 // anisotropic children)
7688
7689 // e) the quad is refined isotropically and shall be refined
7690 // anisotropically (this is transformed to case c), however we
7691 // might have to renumber/rename children...)
7692
7693 // we need a loop in cases c) and d), as the anisotropic
7694 // children might have a lower index than the mother quad
7695 for (unsigned int loop = 0; loop < 2; ++loop)
7696 {
7697 // usually, only active objects can be refined
7698 // further. however, in cases d) and e) that is not true,
7699 // so we have to use 'normal' iterators here
7701 quad = triangulation.begin_quad(),
7702 endq = triangulation.end_quad();
7704 next_unused_line = triangulation.begin_raw_line();
7706 next_unused_quad = triangulation.begin_raw_quad();
7707
7708 for (; quad != endq; ++quad)
7709 {
7710 if (quad->user_index())
7711 {
7712 RefinementCase<dim - 1> aniso_quad_ref_case =
7713 face_refinement_cases[quad->user_index()];
7714 // there is one unlikely event here, where we
7715 // already have refind the face: if the face was
7716 // refined anisotropically and we want to refine
7717 // it isotropically, both children are flagged for
7718 // anisotropic refinement. however, if those
7719 // children were already flagged for anisotropic
7720 // refinement, they might already be processed and
7721 // refined.
7722 if (aniso_quad_ref_case == quad->refinement_case())
7723 continue;
7724
7725 Assert(quad->refinement_case() ==
7727 quad->refinement_case() ==
7730
7731 // this quad needs to be refined anisotropically
7732 Assert(quad->user_index() ==
7734 quad->user_index() ==
7737
7738 // make the new line interior to the quad
7740 new_line;
7741
7742 new_line =
7743 triangulation.faces->lines
7744 .template next_free_single_object<1>(triangulation);
7745 AssertIsNotUsed(new_line);
7746
7747 // first collect the
7748 // indices of the vertices:
7749 // *--1--*
7750 // | | |
7751 // | | | cut_x
7752 // | | |
7753 // *--0--*
7754 //
7755 // *-----*
7756 // | |
7757 // 0-----1 cut_y
7758 // | |
7759 // *-----*
7760 unsigned int vertex_indices[2];
7761 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
7762 {
7763 vertex_indices[0] =
7764 quad->line(2)->child(0)->vertex_index(1);
7765 vertex_indices[1] =
7766 quad->line(3)->child(0)->vertex_index(1);
7767 }
7768 else
7769 {
7770 vertex_indices[0] =
7771 quad->line(0)->child(0)->vertex_index(1);
7772 vertex_indices[1] =
7773 quad->line(1)->child(0)->vertex_index(1);
7774 }
7775
7776 new_line->set_bounding_object_indices(
7778 new_line->set_used_flag();
7779 new_line->clear_user_flag();
7780 new_line->clear_user_data();
7781 new_line->clear_children();
7782 new_line->set_boundary_id_internal(quad->boundary_id());
7783 new_line->set_manifold_id(quad->manifold_id());
7784
7785 // child 0 and 1 of a line are switched if the
7786 // line orientation is false. set up a miniature
7787 // table, indicating which child to take for line
7788 // orientations false and true. first index: child
7789 // index in standard orientation, second index:
7790 // line orientation
7791 const unsigned int index[2][2] = {
7792 {1, 0}, // child 0, line_orientation=false and true
7793 {0, 1}}; // child 1, line_orientation=false and true
7794
7795 // find some space (consecutive) for the two newly
7796 // to be created quads.
7798 new_quads[2];
7799
7800 next_unused_quad =
7801 triangulation.faces->quads
7802 .template next_free_pair_object<2>(triangulation);
7803 new_quads[0] = next_unused_quad;
7804 AssertIsNotUsed(new_quads[0]);
7805
7806 ++next_unused_quad;
7807 new_quads[1] = next_unused_quad;
7808 AssertIsNotUsed(new_quads[1]);
7809
7810 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
7811 {
7812 new_quads[0]->set_bounding_object_indices(
7813 {static_cast<int>(quad->line_index(0)),
7814 new_line->index(),
7815 quad->line(2)
7816 ->child(index[0][quad->line_orientation(2)])
7817 ->index(),
7818 quad->line(3)
7819 ->child(index[0][quad->line_orientation(3)])
7820 ->index()});
7821 new_quads[1]->set_bounding_object_indices(
7822 {new_line->index(),
7823 static_cast<int>(quad->line_index(1)),
7824 quad->line(2)
7825 ->child(index[1][quad->line_orientation(2)])
7826 ->index(),
7827 quad->line(3)
7828 ->child(index[1][quad->line_orientation(3)])
7829 ->index()});
7830 }
7831 else
7832 {
7833 new_quads[0]->set_bounding_object_indices(
7834 {quad->line(0)
7835 ->child(index[0][quad->line_orientation(0)])
7836 ->index(),
7837 quad->line(1)
7838 ->child(index[0][quad->line_orientation(1)])
7839 ->index(),
7840 static_cast<int>(quad->line_index(2)),
7841 new_line->index()});
7842 new_quads[1]->set_bounding_object_indices(
7843 {quad->line(0)
7844 ->child(index[1][quad->line_orientation(0)])
7845 ->index(),
7846 quad->line(1)
7847 ->child(index[1][quad->line_orientation(1)])
7848 ->index(),
7849 new_line->index(),
7850 static_cast<int>(quad->line_index(3))});
7851 }
7852
7853 for (const auto &new_quad : new_quads)
7854 {
7855 new_quad->set_used_flag();
7856 new_quad->clear_user_flag();
7857 new_quad->clear_user_data();
7858 new_quad->clear_children();
7859 new_quad->set_boundary_id_internal(quad->boundary_id());
7860 new_quad->set_manifold_id(quad->manifold_id());
7861 // set all line orientations to true, change
7862 // this after the loop, as we have to consider
7863 // different lines for each child
7864 for (unsigned int j = 0;
7865 j < GeometryInfo<dim>::lines_per_face;
7866 ++j)
7867 new_quad->set_line_orientation(j, true);
7868 }
7869 // now set the line orientation of children of
7870 // outer lines correctly, the lines in the
7871 // interior of the refined quad are automatically
7872 // oriented conforming to the standard
7873 new_quads[0]->set_line_orientation(
7874 0, quad->line_orientation(0));
7875 new_quads[0]->set_line_orientation(
7876 2, quad->line_orientation(2));
7877 new_quads[1]->set_line_orientation(
7878 1, quad->line_orientation(1));
7879 new_quads[1]->set_line_orientation(
7880 3, quad->line_orientation(3));
7881 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
7882 {
7883 new_quads[0]->set_line_orientation(
7884 3, quad->line_orientation(3));
7885 new_quads[1]->set_line_orientation(
7886 2, quad->line_orientation(2));
7887 }
7888 else
7889 {
7890 new_quads[0]->set_line_orientation(
7891 1, quad->line_orientation(1));
7892 new_quads[1]->set_line_orientation(
7893 0, quad->line_orientation(0));
7894 }
7895
7896 // test, whether this face is refined
7897 // isotropically already. if so, set the correct
7898 // children pointers.
7899 if (quad->refinement_case() ==
7900 RefinementCase<dim - 1>::cut_xy)
7901 {
7902 // we will put a new refinemnt level of
7903 // anisotropic refinement between the
7904 // unrefined and isotropically refined quad
7905 // ending up with the same fine quads but
7906 // introducing anisotropically refined ones as
7907 // children of the unrefined quad and mother
7908 // cells of the original fine ones.
7909
7910 // this process includes the creation of a new
7911 // middle line which we will assign as the
7912 // mother line of two of the existing inner
7913 // lines. If those inner lines are not
7914 // consecutive in memory, we won't find them
7915 // later on, so we have to create new ones
7916 // instead and replace all occurrences of the
7917 // old ones with those new ones. As this is
7918 // kind of ugly, we hope we don't have to do
7919 // it often...
7921 old_child[2];
7922 if (aniso_quad_ref_case ==
7924 {
7925 old_child[0] = quad->child(0)->line(1);
7926 old_child[1] = quad->child(2)->line(1);
7927 }
7928 else
7929 {
7930 Assert(aniso_quad_ref_case ==
7933
7934 old_child[0] = quad->child(0)->line(3);
7935 old_child[1] = quad->child(1)->line(3);
7936 }
7937
7938 if (old_child[0]->index() + 1 != old_child[1]->index())
7939 {
7940 // this is exactly the ugly case we taked
7941 // about. so, no coimplaining, lets get
7942 // two new lines and copy all info
7943 typename Triangulation<dim,
7944 spacedim>::raw_line_iterator
7945 new_child[2];
7946
7947 new_child[0] = new_child[1] =
7948 triangulation.faces->lines
7949 .template next_free_pair_object<1>(
7951 ++new_child[1];
7952
7953 new_child[0]->set_used_flag();
7954 new_child[1]->set_used_flag();
7955
7956 const int old_index_0 = old_child[0]->index(),
7957 old_index_1 = old_child[1]->index(),
7958 new_index_0 = new_child[0]->index(),
7959 new_index_1 = new_child[1]->index();
7960
7961 // loop over all quads and replace the old
7962 // lines
7963 for (unsigned int q = 0;
7964 q < triangulation.faces->quads.n_objects();
7965 ++q)
7966 for (unsigned int l = 0;
7967 l < GeometryInfo<dim>::lines_per_face;
7968 ++l)
7969 {
7970 const int this_index =
7971 triangulation.faces->quads
7972 .get_bounding_object_indices(q)[l];
7973 if (this_index == old_index_0)
7974 triangulation.faces->quads
7975 .get_bounding_object_indices(q)[l] =
7976 new_index_0;
7977 else if (this_index == old_index_1)
7978 triangulation.faces->quads
7979 .get_bounding_object_indices(q)[l] =
7980 new_index_1;
7981 }
7982 // now we have to copy all information of
7983 // the two lines
7984 for (unsigned int i = 0; i < 2; ++i)
7985 {
7986 Assert(!old_child[i]->has_children(),
7988
7989 new_child[i]->set_bounding_object_indices(
7990 {old_child[i]->vertex_index(0),
7991 old_child[i]->vertex_index(1)});
7992 new_child[i]->set_boundary_id_internal(
7993 old_child[i]->boundary_id());
7994 new_child[i]->set_manifold_id(
7995 old_child[i]->manifold_id());
7996 new_child[i]->set_user_index(
7997 old_child[i]->user_index());
7998 if (old_child[i]->user_flag_set())
7999 new_child[i]->set_user_flag();
8000 else
8001 new_child[i]->clear_user_flag();
8002
8003 new_child[i]->clear_children();
8004
8005 old_child[i]->clear_user_flag();
8006 old_child[i]->clear_user_index();
8007 old_child[i]->clear_used_flag();
8008 }
8009 }
8010 // now that we cared about the lines, go on
8011 // with the quads themselves, where we might
8012 // encounter similar situations...
8013 if (aniso_quad_ref_case ==
8015 {
8016 new_line->set_children(
8017 0, quad->child(0)->line_index(1));
8018 Assert(new_line->child(1) ==
8019 quad->child(2)->line(1),
8021 // now evereything is quite
8022 // complicated. we have the children
8023 // numbered according to
8024 //
8025 // *---*---*
8026 // |n+2|n+3|
8027 // *---*---*
8028 // | n |n+1|
8029 // *---*---*
8030 //
8031 // from the original isotropic
8032 // refinement. we have to reorder them as
8033 //
8034 // *---*---*
8035 // |n+1|n+3|
8036 // *---*---*
8037 // | n |n+2|
8038 // *---*---*
8039 //
8040 // such that n and n+1 are consecutive
8041 // children of m and n+2 and n+3 are
8042 // consecutive children of m+1, where m
8043 // and m+1 are given as in
8044 //
8045 // *---*---*
8046 // | | |
8047 // | m |m+1|
8048 // | | |
8049 // *---*---*
8050 //
8051 // this is a bit ugly, of course: loop
8052 // over all cells on all levels and look
8053 // for faces n+1 (switch_1) and n+2
8054 // (switch_2).
8055 const typename Triangulation<dim, spacedim>::
8056 quad_iterator switch_1 = quad->child(1),
8057 switch_2 = quad->child(2);
8058 const int switch_1_index = switch_1->index();
8059 const int switch_2_index = switch_2->index();
8060 for (unsigned int l = 0;
8061 l < triangulation.levels.size();
8062 ++l)
8063 for (unsigned int h = 0;
8064 h <
8065 triangulation.levels[l]->cells.n_objects();
8066 ++h)
8067 for (const unsigned int q :
8069 {
8070 const int face_index =
8072 ->cells.get_bounding_object_indices(
8073 h)[q];
8074 if (face_index == switch_1_index)
8075 triangulation.levels[l]
8076 ->cells.get_bounding_object_indices(
8077 h)[q] = switch_2_index;
8078 else if (face_index == switch_2_index)
8079 triangulation.levels[l]
8080 ->cells.get_bounding_object_indices(
8081 h)[q] = switch_1_index;
8082 }
8083 // now we have to copy all information of
8084 // the two quads
8085 const unsigned int switch_1_lines[4] = {
8086 switch_1->line_index(0),
8087 switch_1->line_index(1),
8088 switch_1->line_index(2),
8089 switch_1->line_index(3)};
8090 const bool switch_1_line_orientations[4] = {
8091 switch_1->line_orientation(0),
8092 switch_1->line_orientation(1),
8093 switch_1->line_orientation(2),
8094 switch_1->line_orientation(3)};
8095 const types::boundary_id switch_1_boundary_id =
8096 switch_1->boundary_id();
8097 const unsigned int switch_1_user_index =
8098 switch_1->user_index();
8099 const bool switch_1_user_flag =
8100 switch_1->user_flag_set();
8101 const RefinementCase<dim - 1>
8102 switch_1_refinement_case =
8103 switch_1->refinement_case();
8104 const int switch_1_first_child_pair =
8105 (switch_1_refinement_case ?
8106 switch_1->child_index(0) :
8107 -1);
8108 const int switch_1_second_child_pair =
8109 (switch_1_refinement_case ==
8110 RefinementCase<dim - 1>::cut_xy ?
8111 switch_1->child_index(2) :
8112 -1);
8113
8114 switch_1->set_bounding_object_indices(
8115 {switch_2->line_index(0),
8116 switch_2->line_index(1),
8117 switch_2->line_index(2),
8118 switch_2->line_index(3)});
8119 switch_1->set_line_orientation(
8120 0, switch_2->line_orientation(0));
8121 switch_1->set_line_orientation(
8122 1, switch_2->line_orientation(1));
8123 switch_1->set_line_orientation(
8124 2, switch_2->line_orientation(2));
8125 switch_1->set_line_orientation(
8126 3, switch_2->line_orientation(3));
8127 switch_1->set_boundary_id_internal(
8128 switch_2->boundary_id());
8129 switch_1->set_manifold_id(switch_2->manifold_id());
8130 switch_1->set_user_index(switch_2->user_index());
8131 if (switch_2->user_flag_set())
8132 switch_1->set_user_flag();
8133 else
8134 switch_1->clear_user_flag();
8135 switch_1->clear_refinement_case();
8136 switch_1->set_refinement_case(
8137 switch_2->refinement_case());
8138 switch_1->clear_children();
8139 if (switch_2->refinement_case())
8140 switch_1->set_children(0,
8141 switch_2->child_index(0));
8142 if (switch_2->refinement_case() ==
8143 RefinementCase<dim - 1>::cut_xy)
8144 switch_1->set_children(2,
8145 switch_2->child_index(2));
8146
8147 switch_2->set_bounding_object_indices(
8148 {switch_1_lines[0],
8149 switch_1_lines[1],
8150 switch_1_lines[2],
8151 switch_1_lines[3]});
8152 switch_2->set_line_orientation(
8153 0, switch_1_line_orientations[0]);
8154 switch_2->set_line_orientation(
8155 1, switch_1_line_orientations[1]);
8156 switch_2->set_line_orientation(
8157 2, switch_1_line_orientations[2]);
8158 switch_2->set_line_orientation(
8159 3, switch_1_line_orientations[3]);
8160 switch_2->set_boundary_id_internal(
8161 switch_1_boundary_id);
8162 switch_2->set_manifold_id(switch_1->manifold_id());
8163 switch_2->set_user_index(switch_1_user_index);
8164 if (switch_1_user_flag)
8165 switch_2->set_user_flag();
8166 else
8167 switch_2->clear_user_flag();
8168 switch_2->clear_refinement_case();
8169 switch_2->set_refinement_case(
8170 switch_1_refinement_case);
8171 switch_2->clear_children();
8172 switch_2->set_children(0,
8173 switch_1_first_child_pair);
8174 switch_2->set_children(2,
8175 switch_1_second_child_pair);
8176
8177 new_quads[0]->set_refinement_case(
8179 new_quads[0]->set_children(0, quad->child_index(0));
8180 new_quads[1]->set_refinement_case(
8182 new_quads[1]->set_children(0, quad->child_index(2));
8183 }
8184 else
8185 {
8186 new_quads[0]->set_refinement_case(
8188 new_quads[0]->set_children(0, quad->child_index(0));
8189 new_quads[1]->set_refinement_case(
8191 new_quads[1]->set_children(0, quad->child_index(2));
8192 new_line->set_children(
8193 0, quad->child(0)->line_index(3));
8194 Assert(new_line->child(1) ==
8195 quad->child(1)->line(3),
8197 }
8198 quad->clear_children();
8199 }
8200
8201 // note these quads as children to the present one
8202 quad->set_children(0, new_quads[0]->index());
8203
8204 quad->set_refinement_case(aniso_quad_ref_case);
8205
8206 // finally clear flag indicating the need for
8207 // refinement
8208 quad->clear_user_data();
8209 } // if (anisotropic refinement)
8210
8211 if (quad->user_flag_set())
8212 {
8213 // this quad needs to be refined isotropically
8214
8215 // first of all: we only get here in the first run
8216 // of the loop
8217 Assert(loop == 0, ExcInternalError());
8218
8219 // find the next unused vertex. we'll need this in
8220 // any case
8221 while (triangulation.vertices_used[next_unused_vertex] ==
8222 true)
8223 ++next_unused_vertex;
8224 Assert(
8225 next_unused_vertex < triangulation.vertices.size(),
8226 ExcMessage(
8227 "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."));
8228
8229 // now: if the quad is refined anisotropically
8230 // already, set the anisotropic refinement flag
8231 // for both children. Additionally, we have to
8232 // refine the inner line, as it is an outer line
8233 // of the two (anisotropic) children
8234 const RefinementCase<dim - 1> quad_ref_case =
8235 quad->refinement_case();
8236
8237 if (quad_ref_case == RefinementCase<dim - 1>::cut_x ||
8238 quad_ref_case == RefinementCase<dim - 1>::cut_y)
8239 {
8240 // set the 'opposite' refine case for children
8241 quad->child(0)->set_user_index(
8242 RefinementCase<dim - 1>::cut_xy - quad_ref_case);
8243 quad->child(1)->set_user_index(
8244 RefinementCase<dim - 1>::cut_xy - quad_ref_case);
8245 // refine the inner line
8247 middle_line;
8248 if (quad_ref_case == RefinementCase<dim - 1>::cut_x)
8249 middle_line = quad->child(0)->line(1);
8250 else
8251 middle_line = quad->child(0)->line(3);
8252
8253 // if the face has been refined
8254 // anisotropically in the last refinement step
8255 // it might be, that it is flagged already and
8256 // that the middle line is thus refined
8257 // already. if not create children.
8258 if (!middle_line->has_children())
8259 {
8260 // set the middle vertex
8261 // appropriately. double refinement of
8262 // quads can only happen in the interior
8263 // of the domain, so we need not care
8264 // about boundary quads here
8265 triangulation.vertices[next_unused_vertex] =
8266 middle_line->center(true);
8267 triangulation.vertices_used[next_unused_vertex] =
8268 true;
8269
8270 // now search a slot for the two
8271 // child lines
8272 next_unused_line =
8273 triangulation.faces->lines
8274 .template next_free_pair_object<1>(
8276
8277 // set the child pointer of the present
8278 // line
8279 middle_line->set_children(
8280 0, next_unused_line->index());
8281
8282 // set the two new lines
8283 const typename Triangulation<dim, spacedim>::
8284 raw_line_iterator children[2] = {
8285 next_unused_line, ++next_unused_line};
8286
8287 // some tests; if any of the iterators
8288 // should be invalid, then already
8289 // dereferencing will fail
8290 AssertIsNotUsed(children[0]);
8291 AssertIsNotUsed(children[1]);
8292
8293 children[0]->set_bounding_object_indices(
8294 {middle_line->vertex_index(0),
8295 next_unused_vertex});
8296 children[1]->set_bounding_object_indices(
8297 {next_unused_vertex,
8298 middle_line->vertex_index(1)});
8299
8300 children[0]->set_used_flag();
8301 children[1]->set_used_flag();
8302 children[0]->clear_children();
8303 children[1]->clear_children();
8304 children[0]->clear_user_data();
8305 children[1]->clear_user_data();
8306 children[0]->clear_user_flag();
8307 children[1]->clear_user_flag();
8308
8309 children[0]->set_boundary_id_internal(
8310 middle_line->boundary_id());
8311 children[1]->set_boundary_id_internal(
8312 middle_line->boundary_id());
8313
8314 children[0]->set_manifold_id(
8315 middle_line->manifold_id());
8316 children[1]->set_manifold_id(
8317 middle_line->manifold_id());
8318 }
8319 // now remove the flag from the quad and go to
8320 // the next quad, the actual refinement of the
8321 // quad takes place later on in this pass of
8322 // the loop or in the next one
8323 quad->clear_user_flag();
8324 continue;
8325 } // if (several refinement cases)
8326
8327 // if we got here, we have an unrefined quad and
8328 // have to do the usual work like in an purely
8329 // isotropic refinement
8330 Assert(quad_ref_case ==
8333
8334 // set the middle vertex appropriately: it might be that
8335 // the quad itself is not at the boundary, but that one of
8336 // its lines actually is. in this case, the newly created
8337 // vertices at the centers of the lines are not
8338 // necessarily the mean values of the adjacent vertices,
8339 // so do not compute the new vertex as the mean value of
8340 // the 4 vertices of the face, but rather as a weighted
8341 // mean value of the 8 vertices which we already have (the
8342 // four old ones, and the four ones inserted as middle
8343 // points for the four lines). summing up some more points
8344 // is generally cheaper than first asking whether one of
8345 // the lines is at the boundary
8346 //
8347 // note that the exact weights are chosen such as to
8348 // minimize the distortion of the four new quads from the
8349 // optimal shape. their description uses the formulas
8350 // underlying the TransfiniteInterpolationManifold
8351 // implementation
8352 triangulation.vertices[next_unused_vertex] =
8353 quad->center(true, true);
8354 triangulation.vertices_used[next_unused_vertex] = true;
8355
8356 // now that we created the right point, make up
8357 // the four lines interior to the quad (++ takes
8358 // care of the end of the vector)
8360 new_lines[4];
8361
8362 for (unsigned int i = 0; i < 4; ++i)
8363 {
8364 if (i % 2 == 0)
8365 // search a free pair of lines for 0. and
8366 // 2. line, so that two of them end up
8367 // together, which is necessary if later on
8368 // we want to refine the quad
8369 // anisotropically and the two lines end up
8370 // as children of new line
8371 next_unused_line =
8372 triangulation.faces->lines
8373 .template next_free_pair_object<1>(triangulation);
8374
8375 new_lines[i] = next_unused_line;
8376 ++next_unused_line;
8377
8378 AssertIsNotUsed(new_lines[i]);
8379 }
8380
8381 // set the data of the four lines. first collect
8382 // the indices of the five vertices:
8383 //
8384 // *--3--*
8385 // | | |
8386 // 0--4--1
8387 // | | |
8388 // *--2--*
8389 //
8390 // the lines are numbered as follows:
8391 //
8392 // *--*--*
8393 // | 1 |
8394 // *2-*-3*
8395 // | 0 |
8396 // *--*--*
8397
8398 const unsigned int vertex_indices[5] = {
8399 quad->line(0)->child(0)->vertex_index(1),
8400 quad->line(1)->child(0)->vertex_index(1),
8401 quad->line(2)->child(0)->vertex_index(1),
8402 quad->line(3)->child(0)->vertex_index(1),
8403 next_unused_vertex};
8404
8405 new_lines[0]->set_bounding_object_indices(
8407 new_lines[1]->set_bounding_object_indices(
8409 new_lines[2]->set_bounding_object_indices(
8411 new_lines[3]->set_bounding_object_indices(
8413
8414 for (const auto &new_line : new_lines)
8415 {
8416 new_line->set_used_flag();
8417 new_line->clear_user_flag();
8418 new_line->clear_user_data();
8419 new_line->clear_children();
8420 new_line->set_boundary_id_internal(quad->boundary_id());
8421 new_line->set_manifold_id(quad->manifold_id());
8422 }
8423
8424 // now for the quads. again, first collect some
8425 // data about the indices of the lines, with the
8426 // following numbering:
8427 //
8428 // .-6-.-7-.
8429 // 1 9 3
8430 // .-10.11-.
8431 // 0 8 2
8432 // .-4-.-5-.
8433
8434 // child 0 and 1 of a line are switched if the
8435 // line orientation is false. set up a miniature
8436 // table, indicating which child to take for line
8437 // orientations false and true. first index: child
8438 // index in standard orientation, second index:
8439 // line orientation
8440 const unsigned int index[2][2] = {
8441 {1, 0}, // child 0, line_orientation=false and true
8442 {0, 1}}; // child 1, line_orientation=false and true
8443
8444 const int line_indices[12] = {
8445 quad->line(0)
8446 ->child(index[0][quad->line_orientation(0)])
8447 ->index(),
8448 quad->line(0)
8449 ->child(index[1][quad->line_orientation(0)])
8450 ->index(),
8451 quad->line(1)
8452 ->child(index[0][quad->line_orientation(1)])
8453 ->index(),
8454 quad->line(1)
8455 ->child(index[1][quad->line_orientation(1)])
8456 ->index(),
8457 quad->line(2)
8458 ->child(index[0][quad->line_orientation(2)])
8459 ->index(),
8460 quad->line(2)
8461 ->child(index[1][quad->line_orientation(2)])
8462 ->index(),
8463 quad->line(3)
8464 ->child(index[0][quad->line_orientation(3)])
8465 ->index(),
8466 quad->line(3)
8467 ->child(index[1][quad->line_orientation(3)])
8468 ->index(),
8469 new_lines[0]->index(),
8470 new_lines[1]->index(),
8471 new_lines[2]->index(),
8472 new_lines[3]->index()};
8473
8474 // find some space (consecutive)
8475 // for the first two newly to be
8476 // created quads.
8478 new_quads[4];
8479
8480 next_unused_quad =
8481 triangulation.faces->quads
8482 .template next_free_pair_object<2>(triangulation);
8483
8484 new_quads[0] = next_unused_quad;
8485 AssertIsNotUsed(new_quads[0]);
8486
8487 ++next_unused_quad;
8488 new_quads[1] = next_unused_quad;
8489 AssertIsNotUsed(new_quads[1]);
8490
8491 next_unused_quad =
8492 triangulation.faces->quads
8493 .template next_free_pair_object<2>(triangulation);
8494 new_quads[2] = next_unused_quad;
8495 AssertIsNotUsed(new_quads[2]);
8496
8497 ++next_unused_quad;
8498 new_quads[3] = next_unused_quad;
8499 AssertIsNotUsed(new_quads[3]);
8500
8501 // note these quads as children to the present one
8502 quad->set_children(0, new_quads[0]->index());
8503 quad->set_children(2, new_quads[2]->index());
8504 quad->set_refinement_case(RefinementCase<2>::cut_xy);
8505
8506 new_quads[0]->set_bounding_object_indices(
8507 {line_indices[0],
8508 line_indices[8],
8509 line_indices[4],
8510 line_indices[10]});
8511 new_quads[1]->set_bounding_object_indices(
8512 {line_indices[8],
8513 line_indices[2],
8514 line_indices[5],
8515 line_indices[11]});
8516 new_quads[2]->set_bounding_object_indices(
8517 {line_indices[1],
8518 line_indices[9],
8519 line_indices[10],
8520 line_indices[6]});
8521 new_quads[3]->set_bounding_object_indices(
8522 {line_indices[9],
8523 line_indices[3],
8524 line_indices[11],
8525 line_indices[7]});
8526 for (const auto &new_quad : new_quads)
8527 {
8528 new_quad->set_used_flag();
8529 new_quad->clear_user_flag();
8530 new_quad->clear_user_data();
8531 new_quad->clear_children();
8532 new_quad->set_boundary_id_internal(quad->boundary_id());
8533 new_quad->set_manifold_id(quad->manifold_id());
8534 // set all line orientations to true, change
8535 // this after the loop, as we have to consider
8536 // different lines for each child
8537 for (unsigned int j = 0;
8538 j < GeometryInfo<dim>::lines_per_face;
8539 ++j)
8540 new_quad->set_line_orientation(j, true);
8541 }
8542 // now set the line orientation of children of
8543 // outer lines correctly, the lines in the
8544 // interior of the refined quad are automatically
8545 // oriented conforming to the standard
8546 new_quads[0]->set_line_orientation(
8547 0, quad->line_orientation(0));
8548 new_quads[0]->set_line_orientation(
8549 2, quad->line_orientation(2));
8550 new_quads[1]->set_line_orientation(
8551 1, quad->line_orientation(1));
8552 new_quads[1]->set_line_orientation(
8553 2, quad->line_orientation(2));
8554 new_quads[2]->set_line_orientation(
8555 0, quad->line_orientation(0));
8556 new_quads[2]->set_line_orientation(
8557 3, quad->line_orientation(3));
8558 new_quads[3]->set_line_orientation(
8559 1, quad->line_orientation(1));
8560 new_quads[3]->set_line_orientation(
8561 3, quad->line_orientation(3));
8562
8563 // finally clear flag indicating the need for
8564 // refinement
8565 quad->clear_user_flag();
8566 } // if (isotropic refinement)
8567 } // for all quads
8568 } // looped two times over all quads, all quads refined now
8569
8570 //---------------------------------
8571 // Now, finally, set up the new
8572 // cells
8573 //---------------------------------
8574
8576 cells_with_distorted_children;
8577
8578 for (unsigned int level = 0; level != triangulation.levels.size() - 1;
8579 ++level)
8580 {
8581 // only active objects can be refined further; remember
8582 // that we won't operate on the finest level, so
8583 // triangulation.begin_*(level+1) is allowed
8586 endh = triangulation.begin_active_hex(level + 1);
8588 next_unused_hex = triangulation.begin_raw_hex(level + 1);
8589
8590 for (; hex != endh; ++hex)
8591 if (hex->refine_flag_set())
8592 {
8593 // this hex needs to be refined
8594
8595 // clear flag indicating the need for refinement. do
8596 // it here already, since we can't do it anymore
8597 // once the cell has children
8598 const RefinementCase<dim> ref_case = hex->refine_flag_set();
8599 hex->clear_refine_flag();
8600 hex->set_refinement_case(ref_case);
8601
8602 // depending on the refine case we might have to
8603 // create additional vertices, lines and quads
8604 // interior of the hex before the actual children
8605 // can be set up.
8606
8607 // in a first step: reserve the needed space for
8608 // lines, quads and hexes and initialize them
8609 // correctly
8610
8611 unsigned int n_new_lines = 0;
8612 unsigned int n_new_quads = 0;
8613 unsigned int n_new_hexes = 0;
8614 switch (ref_case)
8615 {
8619 n_new_lines = 0;
8620 n_new_quads = 1;
8621 n_new_hexes = 2;
8622 break;
8626 n_new_lines = 1;
8627 n_new_quads = 4;
8628 n_new_hexes = 4;
8629 break;
8631 n_new_lines = 6;
8632 n_new_quads = 12;
8633 n_new_hexes = 8;
8634 break;
8635 default:
8637 break;
8638 }
8639
8640 // find some space for the newly to be created
8641 // interior lines and initialize them.
8642 std::vector<
8644 new_lines(n_new_lines);
8645 for (unsigned int i = 0; i < n_new_lines; ++i)
8646 {
8647 new_lines[i] =
8648 triangulation.faces->lines
8649 .template next_free_single_object<1>(triangulation);
8650
8651 AssertIsNotUsed(new_lines[i]);
8652 new_lines[i]->set_used_flag();
8653 new_lines[i]->clear_user_flag();
8654 new_lines[i]->clear_user_data();
8655 new_lines[i]->clear_children();
8656 // interior line
8657 new_lines[i]->set_boundary_id_internal(
8659 // they inherit geometry description of the hex they
8660 // belong to
8661 new_lines[i]->set_manifold_id(hex->manifold_id());
8662 }
8663
8664 // find some space for the newly to be created
8665 // interior quads and initialize them.
8666 std::vector<
8668 new_quads(n_new_quads);
8669 for (unsigned int i = 0; i < n_new_quads; ++i)
8670 {
8671 new_quads[i] =
8672 triangulation.faces->quads
8673 .template next_free_single_object<2>(triangulation);
8674
8675 AssertIsNotUsed(new_quads[i]);
8676 new_quads[i]->set_used_flag();
8677 new_quads[i]->clear_user_flag();
8678 new_quads[i]->clear_user_data();
8679 new_quads[i]->clear_children();
8680 // interior quad
8681 new_quads[i]->set_boundary_id_internal(
8683 // they inherit geometry description of the hex they
8684 // belong to
8685 new_quads[i]->set_manifold_id(hex->manifold_id());
8686 // set all line orientation flags to true by
8687 // default, change this afterwards, if necessary
8688 for (unsigned int j = 0;
8689 j < GeometryInfo<dim>::lines_per_face;
8690 ++j)
8691 new_quads[i]->set_line_orientation(j, true);
8692 }
8693
8694 types::subdomain_id subdomainid = hex->subdomain_id();
8695
8696 // find some space for the newly to be created hexes
8697 // and initialize them.
8698 std::vector<
8700 new_hexes(n_new_hexes);
8701 for (unsigned int i = 0; i < n_new_hexes; ++i)
8702 {
8703 if (i % 2 == 0)
8704 next_unused_hex =
8705 triangulation.levels[level + 1]->cells.next_free_hex(
8706 triangulation, level + 1);
8707 else
8708 ++next_unused_hex;
8709
8710 new_hexes[i] = next_unused_hex;
8711
8712 AssertIsNotUsed(new_hexes[i]);
8713 new_hexes[i]->set_used_flag();
8714 new_hexes[i]->clear_user_flag();
8715 new_hexes[i]->clear_user_data();
8716 new_hexes[i]->clear_children();
8717 // inherit material
8718 // properties
8719 new_hexes[i]->set_material_id(hex->material_id());
8720 new_hexes[i]->set_manifold_id(hex->manifold_id());
8721 new_hexes[i]->set_subdomain_id(subdomainid);
8722
8723 if (i % 2)
8724 new_hexes[i]->set_parent(hex->index());
8725 // set the face_orientation flag to true for all
8726 // faces initially, as this is the default value
8727 // which is true for all faces interior to the
8728 // hex. later on go the other way round and
8729 // reset faces that are at the boundary of the
8730 // mother cube
8731 //
8732 // the same is true for the face_flip and
8733 // face_rotation flags. however, the latter two
8734 // are set to false by default as this is the
8735 // standard value
8736 for (const unsigned int f :
8738 new_hexes[i]->set_combined_face_orientation(
8739 f,
8741 }
8742 // note these hexes as children to the present cell
8743 for (unsigned int i = 0; i < n_new_hexes / 2; ++i)
8744 hex->set_children(2 * i, new_hexes[2 * i]->index());
8745
8746 // we have to take into account whether the
8747 // different faces are oriented correctly or in the
8748 // opposite direction, so store that up front
8749
8750 // face_orientation
8751 const bool f_or[6] = {hex->face_orientation(0),
8752 hex->face_orientation(1),
8753 hex->face_orientation(2),
8754 hex->face_orientation(3),
8755 hex->face_orientation(4),
8756 hex->face_orientation(5)};
8757
8758 // face_flip
8759 const bool f_fl[6] = {hex->face_flip(0),
8760 hex->face_flip(1),
8761 hex->face_flip(2),
8762 hex->face_flip(3),
8763 hex->face_flip(4),
8764 hex->face_flip(5)};
8765
8766 // face_rotation
8767 const bool f_ro[6] = {hex->face_rotation(0),
8768 hex->face_rotation(1),
8769 hex->face_rotation(2),
8770 hex->face_rotation(3),
8771 hex->face_rotation(4),
8772 hex->face_rotation(5)};
8773
8774 // combined orientation
8775 const unsigned char f_co[6] = {
8776 hex->combined_face_orientation(0),
8777 hex->combined_face_orientation(1),
8778 hex->combined_face_orientation(2),
8779 hex->combined_face_orientation(3),
8780 hex->combined_face_orientation(4),
8781 hex->combined_face_orientation(5)};
8782
8783 // little helper table, indicating, whether the
8784 // child with index 0 or with index 1 can be found
8785 // at the standard origin of an anisotropically
8786 // refined quads in real orientation index 1:
8787 // (RefineCase - 1) index 2: face_flip
8788
8789 // index 3: face rotation
8790 // note: face orientation has no influence
8791 const unsigned int child_at_origin[2][2][2] = {
8792 {{0, 0}, // RefinementCase<dim>::cut_x, face_flip=false,
8793 // face_rotation=false and true
8794 {1, 1}}, // RefinementCase<dim>::cut_x, face_flip=true,
8795 // face_rotation=false and true
8796 {{0, 1}, // RefinementCase<dim>::cut_y, face_flip=false,
8797 // face_rotation=false and true
8798 {1, 0}}}; // RefinementCase<dim>::cut_y, face_flip=true,
8799 // face_rotation=false and true
8800
8801 //-------------------------------------
8802 //
8803 // in the following we will do the same thing for
8804 // each refinement case: create a new vertex (if
8805 // needed), create new interior lines (if needed),
8806 // create new interior quads and afterwards build
8807 // the children hexes out of these and the existing
8808 // subfaces of the outer quads (which have been
8809 // created above). However, even if the steps are
8810 // quite similar, the actual work strongly depends
8811 // on the actual refinement case. therefore, we use
8812 // separate blocks of code for each of these cases,
8813 // which hopefully increases the readability to some
8814 // extend.
8815
8816 switch (ref_case)
8817 {
8819 {
8820 //----------------------------
8821 //
8822 // RefinementCase<dim>::cut_x
8823 //
8824 // the refined cube will look
8825 // like this:
8826 //
8827 // *----*----*
8828 // / / /|
8829 // / / / |
8830 // / / / |
8831 // *----*----* |
8832 // | | | |
8833 // | | | *
8834 // | | | /
8835 // | | | /
8836 // | | |/
8837 // *----*----*
8838 //
8839 // again, first collect some data about the
8840 // indices of the lines, with the following
8841 // numbering:
8842
8843 // face 2: front plane
8844 // (note: x,y exchanged)
8845 // *---*---*
8846 // | | |
8847 // | 0 |
8848 // | | |
8849 // *---*---*
8850 // m0
8851 // face 3: back plane
8852 // (note: x,y exchanged)
8853 // m1
8854 // *---*---*
8855 // | | |
8856 // | 1 |
8857 // | | |
8858 // *---*---*
8859 // face 4: bottom plane
8860 // *---*---*
8861 // / / /
8862 // / 2 /
8863 // / / /
8864 // *---*---*
8865 // m0
8866 // face 5: top plane
8867 // m1
8868 // *---*---*
8869 // / / /
8870 // / 3 /
8871 // / / /
8872 // *---*---*
8873
8874 // set up a list of line iterators first. from
8875 // this, construct lists of line_indices and
8876 // line orientations later on
8877 const typename Triangulation<dim, spacedim>::
8878 raw_line_iterator lines[4] = {
8879 hex->face(2)->child(0)->line(
8880 (hex->face(2)->refinement_case() ==
8882 1 :
8883 3), // 0
8884 hex->face(3)->child(0)->line(
8885 (hex->face(3)->refinement_case() ==
8887 1 :
8888 3), // 1
8889 hex->face(4)->child(0)->line(
8890 (hex->face(4)->refinement_case() ==
8892 1 :
8893 3), // 2
8894 hex->face(5)->child(0)->line(
8895 (hex->face(5)->refinement_case() ==
8897 1 :
8898 3) // 3
8899 };
8900
8901 unsigned int line_indices[4];
8902 for (unsigned int i = 0; i < 4; ++i)
8903 line_indices[i] = lines[i]->index();
8904
8905 // the orientation of lines for the inner quads
8906 // is quite tricky. as these lines are newly
8907 // created ones and thus have no parents, they
8908 // cannot inherit this property. set up an array
8909 // and fill it with the respective values
8910 bool line_orientation[4];
8911
8912 // the middle vertex marked as m0 above is the
8913 // start vertex for lines 0 and 2 in standard
8914 // orientation, whereas m1 is the end vertex of
8915 // lines 1 and 3 in standard orientation
8916 const unsigned int middle_vertices[2] = {
8917 hex->line(2)->child(0)->vertex_index(1),
8918 hex->line(7)->child(0)->vertex_index(1)};
8919
8920 for (unsigned int i = 0; i < 4; ++i)
8921 if (lines[i]->vertex_index(i % 2) ==
8922 middle_vertices[i % 2])
8923 line_orientation[i] = true;
8924 else
8925 {
8926 // it must be the other
8927 // way round then
8928 Assert(lines[i]->vertex_index((i + 1) % 2) ==
8929 middle_vertices[i % 2],
8931 line_orientation[i] = false;
8932 }
8933
8934 // set up the new quad, line numbering is as
8935 // indicated above
8936 new_quads[0]->set_bounding_object_indices(
8937 {line_indices[0],
8938 line_indices[1],
8939 line_indices[2],
8940 line_indices[3]});
8941
8942 new_quads[0]->set_line_orientation(
8943 0, line_orientation[0]);
8944 new_quads[0]->set_line_orientation(
8945 1, line_orientation[1]);
8946 new_quads[0]->set_line_orientation(
8947 2, line_orientation[2]);
8948 new_quads[0]->set_line_orientation(
8949 3, line_orientation[3]);
8950
8951 // the quads are numbered as follows:
8952 //
8953 // planes in the interior of the old hex:
8954 //
8955 // *
8956 // /|
8957 // / | x
8958 // / | *-------* *---------*
8959 // * | | | / /
8960 // | 0 | | | / /
8961 // | * | | / /
8962 // | / *-------*y *---------*x
8963 // | /
8964 // |/
8965 // *
8966 //
8967 // children of the faces of the old hex
8968 //
8969 // *---*---* *---*---*
8970 // /| | | / / /|
8971 // / | | | / 9 / 10/ |
8972 // / | 5 | 6 | / / / |
8973 // * | | | *---*---* |
8974 // | 1 *---*---* | | | 2 *
8975 // | / / / | | | /
8976 // | / 7 / 8 / | 3 | 4 | /
8977 // |/ / / | | |/
8978 // *---*---* *---*---*
8979 //
8980 // note that we have to take care of the
8981 // orientation of faces.
8982 const int quad_indices[11] = {
8983 new_quads[0]->index(), // 0
8984
8985 hex->face(0)->index(), // 1
8986
8987 hex->face(1)->index(), // 2
8988
8989 hex->face(2)->child_index(
8990 child_at_origin[hex->face(2)->refinement_case() -
8991 1][f_fl[2]][f_ro[2]]), // 3
8992 hex->face(2)->child_index(
8993 1 -
8994 child_at_origin[hex->face(2)->refinement_case() -
8995 1][f_fl[2]][f_ro[2]]),
8996
8997 hex->face(3)->child_index(
8998 child_at_origin[hex->face(3)->refinement_case() -
8999 1][f_fl[3]][f_ro[3]]), // 5
9000 hex->face(3)->child_index(
9001 1 -
9002 child_at_origin[hex->face(3)->refinement_case() -
9003 1][f_fl[3]][f_ro[3]]),
9004
9005 hex->face(4)->child_index(
9006 child_at_origin[hex->face(4)->refinement_case() -
9007 1][f_fl[4]][f_ro[4]]), // 7
9008 hex->face(4)->child_index(
9009 1 -
9010 child_at_origin[hex->face(4)->refinement_case() -
9011 1][f_fl[4]][f_ro[4]]),
9012
9013 hex->face(5)->child_index(
9014 child_at_origin[hex->face(5)->refinement_case() -
9015 1][f_fl[5]][f_ro[5]]), // 9
9016 hex->face(5)->child_index(
9017 1 -
9018 child_at_origin[hex->face(5)->refinement_case() -
9019 1][f_fl[5]][f_ro[5]])
9020
9021 };
9022
9023 new_hexes[0]->set_bounding_object_indices(
9024 {quad_indices[1],
9025 quad_indices[0],
9026 quad_indices[3],
9027 quad_indices[5],
9028 quad_indices[7],
9029 quad_indices[9]});
9030 new_hexes[1]->set_bounding_object_indices(
9031 {quad_indices[0],
9032 quad_indices[2],
9033 quad_indices[4],
9034 quad_indices[6],
9035 quad_indices[8],
9036 quad_indices[10]});
9037 break;
9038 }
9039
9041 {
9042 //----------------------------
9043 //
9044 // RefinementCase<dim>::cut_y
9045 //
9046 // the refined cube will look like this:
9047 //
9048 // *---------*
9049 // / /|
9050 // *---------* |
9051 // / /| |
9052 // *---------* | |
9053 // | | | |
9054 // | | | *
9055 // | | |/
9056 // | | *
9057 // | |/
9058 // *---------*
9059 //
9060 // again, first collect some data about the
9061 // indices of the lines, with the following
9062 // numbering:
9063
9064 // face 0: left plane
9065 // *
9066 // /|
9067 // * |
9068 // /| |
9069 // * | |
9070 // | 0 |
9071 // | | *
9072 // | |/
9073 // | *m0
9074 // |/
9075 // *
9076 // face 1: right plane
9077 // *
9078 // /|
9079 // m1* |
9080 // /| |
9081 // * | |
9082 // | 1 |
9083 // | | *
9084 // | |/
9085 // | *
9086 // |/
9087 // *
9088 // face 4: bottom plane
9089 // *-------*
9090 // / /
9091 // m0*---2---*
9092 // / /
9093 // *-------*
9094 // face 5: top plane
9095 // *-------*
9096 // / /
9097 // *---3---*m1
9098 // / /
9099 // *-------*
9100
9101 // set up a list of line iterators first. from
9102 // this, construct lists of line_indices and
9103 // line orientations later on
9104 const typename Triangulation<dim, spacedim>::
9105 raw_line_iterator lines[4] = {
9106 hex->face(0)->child(0)->line(
9107 (hex->face(0)->refinement_case() ==
9109 1 :
9110 3), // 0
9111 hex->face(1)->child(0)->line(
9112 (hex->face(1)->refinement_case() ==
9114 1 :
9115 3), // 1
9116 hex->face(4)->child(0)->line(
9117 (hex->face(4)->refinement_case() ==
9119 1 :
9120 3), // 2
9121 hex->face(5)->child(0)->line(
9122 (hex->face(5)->refinement_case() ==
9124 1 :
9125 3) // 3
9126 };
9127
9128 unsigned int line_indices[4];
9129 for (unsigned int i = 0; i < 4; ++i)
9130 line_indices[i] = lines[i]->index();
9131
9132 // the orientation of lines for the inner quads
9133 // is quite tricky. as these lines are newly
9134 // created ones and thus have no parents, they
9135 // cannot inherit this property. set up an array
9136 // and fill it with the respective values
9137 bool line_orientation[4];
9138
9139 // the middle vertex marked as m0 above is the
9140 // start vertex for lines 0 and 2 in standard
9141 // orientation, whereas m1 is the end vertex of
9142 // lines 1 and 3 in standard orientation
9143 const unsigned int middle_vertices[2] = {
9144 hex->line(0)->child(0)->vertex_index(1),
9145 hex->line(5)->child(0)->vertex_index(1)};
9146
9147 for (unsigned int i = 0; i < 4; ++i)
9148 if (lines[i]->vertex_index(i % 2) ==
9149 middle_vertices[i % 2])
9150 line_orientation[i] = true;
9151 else
9152 {
9153 // it must be the other way round then
9154 Assert(lines[i]->vertex_index((i + 1) % 2) ==
9155 middle_vertices[i % 2],
9157 line_orientation[i] = false;
9158 }
9159
9160 // set up the new quad, line numbering is as
9161 // indicated above
9162 new_quads[0]->set_bounding_object_indices(
9163 {line_indices[2],
9164 line_indices[3],
9165 line_indices[0],
9166 line_indices[1]});
9167
9168 new_quads[0]->set_line_orientation(
9169 0, line_orientation[2]);
9170 new_quads[0]->set_line_orientation(
9171 1, line_orientation[3]);
9172 new_quads[0]->set_line_orientation(
9173 2, line_orientation[0]);
9174 new_quads[0]->set_line_orientation(
9175 3, line_orientation[1]);
9176
9177 // the quads are numbered as follows:
9178 //
9179 // planes in the interior of the old hex:
9180 //
9181 // *
9182 // /|
9183 // / | x
9184 // / | *-------* *---------*
9185 // * | | | / /
9186 // | | | 0 | / /
9187 // | * | | / /
9188 // | / *-------*y *---------*x
9189 // | /
9190 // |/
9191 // *
9192 //
9193 // children of the faces of the old hex
9194 //
9195 // *-------* *-------*
9196 // /| | / 10 /|
9197 // * | | *-------* |
9198 // /| | 6 | / 9 /| |
9199 // * |2| | *-------* |4|
9200 // | | *-------* | | | *
9201 // |1|/ 8 / | |3|/
9202 // | *-------* | 5 | *
9203 // |/ 7 / | |/
9204 // *-------* *-------*
9205 //
9206 // note that we have to take care of the
9207 // orientation of faces.
9208 const int quad_indices[11] = {
9209 new_quads[0]->index(), // 0
9210
9211 hex->face(0)->child_index(
9212 child_at_origin[hex->face(0)->refinement_case() -
9213 1][f_fl[0]][f_ro[0]]), // 1
9214 hex->face(0)->child_index(
9215 1 -
9216 child_at_origin[hex->face(0)->refinement_case() -
9217 1][f_fl[0]][f_ro[0]]),
9218
9219 hex->face(1)->child_index(
9220 child_at_origin[hex->face(1)->refinement_case() -
9221 1][f_fl[1]][f_ro[1]]), // 3
9222 hex->face(1)->child_index(
9223 1 -
9224 child_at_origin[hex->face(1)->refinement_case() -
9225 1][f_fl[1]][f_ro[1]]),
9226
9227 hex->face(2)->index(), // 5
9228
9229 hex->face(3)->index(), // 6
9230
9231 hex->face(4)->child_index(
9232 child_at_origin[hex->face(4)->refinement_case() -
9233 1][f_fl[4]][f_ro[4]]), // 7
9234 hex->face(4)->child_index(
9235 1 -
9236 child_at_origin[hex->face(4)->refinement_case() -
9237 1][f_fl[4]][f_ro[4]]),
9238
9239 hex->face(5)->child_index(
9240 child_at_origin[hex->face(5)->refinement_case() -
9241 1][f_fl[5]][f_ro[5]]), // 9
9242 hex->face(5)->child_index(
9243 1 -
9244 child_at_origin[hex->face(5)->refinement_case() -
9245 1][f_fl[5]][f_ro[5]])
9246
9247 };
9248
9249 new_hexes[0]->set_bounding_object_indices(
9250 {quad_indices[1],
9251 quad_indices[3],
9252 quad_indices[5],
9253 quad_indices[0],
9254 quad_indices[7],
9255 quad_indices[9]});
9256 new_hexes[1]->set_bounding_object_indices(
9257 {quad_indices[2],
9258 quad_indices[4],
9259 quad_indices[0],
9260 quad_indices[6],
9261 quad_indices[8],
9262 quad_indices[10]});
9263 break;
9264 }
9265
9267 {
9268 //----------------------------
9269 //
9270 // RefinementCase<dim>::cut_z
9271 //
9272 // the refined cube will look like this:
9273 //
9274 // *---------*
9275 // / /|
9276 // / / |
9277 // / / *
9278 // *---------* /|
9279 // | | / |
9280 // | |/ *
9281 // *---------* /
9282 // | | /
9283 // | |/
9284 // *---------*
9285 //
9286 // again, first collect some data about the
9287 // indices of the lines, with the following
9288 // numbering:
9289
9290 // face 0: left plane
9291 // *
9292 // /|
9293 // / |
9294 // / *
9295 // * /|
9296 // | 0 |
9297 // |/ *
9298 // m0* /
9299 // | /
9300 // |/
9301 // *
9302 // face 1: right plane
9303 // *
9304 // /|
9305 // / |
9306 // / *m1
9307 // * /|
9308 // | 1 |
9309 // |/ *
9310 // * /
9311 // | /
9312 // |/
9313 // *
9314 // face 2: front plane
9315 // (note: x,y exchanged)
9316 // *-------*
9317 // | |
9318 // m0*---2---*
9319 // | |
9320 // *-------*
9321 // face 3: back plane
9322 // (note: x,y exchanged)
9323 // *-------*
9324 // | |
9325 // *---3---*m1
9326 // | |
9327 // *-------*
9328
9329 // set up a list of line iterators first. from
9330 // this, construct lists of line_indices and
9331 // line orientations later on
9332 const typename Triangulation<dim, spacedim>::
9333 raw_line_iterator lines[4] = {
9334 hex->face(0)->child(0)->line(
9335 (hex->face(0)->refinement_case() ==
9337 1 :
9338 3), // 0
9339 hex->face(1)->child(0)->line(
9340 (hex->face(1)->refinement_case() ==
9342 1 :
9343 3), // 1
9344 hex->face(2)->child(0)->line(
9345 (hex->face(2)->refinement_case() ==
9347 1 :
9348 3), // 2
9349 hex->face(3)->child(0)->line(
9350 (hex->face(3)->refinement_case() ==
9352 1 :
9353 3) // 3
9354 };
9355
9356 unsigned int line_indices[4];
9357 for (unsigned int i = 0; i < 4; ++i)
9358 line_indices[i] = lines[i]->index();
9359
9360 // the orientation of lines for the inner quads
9361 // is quite tricky. as these lines are newly
9362 // created ones and thus have no parents, they
9363 // cannot inherit this property. set up an array
9364 // and fill it with the respective values
9365 bool line_orientation[4];
9366
9367 // the middle vertex marked as m0 above is the
9368 // start vertex for lines 0 and 2 in standard
9369 // orientation, whereas m1 is the end vertex of
9370 // lines 1 and 3 in standard orientation
9371 const unsigned int middle_vertices[2] = {
9372 middle_vertex_index<dim, spacedim>(hex->line(8)),
9373 middle_vertex_index<dim, spacedim>(hex->line(11))};
9374
9375 for (unsigned int i = 0; i < 4; ++i)
9376 if (lines[i]->vertex_index(i % 2) ==
9377 middle_vertices[i % 2])
9378 line_orientation[i] = true;
9379 else
9380 {
9381 // it must be the other way round then
9382 Assert(lines[i]->vertex_index((i + 1) % 2) ==
9383 middle_vertices[i % 2],
9385 line_orientation[i] = false;
9386 }
9387
9388 // set up the new quad, line numbering is as
9389 // indicated above
9390 new_quads[0]->set_bounding_object_indices(
9391 {line_indices[0],
9392 line_indices[1],
9393 line_indices[2],
9394 line_indices[3]});
9395
9396 new_quads[0]->set_line_orientation(
9397 0, line_orientation[0]);
9398 new_quads[0]->set_line_orientation(
9399 1, line_orientation[1]);
9400 new_quads[0]->set_line_orientation(
9401 2, line_orientation[2]);
9402 new_quads[0]->set_line_orientation(
9403 3, line_orientation[3]);
9404
9405 // the quads are numbered as follows:
9406 //
9407 // planes in the interior of the old hex:
9408 //
9409 // *
9410 // /|
9411 // / | x
9412 // / | *-------* *---------*
9413 // * | | | / /
9414 // | | | | / 0 /
9415 // | * | | / /
9416 // | / *-------*y *---------*x
9417 // | /
9418 // |/
9419 // *
9420 //
9421 // children of the faces of the old hex
9422 //
9423 // *---*---* *-------*
9424 // /| 8 | / /|
9425 // / | | / 10 / |
9426 // / *-------* / / *
9427 // * 2/| | *-------* 4/|
9428 // | / | 7 | | 6 | / |
9429 // |/1 *-------* | |/3 *
9430 // * / / *-------* /
9431 // | / 9 / | | /
9432 // |/ / | 5 |/
9433 // *-------* *---*---*
9434 //
9435 // note that we have to take care of the
9436 // orientation of faces.
9437 const int quad_indices[11] = {
9438 new_quads[0]->index(), // 0
9439
9440 hex->face(0)->child_index(
9441 child_at_origin[hex->face(0)->refinement_case() -
9442 1][f_fl[0]][f_ro[0]]), // 1
9443 hex->face(0)->child_index(
9444 1 -
9445 child_at_origin[hex->face(0)->refinement_case() -
9446 1][f_fl[0]][f_ro[0]]),
9447
9448 hex->face(1)->child_index(
9449 child_at_origin[hex->face(1)->refinement_case() -
9450 1][f_fl[1]][f_ro[1]]), // 3
9451 hex->face(1)->child_index(
9452 1 -
9453 child_at_origin[hex->face(1)->refinement_case() -
9454 1][f_fl[1]][f_ro[1]]),
9455
9456 hex->face(2)->child_index(
9457 child_at_origin[hex->face(2)->refinement_case() -
9458 1][f_fl[2]][f_ro[2]]), // 5
9459 hex->face(2)->child_index(
9460 1 -
9461 child_at_origin[hex->face(2)->refinement_case() -
9462 1][f_fl[2]][f_ro[2]]),
9463
9464 hex->face(3)->child_index(
9465 child_at_origin[hex->face(3)->refinement_case() -
9466 1][f_fl[3]][f_ro[3]]), // 7
9467 hex->face(3)->child_index(
9468 1 -
9469 child_at_origin[hex->face(3)->refinement_case() -
9470 1][f_fl[3]][f_ro[3]]),
9471
9472 hex->face(4)->index(), // 9
9473
9474 hex->face(5)->index() // 10
9475 };
9476
9477 new_hexes[0]->set_bounding_object_indices(
9478 {quad_indices[1],
9479 quad_indices[3],
9480 quad_indices[5],
9481 quad_indices[7],
9482 quad_indices[9],
9483 quad_indices[0]});
9484 new_hexes[1]->set_bounding_object_indices(
9485 {quad_indices[2],
9486 quad_indices[4],
9487 quad_indices[6],
9488 quad_indices[8],
9489 quad_indices[0],
9490 quad_indices[10]});
9491 break;
9492 }
9493
9495 {
9496 //----------------------------
9497 //
9498 // RefinementCase<dim>::cut_xy
9499 //
9500 // the refined cube will look like this:
9501 //
9502 // *----*----*
9503 // / / /|
9504 // *----*----* |
9505 // / / /| |
9506 // *----*----* | |
9507 // | | | | |
9508 // | | | | *
9509 // | | | |/
9510 // | | | *
9511 // | | |/
9512 // *----*----*
9513 //
9514
9515 // first, create the new internal line
9516 new_lines[0]->set_bounding_object_indices(
9517 {middle_vertex_index<dim, spacedim>(hex->face(4)),
9518 middle_vertex_index<dim, spacedim>(hex->face(5))});
9519
9520 // again, first collect some data about the
9521 // indices of the lines, with the following
9522 // numbering:
9523
9524 // face 0: left plane
9525 // *
9526 // /|
9527 // * |
9528 // /| |
9529 // * | |
9530 // | 0 |
9531 // | | *
9532 // | |/
9533 // | *
9534 // |/
9535 // *
9536 // face 1: right plane
9537 // *
9538 // /|
9539 // * |
9540 // /| |
9541 // * | |
9542 // | 1 |
9543 // | | *
9544 // | |/
9545 // | *
9546 // |/
9547 // *
9548 // face 2: front plane
9549 // (note: x,y exchanged)
9550 // *---*---*
9551 // | | |
9552 // | 2 |
9553 // | | |
9554 // *-------*
9555 // face 3: back plane
9556 // (note: x,y exchanged)
9557 // *---*---*
9558 // | | |
9559 // | 3 |
9560 // | | |
9561 // *---*---*
9562 // face 4: bottom plane
9563 // *---*---*
9564 // / 5 /
9565 // *-6-*-7-*
9566 // / 4 /
9567 // *---*---*
9568 // face 5: top plane
9569 // *---*---*
9570 // / 9 /
9571 // *10-*-11*
9572 // / 8 /
9573 // *---*---*
9574 // middle planes
9575 // *-------* *---*---*
9576 // / / | | |
9577 // / / | 12 |
9578 // / / | | |
9579 // *-------* *---*---*
9580
9581 // set up a list of line iterators first. from
9582 // this, construct lists of line_indices and
9583 // line orientations later on
9584 const typename Triangulation<
9585 dim,
9586 spacedim>::raw_line_iterator lines[13] = {
9587 hex->face(0)->child(0)->line(
9588 (hex->face(0)->refinement_case() ==
9590 1 :
9591 3), // 0
9592 hex->face(1)->child(0)->line(
9593 (hex->face(1)->refinement_case() ==
9595 1 :
9596 3), // 1
9597 hex->face(2)->child(0)->line(
9598 (hex->face(2)->refinement_case() ==
9600 1 :
9601 3), // 2
9602 hex->face(3)->child(0)->line(
9603 (hex->face(3)->refinement_case() ==
9605 1 :
9606 3), // 3
9607
9608 hex->face(4)
9609 ->isotropic_child(
9611 0, f_or[4], f_fl[4], f_ro[4]))
9612 ->line(
9614 1, f_or[4], f_fl[4], f_ro[4])), // 4
9615 hex->face(4)
9616 ->isotropic_child(
9618 3, f_or[4], f_fl[4], f_ro[4]))
9619 ->line(
9621 0, f_or[4], f_fl[4], f_ro[4])), // 5
9622 hex->face(4)
9623 ->isotropic_child(
9625 0, f_or[4], f_fl[4], f_ro[4]))
9626 ->line(
9628 3, f_or[4], f_fl[4], f_ro[4])), // 6
9629 hex->face(4)
9630 ->isotropic_child(
9632 3, f_or[4], f_fl[4], f_ro[4]))
9633 ->line(
9635 2, f_or[4], f_fl[4], f_ro[4])), // 7
9636
9637 hex->face(5)
9638 ->isotropic_child(
9640 0, f_or[5], f_fl[5], f_ro[5]))
9641 ->line(
9643 1, f_or[5], f_fl[5], f_ro[5])), // 8
9644 hex->face(5)
9645 ->isotropic_child(
9647 3, f_or[5], f_fl[5], f_ro[5]))
9648 ->line(
9650 0, f_or[5], f_fl[5], f_ro[5])), // 9
9651 hex->face(5)
9652 ->isotropic_child(
9654 0, f_or[5], f_fl[5], f_ro[5]))
9655 ->line(
9657 3, f_or[5], f_fl[5], f_ro[5])), // 10
9658 hex->face(5)
9659 ->isotropic_child(
9661 3, f_or[5], f_fl[5], f_ro[5]))
9662 ->line(
9664 2, f_or[5], f_fl[5], f_ro[5])), // 11
9665
9666 new_lines[0] // 12
9667 };
9668
9669 unsigned int line_indices[13];
9670 for (unsigned int i = 0; i < 13; ++i)
9671 line_indices[i] = lines[i]->index();
9672
9673 // the orientation of lines for the inner quads
9674 // is quite tricky. as these lines are newly
9675 // created ones and thus have no parents, they
9676 // cannot inherit this property. set up an array
9677 // and fill it with the respective values
9678 bool line_orientation[13];
9679
9680 // the middle vertices of the lines of our
9681 // bottom face
9682 const unsigned int middle_vertices[4] = {
9683 hex->line(0)->child(0)->vertex_index(1),
9684 hex->line(1)->child(0)->vertex_index(1),
9685 hex->line(2)->child(0)->vertex_index(1),
9686 hex->line(3)->child(0)->vertex_index(1),
9687 };
9688
9689 // note: for lines 0 to 3 the orientation of the
9690 // line is 'true', if vertex 0 is on the bottom
9691 // face
9692 for (unsigned int i = 0; i < 4; ++i)
9693 if (lines[i]->vertex_index(0) == middle_vertices[i])
9694 line_orientation[i] = true;
9695 else
9696 {
9697 // it must be the other way round then
9698 Assert(lines[i]->vertex_index(1) ==
9699 middle_vertices[i],
9701 line_orientation[i] = false;
9702 }
9703
9704 // note: for lines 4 to 11 (inner lines of the
9705 // outer quads) the following holds: the second
9706 // vertex of the even lines in standard
9707 // orientation is the vertex in the middle of
9708 // the quad, whereas for odd lines the first
9709 // vertex is the same middle vertex.
9710 for (unsigned int i = 4; i < 12; ++i)
9711 if (lines[i]->vertex_index((i + 1) % 2) ==
9712 middle_vertex_index<dim, spacedim>(
9713 hex->face(3 + i / 4)))
9714 line_orientation[i] = true;
9715 else
9716 {
9717 // it must be the other way
9718 // round then
9719 Assert(lines[i]->vertex_index(i % 2) ==
9720 (middle_vertex_index<dim, spacedim>(
9721 hex->face(3 + i / 4))),
9723 line_orientation[i] = false;
9724 }
9725 // for the last line the line orientation is
9726 // always true, since it was just constructed
9727 // that way
9728 line_orientation[12] = true;
9729
9730 // set up the 4 quads, numbered as follows (left
9731 // quad numbering, right line numbering
9732 // extracted from above)
9733 //
9734 // * *
9735 // /| 9|
9736 // * | * |
9737 // y/| | 8| 3
9738 // * |1| * | |
9739 // | | |x | 12|
9740 // |0| * | | *
9741 // | |/ 2 |5
9742 // | * | *
9743 // |/ |4
9744 // * *
9745 //
9746 // x
9747 // *---*---* *10-*-11*
9748 // | | | | | |
9749 // | 2 | 3 | 0 12 1
9750 // | | | | | |
9751 // *---*---*y *-6-*-7-*
9752
9753 new_quads[0]->set_bounding_object_indices(
9754 {line_indices[2],
9755 line_indices[12],
9756 line_indices[4],
9757 line_indices[8]});
9758 new_quads[1]->set_bounding_object_indices(
9759 {line_indices[12],
9760 line_indices[3],
9761 line_indices[5],
9762 line_indices[9]});
9763 new_quads[2]->set_bounding_object_indices(
9764 {line_indices[6],
9765 line_indices[10],
9766 line_indices[0],
9767 line_indices[12]});
9768 new_quads[3]->set_bounding_object_indices(
9769 {line_indices[7],
9770 line_indices[11],
9771 line_indices[12],
9772 line_indices[1]});
9773
9774 new_quads[0]->set_line_orientation(
9775 0, line_orientation[2]);
9776 new_quads[0]->set_line_orientation(
9777 2, line_orientation[4]);
9778 new_quads[0]->set_line_orientation(
9779 3, line_orientation[8]);
9780
9781 new_quads[1]->set_line_orientation(
9782 1, line_orientation[3]);
9783 new_quads[1]->set_line_orientation(
9784 2, line_orientation[5]);
9785 new_quads[1]->set_line_orientation(
9786 3, line_orientation[9]);
9787
9788 new_quads[2]->set_line_orientation(
9789 0, line_orientation[6]);
9790 new_quads[2]->set_line_orientation(
9791 1, line_orientation[10]);
9792 new_quads[2]->set_line_orientation(
9793 2, line_orientation[0]);
9794
9795 new_quads[3]->set_line_orientation(
9796 0, line_orientation[7]);
9797 new_quads[3]->set_line_orientation(
9798 1, line_orientation[11]);
9799 new_quads[3]->set_line_orientation(
9800 3, line_orientation[1]);
9801
9802 // the quads are numbered as follows:
9803 //
9804 // planes in the interior of the old hex:
9805 //
9806 // *
9807 // /|
9808 // * | x
9809 // /| | *---*---* *---------*
9810 // * |1| | | | / /
9811 // | | | | 2 | 3 | / /
9812 // |0| * | | | / /
9813 // | |/ *---*---*y *---------*x
9814 // | *
9815 // |/
9816 // *
9817 //
9818 // children of the faces of the old hex
9819 //
9820 // *---*---* *---*---*
9821 // /| | | /18 / 19/|
9822 // * |10 | 11| /---/---* |
9823 // /| | | | /16 / 17/| |
9824 // * |5| | | *---*---* |7|
9825 // | | *---*---* | | | | *
9826 // |4|/14 / 15/ | | |6|/
9827 // | *---/---/ | 8 | 9 | *
9828 // |/12 / 13/ | | |/
9829 // *---*---* *---*---*
9830 //
9831 // note that we have to take care of the
9832 // orientation of faces.
9833 const int quad_indices[20] = {
9834 new_quads[0]->index(), // 0
9835 new_quads[1]->index(),
9836 new_quads[2]->index(),
9837 new_quads[3]->index(),
9838
9839 hex->face(0)->child_index(
9840 child_at_origin[hex->face(0)->refinement_case() -
9841 1][f_fl[0]][f_ro[0]]), // 4
9842 hex->face(0)->child_index(
9843 1 -
9844 child_at_origin[hex->face(0)->refinement_case() -
9845 1][f_fl[0]][f_ro[0]]),
9846
9847 hex->face(1)->child_index(
9848 child_at_origin[hex->face(1)->refinement_case() -
9849 1][f_fl[1]][f_ro[1]]), // 6
9850 hex->face(1)->child_index(
9851 1 -
9852 child_at_origin[hex->face(1)->refinement_case() -
9853 1][f_fl[1]][f_ro[1]]),
9854
9855 hex->face(2)->child_index(
9856 child_at_origin[hex->face(2)->refinement_case() -
9857 1][f_fl[2]][f_ro[2]]), // 8
9858 hex->face(2)->child_index(
9859 1 -
9860 child_at_origin[hex->face(2)->refinement_case() -
9861 1][f_fl[2]][f_ro[2]]),
9862
9863 hex->face(3)->child_index(
9864 child_at_origin[hex->face(3)->refinement_case() -
9865 1][f_fl[3]][f_ro[3]]), // 10
9866 hex->face(3)->child_index(
9867 1 -
9868 child_at_origin[hex->face(3)->refinement_case() -
9869 1][f_fl[3]][f_ro[3]]),
9870
9871 hex->face(4)->isotropic_child_index(
9873 0, f_or[4], f_fl[4], f_ro[4])), // 12
9874 hex->face(4)->isotropic_child_index(
9876 1, f_or[4], f_fl[4], f_ro[4])),
9877 hex->face(4)->isotropic_child_index(
9879 2, f_or[4], f_fl[4], f_ro[4])),
9880 hex->face(4)->isotropic_child_index(
9882 3, f_or[4], f_fl[4], f_ro[4])),
9883
9884 hex->face(5)->isotropic_child_index(
9886 0, f_or[5], f_fl[5], f_ro[5])), // 16
9887 hex->face(5)->isotropic_child_index(
9889 1, f_or[5], f_fl[5], f_ro[5])),
9890 hex->face(5)->isotropic_child_index(
9892 2, f_or[5], f_fl[5], f_ro[5])),
9893 hex->face(5)->isotropic_child_index(
9895 3, f_or[5], f_fl[5], f_ro[5]))};
9896
9897 new_hexes[0]->set_bounding_object_indices(
9898 {quad_indices[4],
9899 quad_indices[0],
9900 quad_indices[8],
9901 quad_indices[2],
9902 quad_indices[12],
9903 quad_indices[16]});
9904 new_hexes[1]->set_bounding_object_indices(
9905 {quad_indices[0],
9906 quad_indices[6],
9907 quad_indices[9],
9908 quad_indices[3],
9909 quad_indices[13],
9910 quad_indices[17]});
9911 new_hexes[2]->set_bounding_object_indices(
9912 {quad_indices[5],
9913 quad_indices[1],
9914 quad_indices[2],
9915 quad_indices[10],
9916 quad_indices[14],
9917 quad_indices[18]});
9918 new_hexes[3]->set_bounding_object_indices(
9919 {quad_indices[1],
9920 quad_indices[7],
9921 quad_indices[3],
9922 quad_indices[11],
9923 quad_indices[15],
9924 quad_indices[19]});
9925 break;
9926 }
9927
9929 {
9930 //----------------------------
9931 //
9932 // RefinementCase<dim>::cut_xz
9933 //
9934 // the refined cube will look like this:
9935 //
9936 // *----*----*
9937 // / / /|
9938 // / / / |
9939 // / / / *
9940 // *----*----* /|
9941 // | | | / |
9942 // | | |/ *
9943 // *----*----* /
9944 // | | | /
9945 // | | |/
9946 // *----*----*
9947 //
9948
9949 // first, create the new internal line
9950 new_lines[0]->set_bounding_object_indices(
9951 {middle_vertex_index<dim, spacedim>(hex->face(2)),
9952 middle_vertex_index<dim, spacedim>(hex->face(3))});
9953
9954 // again, first collect some data about the
9955 // indices of the lines, with the following
9956 // numbering:
9957
9958 // face 0: left plane
9959 // *
9960 // /|
9961 // / |
9962 // / *
9963 // * /|
9964 // | 0 |
9965 // |/ *
9966 // * /
9967 // | /
9968 // |/
9969 // *
9970 // face 1: right plane
9971 // *
9972 // /|
9973 // / |
9974 // / *
9975 // * /|
9976 // | 1 |
9977 // |/ *
9978 // * /
9979 // | /
9980 // |/
9981 // *
9982 // face 2: front plane
9983 // (note: x,y exchanged)
9984 // *---*---*
9985 // | 5 |
9986 // *-6-*-7-*
9987 // | 4 |
9988 // *---*---*
9989 // face 3: back plane
9990 // (note: x,y exchanged)
9991 // *---*---*
9992 // | 9 |
9993 // *10-*-11*
9994 // | 8 |
9995 // *---*---*
9996 // face 4: bottom plane
9997 // *---*---*
9998 // / / /
9999 // / 2 /
10000 // / / /
10001 // *---*---*
10002 // face 5: top plane
10003 // *---*---*
10004 // / / /
10005 // / 3 /
10006 // / / /
10007 // *---*---*
10008 // middle planes
10009 // *---*---* *-------*
10010 // / / / | |
10011 // / 12 / | |
10012 // / / / | |
10013 // *---*---* *-------*
10014
10015 // set up a list of line iterators first. from
10016 // this, construct lists of line_indices and
10017 // line orientations later on
10018 const typename Triangulation<
10019 dim,
10020 spacedim>::raw_line_iterator lines[13] = {
10021 hex->face(0)->child(0)->line(
10022 (hex->face(0)->refinement_case() ==
10024 1 :
10025 3), // 0
10026 hex->face(1)->child(0)->line(
10027 (hex->face(1)->refinement_case() ==
10029 1 :
10030 3), // 1
10031 hex->face(4)->child(0)->line(
10032 (hex->face(4)->refinement_case() ==
10034 1 :
10035 3), // 2
10036 hex->face(5)->child(0)->line(
10037 (hex->face(5)->refinement_case() ==
10039 1 :
10040 3), // 3
10041
10042 hex->face(2)
10043 ->isotropic_child(
10045 0, f_or[2], f_fl[2], f_ro[2]))
10046 ->line(
10048 3, f_or[2], f_fl[2], f_ro[2])), // 4
10049 hex->face(2)
10050 ->isotropic_child(
10052 3, f_or[2], f_fl[2], f_ro[2]))
10053 ->line(
10055 2, f_or[2], f_fl[2], f_ro[2])), // 5
10056 hex->face(2)
10057 ->isotropic_child(
10059 0, f_or[2], f_fl[2], f_ro[2]))
10060 ->line(
10062 1, f_or[2], f_fl[2], f_ro[2])), // 6
10063 hex->face(2)
10064 ->isotropic_child(
10066 3, f_or[2], f_fl[2], f_ro[2]))
10067 ->line(
10069 0, f_or[2], f_fl[2], f_ro[2])), // 7
10070
10071 hex->face(3)
10072 ->isotropic_child(
10074 0, f_or[3], f_fl[3], f_ro[3]))
10075 ->line(
10077 3, f_or[3], f_fl[3], f_ro[3])), // 8
10078 hex->face(3)
10079 ->isotropic_child(
10081 3, f_or[3], f_fl[3], f_ro[3]))
10082 ->line(
10084 2, f_or[3], f_fl[3], f_ro[3])), // 9
10085 hex->face(3)
10086 ->isotropic_child(
10088 0, f_or[3], f_fl[3], f_ro[3]))
10089 ->line(
10091 1, f_or[3], f_fl[3], f_ro[3])), // 10
10092 hex->face(3)
10093 ->isotropic_child(
10095 3, f_or[3], f_fl[3], f_ro[3]))
10096 ->line(
10098 0, f_or[3], f_fl[3], f_ro[3])), // 11
10099
10100 new_lines[0] // 12
10101 };
10102
10103 unsigned int line_indices[13];
10104 for (unsigned int i = 0; i < 13; ++i)
10105 line_indices[i] = lines[i]->index();
10106
10107 // the orientation of lines for the inner quads
10108 // is quite tricky. as these lines are newly
10109 // created ones and thus have no parents, they
10110 // cannot inherit this property. set up an array
10111 // and fill it with the respective values
10112 bool line_orientation[13];
10113
10114 // the middle vertices of the
10115 // lines of our front face
10116 const unsigned int middle_vertices[4] = {
10117 hex->line(8)->child(0)->vertex_index(1),
10118 hex->line(9)->child(0)->vertex_index(1),
10119 hex->line(2)->child(0)->vertex_index(1),
10120 hex->line(6)->child(0)->vertex_index(1),
10121 };
10122
10123 // note: for lines 0 to 3 the orientation of the
10124 // line is 'true', if vertex 0 is on the front
10125 for (unsigned int i = 0; i < 4; ++i)
10126 if (lines[i]->vertex_index(0) == middle_vertices[i])
10127 line_orientation[i] = true;
10128 else
10129 {
10130 // it must be the other way round then
10131 Assert(lines[i]->vertex_index(1) ==
10132 middle_vertices[i],
10134 line_orientation[i] = false;
10135 }
10136
10137 // note: for lines 4 to 11 (inner lines of the
10138 // outer quads) the following holds: the second
10139 // vertex of the even lines in standard
10140 // orientation is the vertex in the middle of
10141 // the quad, whereas for odd lines the first
10142 // vertex is the same middle vertex.
10143 for (unsigned int i = 4; i < 12; ++i)
10144 if (lines[i]->vertex_index((i + 1) % 2) ==
10145 middle_vertex_index<dim, spacedim>(
10146 hex->face(1 + i / 4)))
10147 line_orientation[i] = true;
10148 else
10149 {
10150 // it must be the other way
10151 // round then
10152 Assert(lines[i]->vertex_index(i % 2) ==
10153 (middle_vertex_index<dim, spacedim>(
10154 hex->face(1 + i / 4))),
10156 line_orientation[i] = false;
10157 }
10158 // for the last line the line orientation is
10159 // always true, since it was just constructed
10160 // that way
10161 line_orientation[12] = true;
10162
10163 // set up the 4 quads, numbered as follows (left
10164 // quad numbering, right line numbering
10165 // extracted from above), the drawings denote
10166 // middle planes
10167 //
10168 // * *
10169 // /| /|
10170 // / | 3 9
10171 // y/ * / *
10172 // * 3/| * /|
10173 // | / |x 5 12|8
10174 // |/ * |/ *
10175 // * 2/ * /
10176 // | / 4 2
10177 // |/ |/
10178 // * *
10179 //
10180 // y
10181 // *----*----* *-10-*-11-*
10182 // / / / / / /
10183 // / 0 / 1 / 0 12 1
10184 // / / / / / /
10185 // *----*----*x *--6-*--7-*
10186
10187 new_quads[0]->set_bounding_object_indices(
10188 {line_indices[0],
10189 line_indices[12],
10190 line_indices[6],
10191 line_indices[10]});
10192 new_quads[1]->set_bounding_object_indices(
10193 {line_indices[12],
10194 line_indices[1],
10195 line_indices[7],
10196 line_indices[11]});
10197 new_quads[2]->set_bounding_object_indices(
10198 {line_indices[4],
10199 line_indices[8],
10200 line_indices[2],
10201 line_indices[12]});
10202 new_quads[3]->set_bounding_object_indices(
10203 {line_indices[5],
10204 line_indices[9],
10205 line_indices[12],
10206 line_indices[3]});
10207
10208 new_quads[0]->set_line_orientation(
10209 0, line_orientation[0]);
10210 new_quads[0]->set_line_orientation(
10211 2, line_orientation[6]);
10212 new_quads[0]->set_line_orientation(
10213 3, line_orientation[10]);
10214
10215 new_quads[1]->set_line_orientation(
10216 1, line_orientation[1]);
10217 new_quads[1]->set_line_orientation(
10218 2, line_orientation[7]);
10219 new_quads[1]->set_line_orientation(
10220 3, line_orientation[11]);
10221
10222 new_quads[2]->set_line_orientation(
10223 0, line_orientation[4]);
10224 new_quads[2]->set_line_orientation(
10225 1, line_orientation[8]);
10226 new_quads[2]->set_line_orientation(
10227 2, line_orientation[2]);
10228
10229 new_quads[3]->set_line_orientation(
10230 0, line_orientation[5]);
10231 new_quads[3]->set_line_orientation(
10232 1, line_orientation[9]);
10233 new_quads[3]->set_line_orientation(
10234 3, line_orientation[3]);
10235
10236 // the quads are numbered as follows:
10237 //
10238 // planes in the interior of the old hex:
10239 //
10240 // *
10241 // /|
10242 // / | x
10243 // /3 * *-------* *----*----*
10244 // * /| | | / / /
10245 // | / | | | / 0 / 1 /
10246 // |/ * | | / / /
10247 // * 2/ *-------*y *----*----*x
10248 // | /
10249 // |/
10250 // *
10251 //
10252 // children of the faces
10253 // of the old hex
10254 // *---*---* *---*---*
10255 // /|13 | 15| / / /|
10256 // / | | | /18 / 19/ |
10257 // / *---*---* / / / *
10258 // * 5/| | | *---*---* 7/|
10259 // | / |12 | 14| | 9 | 11| / |
10260 // |/4 *---*---* | | |/6 *
10261 // * / / / *---*---* /
10262 // | /16 / 17/ | | | /
10263 // |/ / / | 8 | 10|/
10264 // *---*---* *---*---*
10265 //
10266 // note that we have to take care of the
10267 // orientation of faces.
10268 const int quad_indices[20] = {
10269 new_quads[0]->index(), // 0
10270 new_quads[1]->index(),
10271 new_quads[2]->index(),
10272 new_quads[3]->index(),
10273
10274 hex->face(0)->child_index(
10275 child_at_origin[hex->face(0)->refinement_case() -
10276 1][f_fl[0]][f_ro[0]]), // 4
10277 hex->face(0)->child_index(
10278 1 -
10279 child_at_origin[hex->face(0)->refinement_case() -
10280 1][f_fl[0]][f_ro[0]]),
10281
10282 hex->face(1)->child_index(
10283 child_at_origin[hex->face(1)->refinement_case() -
10284 1][f_fl[1]][f_ro[1]]), // 6
10285 hex->face(1)->child_index(
10286 1 -
10287 child_at_origin[hex->face(1)->refinement_case() -
10288 1][f_fl[1]][f_ro[1]]),
10289
10290 hex->face(2)->isotropic_child_index(
10292 0, f_or[2], f_fl[2], f_ro[2])), // 8
10293 hex->face(2)->isotropic_child_index(
10295 1, f_or[2], f_fl[2], f_ro[2])),
10296 hex->face(2)->isotropic_child_index(
10298 2, f_or[2], f_fl[2], f_ro[2])),
10299 hex->face(2)->isotropic_child_index(
10301 3, f_or[2], f_fl[2], f_ro[2])),
10302
10303 hex->face(3)->isotropic_child_index(
10305 0, f_or[3], f_fl[3], f_ro[3])), // 12
10306 hex->face(3)->isotropic_child_index(
10308 1, f_or[3], f_fl[3], f_ro[3])),
10309 hex->face(3)->isotropic_child_index(
10311 2, f_or[3], f_fl[3], f_ro[3])),
10312 hex->face(3)->isotropic_child_index(
10314 3, f_or[3], f_fl[3], f_ro[3])),
10315
10316 hex->face(4)->child_index(
10317 child_at_origin[hex->face(4)->refinement_case() -
10318 1][f_fl[4]][f_ro[4]]), // 16
10319 hex->face(4)->child_index(
10320 1 -
10321 child_at_origin[hex->face(4)->refinement_case() -
10322 1][f_fl[4]][f_ro[4]]),
10323
10324 hex->face(5)->child_index(
10325 child_at_origin[hex->face(5)->refinement_case() -
10326 1][f_fl[5]][f_ro[5]]), // 18
10327 hex->face(5)->child_index(
10328 1 -
10329 child_at_origin[hex->face(5)->refinement_case() -
10330 1][f_fl[5]][f_ro[5]])};
10331
10332 // due to the exchange of x and y for the front
10333 // and back face, we order the children
10334 // according to
10335 //
10336 // *---*---*
10337 // | 1 | 3 |
10338 // *---*---*
10339 // | 0 | 2 |
10340 // *---*---*
10341 new_hexes[0]->set_bounding_object_indices(
10342 {quad_indices[4],
10343 quad_indices[2],
10344 quad_indices[8],
10345 quad_indices[12],
10346 quad_indices[16],
10347 quad_indices[0]});
10348 new_hexes[1]->set_bounding_object_indices(
10349 {quad_indices[5],
10350 quad_indices[3],
10351 quad_indices[9],
10352 quad_indices[13],
10353 quad_indices[0],
10354 quad_indices[18]});
10355 new_hexes[2]->set_bounding_object_indices(
10356 {quad_indices[2],
10357 quad_indices[6],
10358 quad_indices[10],
10359 quad_indices[14],
10360 quad_indices[17],
10361 quad_indices[1]});
10362 new_hexes[3]->set_bounding_object_indices(
10363 {quad_indices[3],
10364 quad_indices[7],
10365 quad_indices[11],
10366 quad_indices[15],
10367 quad_indices[1],
10368 quad_indices[19]});
10369 break;
10370 }
10371
10373 {
10374 //----------------------------
10375 //
10376 // RefinementCase<dim>::cut_yz
10377 //
10378 // the refined cube will look like this:
10379 //
10380 // *---------*
10381 // / /|
10382 // *---------* |
10383 // / /| |
10384 // *---------* |/|
10385 // | | * |
10386 // | |/| *
10387 // *---------* |/
10388 // | | *
10389 // | |/
10390 // *---------*
10391 //
10392
10393 // first, create the new
10394 // internal line
10395 new_lines[0]->set_bounding_object_indices(
10396
10397 {middle_vertex_index<dim, spacedim>(hex->face(0)),
10398 middle_vertex_index<dim, spacedim>(hex->face(1))});
10399
10400 // again, first collect some data about the
10401 // indices of the lines, with the following
10402 // numbering: (note that face 0 and 1 each are
10403 // shown twice for better readability)
10404
10405 // face 0: left plane
10406 // * *
10407 // /| /|
10408 // * | * |
10409 // /| * /| *
10410 // * 5/| * |7|
10411 // | * | | * |
10412 // |/| * |6| *
10413 // * 4/ * |/
10414 // | * | *
10415 // |/ |/
10416 // * *
10417 // face 1: right plane
10418 // * *
10419 // /| /|
10420 // * | * |
10421 // /| * /| *
10422 // * 9/| * |11
10423 // | * | | * |
10424 // |/| * |10 *
10425 // * 8/ * |/
10426 // | * | *
10427 // |/ |/
10428 // * *
10429 // face 2: front plane
10430 // (note: x,y exchanged)
10431 // *-------*
10432 // | |
10433 // *---0---*
10434 // | |
10435 // *-------*
10436 // face 3: back plane
10437 // (note: x,y exchanged)
10438 // *-------*
10439 // | |
10440 // *---1---*
10441 // | |
10442 // *-------*
10443 // face 4: bottom plane
10444 // *-------*
10445 // / /
10446 // *---2---*
10447 // / /
10448 // *-------*
10449 // face 5: top plane
10450 // *-------*
10451 // / /
10452 // *---3---*
10453 // / /
10454 // *-------*
10455 // middle planes
10456 // *-------* *-------*
10457 // / / | |
10458 // *---12--* | |
10459 // / / | |
10460 // *-------* *-------*
10461
10462 // set up a list of line iterators first. from
10463 // this, construct lists of line_indices and
10464 // line orientations later on
10465 const typename Triangulation<
10466 dim,
10467 spacedim>::raw_line_iterator lines[13] = {
10468 hex->face(2)->child(0)->line(
10469 (hex->face(2)->refinement_case() ==
10471 1 :
10472 3), // 0
10473 hex->face(3)->child(0)->line(
10474 (hex->face(3)->refinement_case() ==
10476 1 :
10477 3), // 1
10478 hex->face(4)->child(0)->line(
10479 (hex->face(4)->refinement_case() ==
10481 1 :
10482 3), // 2
10483 hex->face(5)->child(0)->line(
10484 (hex->face(5)->refinement_case() ==
10486 1 :
10487 3), // 3
10488
10489 hex->face(0)
10490 ->isotropic_child(
10492 0, f_or[0], f_fl[0], f_ro[0]))
10493 ->line(
10495 1, f_or[0], f_fl[0], f_ro[0])), // 4
10496 hex->face(0)
10497 ->isotropic_child(
10499 3, f_or[0], f_fl[0], f_ro[0]))
10500 ->line(
10502 0, f_or[0], f_fl[0], f_ro[0])), // 5
10503 hex->face(0)
10504 ->isotropic_child(
10506 0, f_or[0], f_fl[0], f_ro[0]))
10507 ->line(
10509 3, f_or[0], f_fl[0], f_ro[0])), // 6
10510 hex->face(0)
10511 ->isotropic_child(
10513 3, f_or[0], f_fl[0], f_ro[0]))
10514 ->line(
10516 2, f_or[0], f_fl[0], f_ro[0])), // 7
10517
10518 hex->face(1)
10519 ->isotropic_child(
10521 0, f_or[1], f_fl[1], f_ro[1]))
10522 ->line(
10524 1, f_or[1], f_fl[1], f_ro[1])), // 8
10525 hex->face(1)
10526 ->isotropic_child(
10528 3, f_or[1], f_fl[1], f_ro[1]))
10529 ->line(
10531 0, f_or[1], f_fl[1], f_ro[1])), // 9
10532 hex->face(1)
10533 ->isotropic_child(
10535 0, f_or[1], f_fl[1], f_ro[1]))
10536 ->line(
10538 3, f_or[1], f_fl[1], f_ro[1])), // 10
10539 hex->face(1)
10540 ->isotropic_child(
10542 3, f_or[1], f_fl[1], f_ro[1]))
10543 ->line(
10545 2, f_or[1], f_fl[1], f_ro[1])), // 11
10546
10547 new_lines[0] // 12
10548 };
10549
10550 unsigned int line_indices[13];
10551
10552 for (unsigned int i = 0; i < 13; ++i)
10553 line_indices[i] = lines[i]->index();
10554
10555 // the orientation of lines for the inner quads
10556 // is quite tricky. as these lines are newly
10557 // created ones and thus have no parents, they
10558 // cannot inherit this property. set up an array
10559 // and fill it with the respective values
10560 bool line_orientation[13];
10561
10562 // the middle vertices of the lines of our front
10563 // face
10564 const unsigned int middle_vertices[4] = {
10565 hex->line(8)->child(0)->vertex_index(1),
10566 hex->line(10)->child(0)->vertex_index(1),
10567 hex->line(0)->child(0)->vertex_index(1),
10568 hex->line(4)->child(0)->vertex_index(1),
10569 };
10570
10571 // note: for lines 0 to 3 the orientation of the
10572 // line is 'true', if vertex 0 is on the front
10573 for (unsigned int i = 0; i < 4; ++i)
10574 if (lines[i]->vertex_index(0) == middle_vertices[i])
10575 line_orientation[i] = true;
10576 else
10577 {
10578 // it must be the other way round then
10579 Assert(lines[i]->vertex_index(1) ==
10580 middle_vertices[i],
10582 line_orientation[i] = false;
10583 }
10584
10585 // note: for lines 4 to 11 (inner lines of the
10586 // outer quads) the following holds: the second
10587 // vertex of the even lines in standard
10588 // orientation is the vertex in the middle of
10589 // the quad, whereas for odd lines the first
10590 // vertex is the same middle vertex.
10591 for (unsigned int i = 4; i < 12; ++i)
10592 if (lines[i]->vertex_index((i + 1) % 2) ==
10593 middle_vertex_index<dim, spacedim>(
10594 hex->face(i / 4 - 1)))
10595 line_orientation[i] = true;
10596 else
10597 {
10598 // it must be the other way
10599 // round then
10600 Assert(lines[i]->vertex_index(i % 2) ==
10601 (middle_vertex_index<dim, spacedim>(
10602 hex->face(i / 4 - 1))),
10604 line_orientation[i] = false;
10605 }
10606 // for the last line the line orientation is
10607 // always true, since it was just constructed
10608 // that way
10609 line_orientation[12] = true;
10610
10611 // set up the 4 quads, numbered as follows (left
10612 // quad numbering, right line numbering
10613 // extracted from above)
10614 //
10615 // x
10616 // *-------* *---3---*
10617 // | 3 | 5 9
10618 // *-------* *---12--*
10619 // | 2 | 4 8
10620 // *-------*y *---2---*
10621 //
10622 // y
10623 // *---------* *----1----*
10624 // / 1 / 7 11
10625 // *---------* *----12---*
10626 // / 0 / 6 10
10627 // *---------*x *----0----*
10628
10629 new_quads[0]->set_bounding_object_indices(
10630 {line_indices[6],
10631 line_indices[10],
10632 line_indices[0],
10633 line_indices[12]});
10634 new_quads[1]->set_bounding_object_indices(
10635 {line_indices[7],
10636 line_indices[11],
10637 line_indices[12],
10638 line_indices[1]});
10639 new_quads[2]->set_bounding_object_indices(
10640 {line_indices[2],
10641 line_indices[12],
10642 line_indices[4],
10643 line_indices[8]});
10644 new_quads[3]->set_bounding_object_indices(
10645 {line_indices[12],
10646 line_indices[3],
10647 line_indices[5],
10648 line_indices[9]});
10649
10650 new_quads[0]->set_line_orientation(
10651 0, line_orientation[6]);
10652 new_quads[0]->set_line_orientation(
10653 1, line_orientation[10]);
10654 new_quads[0]->set_line_orientation(
10655 2, line_orientation[0]);
10656
10657 new_quads[1]->set_line_orientation(
10658 0, line_orientation[7]);
10659 new_quads[1]->set_line_orientation(
10660 1, line_orientation[11]);
10661 new_quads[1]->set_line_orientation(
10662 3, line_orientation[1]);
10663
10664 new_quads[2]->set_line_orientation(
10665 0, line_orientation[2]);
10666 new_quads[2]->set_line_orientation(
10667 2, line_orientation[4]);
10668 new_quads[2]->set_line_orientation(
10669 3, line_orientation[8]);
10670
10671 new_quads[3]->set_line_orientation(
10672 1, line_orientation[3]);
10673 new_quads[3]->set_line_orientation(
10674 2, line_orientation[5]);
10675 new_quads[3]->set_line_orientation(
10676 3, line_orientation[9]);
10677
10678 // the quads are numbered as follows:
10679 //
10680 // planes in the interior of the old hex:
10681 //
10682 // *
10683 // /|
10684 // / | x
10685 // / | *-------* *---------*
10686 // * | | 3 | / 1 /
10687 // | | *-------* *---------*
10688 // | * | 2 | / 0 /
10689 // | / *-------*y *---------*x
10690 // | /
10691 // |/
10692 // *
10693 //
10694 // children of the faces
10695 // of the old hex
10696 // *-------* *-------*
10697 // /| | / 19 /|
10698 // * | 15 | *-------* |
10699 // /|7*-------* / 18 /|11
10700 // * |/| | *-------* |/|
10701 // |6* | 14 | | 10* |
10702 // |/|5*-------* | 13 |/|9*
10703 // * |/ 17 / *-------* |/
10704 // |4*-------* | |8*
10705 // |/ 16 / | 12 |/
10706 // *-------* *-------*
10707 //
10708 // note that we have to take care of the
10709 // orientation of faces.
10710 const int quad_indices[20] = {
10711 new_quads[0]->index(), // 0
10712 new_quads[1]->index(),
10713 new_quads[2]->index(),
10714 new_quads[3]->index(),
10715
10716 hex->face(0)->isotropic_child_index(
10718 0, f_or[0], f_fl[0], f_ro[0])), // 4
10719 hex->face(0)->isotropic_child_index(
10721 1, f_or[0], f_fl[0], f_ro[0])),
10722 hex->face(0)->isotropic_child_index(
10724 2, f_or[0], f_fl[0], f_ro[0])),
10725 hex->face(0)->isotropic_child_index(
10727 3, f_or[0], f_fl[0], f_ro[0])),
10728
10729 hex->face(1)->isotropic_child_index(
10731 0, f_or[1], f_fl[1], f_ro[1])), // 8
10732 hex->face(1)->isotropic_child_index(
10734 1, f_or[1], f_fl[1], f_ro[1])),
10735 hex->face(1)->isotropic_child_index(
10737 2, f_or[1], f_fl[1], f_ro[1])),
10738 hex->face(1)->isotropic_child_index(
10740 3, f_or[1], f_fl[1], f_ro[1])),
10741
10742 hex->face(2)->child_index(
10743 child_at_origin[hex->face(2)->refinement_case() -
10744 1][f_fl[2]][f_ro[2]]), // 12
10745 hex->face(2)->child_index(
10746 1 -
10747 child_at_origin[hex->face(2)->refinement_case() -
10748 1][f_fl[2]][f_ro[2]]),
10749
10750 hex->face(3)->child_index(
10751 child_at_origin[hex->face(3)->refinement_case() -
10752 1][f_fl[3]][f_ro[3]]), // 14
10753 hex->face(3)->child_index(
10754 1 -
10755 child_at_origin[hex->face(3)->refinement_case() -
10756 1][f_fl[3]][f_ro[3]]),
10757
10758 hex->face(4)->child_index(
10759 child_at_origin[hex->face(4)->refinement_case() -
10760 1][f_fl[4]][f_ro[4]]), // 16
10761 hex->face(4)->child_index(
10762 1 -
10763 child_at_origin[hex->face(4)->refinement_case() -
10764 1][f_fl[4]][f_ro[4]]),
10765
10766 hex->face(5)->child_index(
10767 child_at_origin[hex->face(5)->refinement_case() -
10768 1][f_fl[5]][f_ro[5]]), // 18
10769 hex->face(5)->child_index(
10770 1 -
10771 child_at_origin[hex->face(5)->refinement_case() -
10772 1][f_fl[5]][f_ro[5]])};
10773
10774 new_hexes[0]->set_bounding_object_indices(
10775 {quad_indices[4],
10776 quad_indices[8],
10777 quad_indices[12],
10778 quad_indices[2],
10779 quad_indices[16],
10780 quad_indices[0]});
10781 new_hexes[1]->set_bounding_object_indices(
10782 {quad_indices[5],
10783 quad_indices[9],
10784 quad_indices[2],
10785 quad_indices[14],
10786 quad_indices[17],
10787 quad_indices[1]});
10788 new_hexes[2]->set_bounding_object_indices(
10789 {quad_indices[6],
10790 quad_indices[10],
10791 quad_indices[13],
10792 quad_indices[3],
10793 quad_indices[0],
10794 quad_indices[18]});
10795 new_hexes[3]->set_bounding_object_indices(
10796 {quad_indices[7],
10797 quad_indices[11],
10798 quad_indices[3],
10799 quad_indices[15],
10800 quad_indices[1],
10801 quad_indices[19]});
10802 break;
10803 }
10804
10806 {
10807 //----------------------------
10808 //
10809 // RefinementCase<dim>::cut_xyz
10810 // isotropic refinement
10811 //
10812 // the refined cube will look
10813 // like this:
10814 //
10815 // *----*----*
10816 // / / /|
10817 // *----*----* |
10818 // / / /| *
10819 // *----*----* |/|
10820 // | | | * |
10821 // | | |/| *
10822 // *----*----* |/
10823 // | | | *
10824 // | | |/
10825 // *----*----*
10826 //
10827
10828 // find the next unused vertex and set it
10829 // appropriately
10830 while (
10831 triangulation.vertices_used[next_unused_vertex] ==
10832 true)
10833 ++next_unused_vertex;
10834 Assert(
10835 next_unused_vertex < triangulation.vertices.size(),
10836 ExcMessage(
10837 "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."));
10838 triangulation.vertices_used[next_unused_vertex] =
10839 true;
10840
10841 // the new vertex is definitely in the interior,
10842 // so we need not worry about the
10843 // boundary. However we need to worry about
10844 // Manifolds. Let the cell compute its own
10845 // center, by querying the underlying manifold
10846 // object.
10847 triangulation.vertices[next_unused_vertex] =
10848 hex->center(true, true);
10849
10850 // set the data of the six lines. first collect
10851 // the indices of the seven vertices (consider
10852 // the two planes to be crossed to form the
10853 // planes cutting the hex in two vertically and
10854 // horizontally)
10855 //
10856 // *--3--* *--5--*
10857 // / / / | | |
10858 // 0--6--1 0--6--1
10859 // / / / | | |
10860 // *--2--* *--4--*
10861 // the lines are numbered
10862 // as follows:
10863 // *--*--* *--*--*
10864 // / 1 / | 5 |
10865 // *2-*-3* *2-*-3*
10866 // / 0 / | 4 |
10867 // *--*--* *--*--*
10868 //
10869 const unsigned int vertex_indices[7] = {
10870 middle_vertex_index<dim, spacedim>(hex->face(0)),
10871 middle_vertex_index<dim, spacedim>(hex->face(1)),
10872 middle_vertex_index<dim, spacedim>(hex->face(2)),
10873 middle_vertex_index<dim, spacedim>(hex->face(3)),
10874 middle_vertex_index<dim, spacedim>(hex->face(4)),
10875 middle_vertex_index<dim, spacedim>(hex->face(5)),
10876 next_unused_vertex};
10877
10878 new_lines[0]->set_bounding_object_indices(
10880 new_lines[1]->set_bounding_object_indices(
10882 new_lines[2]->set_bounding_object_indices(
10884 new_lines[3]->set_bounding_object_indices(
10886 new_lines[4]->set_bounding_object_indices(
10888 new_lines[5]->set_bounding_object_indices(
10890
10891 // again, first collect some data about the
10892 // indices of the lines, with the following
10893 // numbering: (note that face 0 and 1 each are
10894 // shown twice for better readability)
10895
10896 // face 0: left plane
10897 // * *
10898 // /| /|
10899 // * | * |
10900 // /| * /| *
10901 // * 1/| * |3|
10902 // | * | | * |
10903 // |/| * |2| *
10904 // * 0/ * |/
10905 // | * | *
10906 // |/ |/
10907 // * *
10908 // face 1: right plane
10909 // * *
10910 // /| /|
10911 // * | * |
10912 // /| * /| *
10913 // * 5/| * |7|
10914 // | * | | * |
10915 // |/| * |6| *
10916 // * 4/ * |/
10917 // | * | *
10918 // |/ |/
10919 // * *
10920 // face 2: front plane
10921 // (note: x,y exchanged)
10922 // *---*---*
10923 // | 11 |
10924 // *-8-*-9-*
10925 // | 10 |
10926 // *---*---*
10927 // face 3: back plane
10928 // (note: x,y exchanged)
10929 // *---*---*
10930 // | 15 |
10931 // *12-*-13*
10932 // | 14 |
10933 // *---*---*
10934 // face 4: bottom plane
10935 // *---*---*
10936 // / 17 /
10937 // *18-*-19*
10938 // / 16 /
10939 // *---*---*
10940 // face 5: top plane
10941 // *---*---*
10942 // / 21 /
10943 // *22-*-23*
10944 // / 20 /
10945 // *---*---*
10946 // middle planes
10947 // *---*---* *---*---*
10948 // / 25 / | 29 |
10949 // *26-*-27* *26-*-27*
10950 // / 24 / | 28 |
10951 // *---*---* *---*---*
10952
10953 // set up a list of line iterators first. from
10954 // this, construct lists of line_indices and
10955 // line orientations later on
10956 const typename Triangulation<
10957 dim,
10958 spacedim>::raw_line_iterator lines[30] = {
10959 hex->face(0)
10960 ->isotropic_child(
10962 0, f_or[0], f_fl[0], f_ro[0]))
10963 ->line(
10965 1, f_or[0], f_fl[0], f_ro[0])), // 0
10966 hex->face(0)
10967 ->isotropic_child(
10969 3, f_or[0], f_fl[0], f_ro[0]))
10970 ->line(
10972 0, f_or[0], f_fl[0], f_ro[0])), // 1
10973 hex->face(0)
10974 ->isotropic_child(
10976 0, f_or[0], f_fl[0], f_ro[0]))
10977 ->line(
10979 3, f_or[0], f_fl[0], f_ro[0])), // 2
10980 hex->face(0)
10981 ->isotropic_child(
10983 3, f_or[0], f_fl[0], f_ro[0]))
10984 ->line(
10986 2, f_or[0], f_fl[0], f_ro[0])), // 3
10987
10988 hex->face(1)
10989 ->isotropic_child(
10991 0, f_or[1], f_fl[1], f_ro[1]))
10992 ->line(
10994 1, f_or[1], f_fl[1], f_ro[1])), // 4
10995 hex->face(1)
10996 ->isotropic_child(
10998 3, f_or[1], f_fl[1], f_ro[1]))
10999 ->line(
11001 0, f_or[1], f_fl[1], f_ro[1])), // 5
11002 hex->face(1)
11003 ->isotropic_child(
11005 0, f_or[1], f_fl[1], f_ro[1]))
11006 ->line(
11008 3, f_or[1], f_fl[1], f_ro[1])), // 6
11009 hex->face(1)
11010 ->isotropic_child(
11012 3, f_or[1], f_fl[1], f_ro[1]))
11013 ->line(
11015 2, f_or[1], f_fl[1], f_ro[1])), // 7
11016
11017 hex->face(2)
11018 ->isotropic_child(
11020 0, f_or[2], f_fl[2], f_ro[2]))
11021 ->line(
11023 1, f_or[2], f_fl[2], f_ro[2])), // 8
11024 hex->face(2)
11025 ->isotropic_child(
11027 3, f_or[2], f_fl[2], f_ro[2]))
11028 ->line(
11030 0, f_or[2], f_fl[2], f_ro[2])), // 9
11031 hex->face(2)
11032 ->isotropic_child(
11034 0, f_or[2], f_fl[2], f_ro[2]))
11035 ->line(
11037 3, f_or[2], f_fl[2], f_ro[2])), // 10
11038 hex->face(2)
11039 ->isotropic_child(
11041 3, f_or[2], f_fl[2], f_ro[2]))
11042 ->line(
11044 2, f_or[2], f_fl[2], f_ro[2])), // 11
11045
11046 hex->face(3)
11047 ->isotropic_child(
11049 0, f_or[3], f_fl[3], f_ro[3]))
11050 ->line(
11052 1, f_or[3], f_fl[3], f_ro[3])), // 12
11053 hex->face(3)
11054 ->isotropic_child(
11056 3, f_or[3], f_fl[3], f_ro[3]))
11057 ->line(
11059 0, f_or[3], f_fl[3], f_ro[3])), // 13
11060 hex->face(3)
11061 ->isotropic_child(
11063 0, f_or[3], f_fl[3], f_ro[3]))
11064 ->line(
11066 3, f_or[3], f_fl[3], f_ro[3])), // 14
11067 hex->face(3)
11068 ->isotropic_child(
11070 3, f_or[3], f_fl[3], f_ro[3]))
11071 ->line(
11073 2, f_or[3], f_fl[3], f_ro[3])), // 15
11074
11075 hex->face(4)
11076 ->isotropic_child(
11078 0, f_or[4], f_fl[4], f_ro[4]))
11079 ->line(
11081 1, f_or[4], f_fl[4], f_ro[4])), // 16
11082 hex->face(4)
11083 ->isotropic_child(
11085 3, f_or[4], f_fl[4], f_ro[4]))
11086 ->line(
11088 0, f_or[4], f_fl[4], f_ro[4])), // 17
11089 hex->face(4)
11090 ->isotropic_child(
11092 0, f_or[4], f_fl[4], f_ro[4]))
11093 ->line(
11095 3, f_or[4], f_fl[4], f_ro[4])), // 18
11096 hex->face(4)
11097 ->isotropic_child(
11099 3, f_or[4], f_fl[4], f_ro[4]))
11100 ->line(
11102 2, f_or[4], f_fl[4], f_ro[4])), // 19
11103
11104 hex->face(5)
11105 ->isotropic_child(
11107 0, f_or[5], f_fl[5], f_ro[5]))
11108 ->line(
11110 1, f_or[5], f_fl[5], f_ro[5])), // 20
11111 hex->face(5)
11112 ->isotropic_child(
11114 3, f_or[5], f_fl[5], f_ro[5]))
11115 ->line(
11117 0, f_or[5], f_fl[5], f_ro[5])), // 21
11118 hex->face(5)
11119 ->isotropic_child(
11121 0, f_or[5], f_fl[5], f_ro[5]))
11122 ->line(
11124 3, f_or[5], f_fl[5], f_ro[5])), // 22
11125 hex->face(5)
11126 ->isotropic_child(
11128 3, f_or[5], f_fl[5], f_ro[5]))
11129 ->line(
11131 2, f_or[5], f_fl[5], f_ro[5])), // 23
11132
11133 new_lines[0], // 24
11134 new_lines[1], // 25
11135 new_lines[2], // 26
11136 new_lines[3], // 27
11137 new_lines[4], // 28
11138 new_lines[5] // 29
11139 };
11140
11141 unsigned int line_indices[30];
11142 for (unsigned int i = 0; i < 30; ++i)
11143 line_indices[i] = lines[i]->index();
11144
11145 // the orientation of lines for the inner quads
11146 // is quite tricky. as these lines are newly
11147 // created ones and thus have no parents, they
11148 // cannot inherit this property. set up an array
11149 // and fill it with the respective values
11150 bool line_orientation[30];
11151
11152 // note: for the first 24 lines (inner lines of
11153 // the outer quads) the following holds: the
11154 // second vertex of the even lines in standard
11155 // orientation is the vertex in the middle of
11156 // the quad, whereas for odd lines the first
11157 // vertex is the same middle vertex.
11158 for (unsigned int i = 0; i < 24; ++i)
11159 if (lines[i]->vertex_index((i + 1) % 2) ==
11160 vertex_indices[i / 4])
11161 line_orientation[i] = true;
11162 else
11163 {
11164 // it must be the other way
11165 // round then
11166 Assert(lines[i]->vertex_index(i % 2) ==
11167 vertex_indices[i / 4],
11169 line_orientation[i] = false;
11170 }
11171 // for the last 6 lines the line orientation is
11172 // always true, since they were just constructed
11173 // that way
11174 for (unsigned int i = 24; i < 30; ++i)
11175 line_orientation[i] = true;
11176
11177 // set up the 12 quads, numbered as follows
11178 // (left quad numbering, right line numbering
11179 // extracted from above)
11180 //
11181 // * *
11182 // /| 21|
11183 // * | * 15
11184 // y/|3* 20| *
11185 // * |/| * |/|
11186 // |2* |x 11 * 14
11187 // |/|1* |/| *
11188 // * |/ * |17
11189 // |0* 10 *
11190 // |/ |16
11191 // * *
11192 //
11193 // x
11194 // *---*---* *22-*-23*
11195 // | 5 | 7 | 1 29 5
11196 // *---*---* *26-*-27*
11197 // | 4 | 6 | 0 28 4
11198 // *---*---*y *18-*-19*
11199 //
11200 // y
11201 // *----*----* *-12-*-13-*
11202 // / 10 / 11 / 3 25 7
11203 // *----*----* *-26-*-27-*
11204 // / 8 / 9 / 2 24 6
11205 // *----*----*x *--8-*--9-*
11206
11207 new_quads[0]->set_bounding_object_indices(
11208 {line_indices[10],
11209 line_indices[28],
11210 line_indices[16],
11211 line_indices[24]});
11212 new_quads[1]->set_bounding_object_indices(
11213 {line_indices[28],
11214 line_indices[14],
11215 line_indices[17],
11216 line_indices[25]});
11217 new_quads[2]->set_bounding_object_indices(
11218 {line_indices[11],
11219 line_indices[29],
11220 line_indices[24],
11221 line_indices[20]});
11222 new_quads[3]->set_bounding_object_indices(
11223 {line_indices[29],
11224 line_indices[15],
11225 line_indices[25],
11226 line_indices[21]});
11227 new_quads[4]->set_bounding_object_indices(
11228 {line_indices[18],
11229 line_indices[26],
11230 line_indices[0],
11231 line_indices[28]});
11232 new_quads[5]->set_bounding_object_indices(
11233 {line_indices[26],
11234 line_indices[22],
11235 line_indices[1],
11236 line_indices[29]});
11237 new_quads[6]->set_bounding_object_indices(
11238 {line_indices[19],
11239 line_indices[27],
11240 line_indices[28],
11241 line_indices[4]});
11242 new_quads[7]->set_bounding_object_indices(
11243 {line_indices[27],
11244 line_indices[23],
11245 line_indices[29],
11246 line_indices[5]});
11247 new_quads[8]->set_bounding_object_indices(
11248 {line_indices[2],
11249 line_indices[24],
11250 line_indices[8],
11251 line_indices[26]});
11252 new_quads[9]->set_bounding_object_indices(
11253 {line_indices[24],
11254 line_indices[6],
11255 line_indices[9],
11256 line_indices[27]});
11257 new_quads[10]->set_bounding_object_indices(
11258 {line_indices[3],
11259 line_indices[25],
11260 line_indices[26],
11261 line_indices[12]});
11262 new_quads[11]->set_bounding_object_indices(
11263 {line_indices[25],
11264 line_indices[7],
11265 line_indices[27],
11266 line_indices[13]});
11267
11268 // now reset the line_orientation flags of outer
11269 // lines as they cannot be set in a loop (at
11270 // least not easily)
11271 new_quads[0]->set_line_orientation(
11272 0, line_orientation[10]);
11273 new_quads[0]->set_line_orientation(
11274 2, line_orientation[16]);
11275
11276 new_quads[1]->set_line_orientation(
11277 1, line_orientation[14]);
11278 new_quads[1]->set_line_orientation(
11279 2, line_orientation[17]);
11280
11281 new_quads[2]->set_line_orientation(
11282 0, line_orientation[11]);
11283 new_quads[2]->set_line_orientation(
11284 3, line_orientation[20]);
11285
11286 new_quads[3]->set_line_orientation(
11287 1, line_orientation[15]);
11288 new_quads[3]->set_line_orientation(
11289 3, line_orientation[21]);
11290
11291 new_quads[4]->set_line_orientation(
11292 0, line_orientation[18]);
11293 new_quads[4]->set_line_orientation(
11294 2, line_orientation[0]);
11295
11296 new_quads[5]->set_line_orientation(
11297 1, line_orientation[22]);
11298 new_quads[5]->set_line_orientation(
11299 2, line_orientation[1]);
11300
11301 new_quads[6]->set_line_orientation(
11302 0, line_orientation[19]);
11303 new_quads[6]->set_line_orientation(
11304 3, line_orientation[4]);
11305
11306 new_quads[7]->set_line_orientation(
11307 1, line_orientation[23]);
11308 new_quads[7]->set_line_orientation(
11309 3, line_orientation[5]);
11310
11311 new_quads[8]->set_line_orientation(
11312 0, line_orientation[2]);
11313 new_quads[8]->set_line_orientation(
11314 2, line_orientation[8]);
11315
11316 new_quads[9]->set_line_orientation(
11317 1, line_orientation[6]);
11318 new_quads[9]->set_line_orientation(
11319 2, line_orientation[9]);
11320
11321 new_quads[10]->set_line_orientation(
11322 0, line_orientation[3]);
11323 new_quads[10]->set_line_orientation(
11324 3, line_orientation[12]);
11325
11326 new_quads[11]->set_line_orientation(
11327 1, line_orientation[7]);
11328 new_quads[11]->set_line_orientation(
11329 3, line_orientation[13]);
11330
11331 //-------------------------------
11332 // create the eight new hexes
11333 //
11334 // again first collect some data. here, we need
11335 // the indices of a whole lotta quads.
11336
11337 // the quads are numbered as follows:
11338 //
11339 // planes in the interior of the old hex:
11340 //
11341 // *
11342 // /|
11343 // * |
11344 // /|3* *---*---* *----*----*
11345 // * |/| | 5 | 7 | / 10 / 11 /
11346 // |2* | *---*---* *----*----*
11347 // |/|1* | 4 | 6 | / 8 / 9 /
11348 // * |/ *---*---*y *----*----*x
11349 // |0*
11350 // |/
11351 // *
11352 //
11353 // children of the faces
11354 // of the old hex
11355 // *-------* *-------*
11356 // /|25 27| /34 35/|
11357 // 15| | / /19
11358 // / | | /32 33/ |
11359 // * |24 26| *-------*18 |
11360 // 1413*-------* |21 23| 17*
11361 // | /30 31/ | | /
11362 // 12/ / | |16
11363 // |/28 29/ |20 22|/
11364 // *-------* *-------*
11365 //
11366 // note that we have to
11367 // take care of the
11368 // orientation of
11369 // faces.
11370 const int quad_indices[36] = {
11371 new_quads[0]->index(), // 0
11372 new_quads[1]->index(),
11373 new_quads[2]->index(),
11374 new_quads[3]->index(),
11375 new_quads[4]->index(),
11376 new_quads[5]->index(),
11377 new_quads[6]->index(),
11378 new_quads[7]->index(),
11379 new_quads[8]->index(),
11380 new_quads[9]->index(),
11381 new_quads[10]->index(),
11382 new_quads[11]->index(), // 11
11383
11384 hex->face(0)->isotropic_child_index(
11386 0, f_or[0], f_fl[0], f_ro[0])), // 12
11387 hex->face(0)->isotropic_child_index(
11389 1, f_or[0], f_fl[0], f_ro[0])),
11390 hex->face(0)->isotropic_child_index(
11392 2, f_or[0], f_fl[0], f_ro[0])),
11393 hex->face(0)->isotropic_child_index(
11395 3, f_or[0], f_fl[0], f_ro[0])),
11396
11397 hex->face(1)->isotropic_child_index(
11399 0, f_or[1], f_fl[1], f_ro[1])), // 16
11400 hex->face(1)->isotropic_child_index(
11402 1, f_or[1], f_fl[1], f_ro[1])),
11403 hex->face(1)->isotropic_child_index(
11405 2, f_or[1], f_fl[1], f_ro[1])),
11406 hex->face(1)->isotropic_child_index(
11408 3, f_or[1], f_fl[1], f_ro[1])),
11409
11410 hex->face(2)->isotropic_child_index(
11412 0, f_or[2], f_fl[2], f_ro[2])), // 20
11413 hex->face(2)->isotropic_child_index(
11415 1, f_or[2], f_fl[2], f_ro[2])),
11416 hex->face(2)->isotropic_child_index(
11418 2, f_or[2], f_fl[2], f_ro[2])),
11419 hex->face(2)->isotropic_child_index(
11421 3, f_or[2], f_fl[2], f_ro[2])),
11422
11423 hex->face(3)->isotropic_child_index(
11425 0, f_or[3], f_fl[3], f_ro[3])), // 24
11426 hex->face(3)->isotropic_child_index(
11428 1, f_or[3], f_fl[3], f_ro[3])),
11429 hex->face(3)->isotropic_child_index(
11431 2, f_or[3], f_fl[3], f_ro[3])),
11432 hex->face(3)->isotropic_child_index(
11434 3, f_or[3], f_fl[3], f_ro[3])),
11435
11436 hex->face(4)->isotropic_child_index(
11438 0, f_or[4], f_fl[4], f_ro[4])), // 28
11439 hex->face(4)->isotropic_child_index(
11441 1, f_or[4], f_fl[4], f_ro[4])),
11442 hex->face(4)->isotropic_child_index(
11444 2, f_or[4], f_fl[4], f_ro[4])),
11445 hex->face(4)->isotropic_child_index(
11447 3, f_or[4], f_fl[4], f_ro[4])),
11448
11449 hex->face(5)->isotropic_child_index(
11451 0, f_or[5], f_fl[5], f_ro[5])), // 32
11452 hex->face(5)->isotropic_child_index(
11454 1, f_or[5], f_fl[5], f_ro[5])),
11455 hex->face(5)->isotropic_child_index(
11457 2, f_or[5], f_fl[5], f_ro[5])),
11458 hex->face(5)->isotropic_child_index(
11460 3, f_or[5], f_fl[5], f_ro[5]))};
11461
11462 // bottom children
11463 new_hexes[0]->set_bounding_object_indices(
11464 {quad_indices[12],
11465 quad_indices[0],
11466 quad_indices[20],
11467 quad_indices[4],
11468 quad_indices[28],
11469 quad_indices[8]});
11470 new_hexes[1]->set_bounding_object_indices(
11471 {quad_indices[0],
11472 quad_indices[16],
11473 quad_indices[22],
11474 quad_indices[6],
11475 quad_indices[29],
11476 quad_indices[9]});
11477 new_hexes[2]->set_bounding_object_indices(
11478 {quad_indices[13],
11479 quad_indices[1],
11480 quad_indices[4],
11481 quad_indices[24],
11482 quad_indices[30],
11483 quad_indices[10]});
11484 new_hexes[3]->set_bounding_object_indices(
11485 {quad_indices[1],
11486 quad_indices[17],
11487 quad_indices[6],
11488 quad_indices[26],
11489 quad_indices[31],
11490 quad_indices[11]});
11491
11492 // top children
11493 new_hexes[4]->set_bounding_object_indices(
11494 {quad_indices[14],
11495 quad_indices[2],
11496 quad_indices[21],
11497 quad_indices[5],
11498 quad_indices[8],
11499 quad_indices[32]});
11500 new_hexes[5]->set_bounding_object_indices(
11501 {quad_indices[2],
11502 quad_indices[18],
11503 quad_indices[23],
11504 quad_indices[7],
11505 quad_indices[9],
11506 quad_indices[33]});
11507 new_hexes[6]->set_bounding_object_indices(
11508 {quad_indices[15],
11509 quad_indices[3],
11510 quad_indices[5],
11511 quad_indices[25],
11512 quad_indices[10],
11513 quad_indices[34]});
11514 new_hexes[7]->set_bounding_object_indices(
11515 {quad_indices[3],
11516 quad_indices[19],
11517 quad_indices[7],
11518 quad_indices[27],
11519 quad_indices[11],
11520 quad_indices[35]});
11521 break;
11522 }
11523 default:
11524 // all refinement cases have been treated, there
11525 // only remains
11526 // RefinementCase<dim>::no_refinement as
11527 // untreated enumeration value. However, in that
11528 // case we should have aborted much
11529 // earlier. thus we should never get here
11531 break;
11532 } // switch (ref_case)
11533
11534 // and set face orientation flags. note that new
11535 // faces in the interior of the mother cell always
11536 // have a correctly oriented face, but the ones on
11537 // the outer faces will inherit this flag
11538 //
11539 // the flag have been set to true for all faces
11540 // initially, now go the other way round and reset
11541 // faces that are at the boundary of the mother cube
11542 //
11543 // the same is true for the face_flip and
11544 // face_rotation flags. however, the latter two are
11545 // set to false by default as this is the standard
11546 // value
11547
11548 // loop over all faces and all (relevant) subfaces
11549 // of that in order to set the correct values for
11550 // face_orientation, face_flip and face_rotation,
11551 // which are inherited from the corresponding face
11552 // of the mother cube
11553 for (const unsigned int f : GeometryInfo<dim>::face_indices())
11554 for (unsigned int s = 0;
11557 ref_case, f)),
11558 1U);
11559 ++s)
11560 {
11561 const unsigned int current_child =
11563 ref_case,
11564 f,
11565 s,
11566 f_or[f],
11567 f_fl[f],
11568 f_ro[f],
11570 ref_case, f, f_or[f], f_fl[f], f_ro[f]));
11571 new_hexes[current_child]->set_combined_face_orientation(
11572 f, f_co[f]);
11573 }
11574
11575 // now see if we have created cells that are
11576 // distorted and if so add them to our list
11577 if (check_for_distorted_cells &&
11578 has_distorted_children<dim, spacedim>(hex))
11579 cells_with_distorted_children.distorted_cells.push_back(
11580 hex);
11581
11582 // note that the refinement flag was already cleared
11583 // at the beginning of this loop
11584
11585 // inform all listeners that cell refinement is done
11586 triangulation.signals.post_refinement_on_cell(hex);
11587 }
11588 }
11589
11590 // clear user data on quads. we used some of this data to
11591 // indicate anisotropic refinemnt cases on faces. all data
11592 // should be cleared by now, but the information whether we
11593 // used indices or pointers is still present. reset it now to
11594 // enable the user to use whichever they like later on.
11595 triangulation.faces->quads.clear_user_data();
11596
11597 // return the list with distorted children
11598 return cells_with_distorted_children;
11599 }
11600
11601
11614 template <int spacedim>
11615 static void
11618
11619
11620
11621 template <int dim, int spacedim>
11622 static void
11625 {
11626 // If the codimension is one, we cannot perform this check
11627 // yet.
11628 if (spacedim > dim)
11629 return;
11630
11631 for (const auto &cell : triangulation.cell_iterators())
11632 if (cell->at_boundary() && cell->refine_flag_set() &&
11633 cell->refine_flag_set() !=
11635 {
11636 // The cell is at the boundary and it is flagged for
11637 // anisotropic refinement. Therefore, we have a closer
11638 // look
11639 const RefinementCase<dim> ref_case = cell->refine_flag_set();
11640 for (const unsigned int face_no :
11642 if (cell->face(face_no)->at_boundary())
11643 {
11644 // this is the critical face at the boundary.
11646 face_no) !=
11647 RefinementCase<dim - 1>::isotropic_refinement)
11648 {
11649 // up to now, we do not want to refine this
11650 // cell along the face under consideration
11651 // here.
11652 const typename Triangulation<dim,
11653 spacedim>::face_iterator
11654 face = cell->face(face_no);
11655 // the new point on the boundary would be this
11656 // one.
11657 const Point<spacedim> new_bound = face->center(true);
11658 // to check it, transform to the unit cell
11659 // with a linear mapping
11660 const Point<dim> new_unit =
11661 cell->reference_cell()
11662 .template get_default_linear_mapping<dim,
11663 spacedim>()
11664 .transform_real_to_unit_cell(cell, new_bound);
11665
11666 // Now, we have to calculate the distance from
11667 // the face in the unit cell.
11668
11669 // take the correct coordinate direction (0
11670 // for faces 0 and 1, 1 for faces 2 and 3, 2
11671 // for faces 4 and 5) and subtract the correct
11672 // boundary value of the face (0 for faces 0,
11673 // 2, and 4; 1 for faces 1, 3 and 5)
11674 const double dist =
11675 std::fabs(new_unit[face_no / 2] - face_no % 2);
11676
11677 // compare this with the empirical value
11678 // allowed. if it is too big, flag the face
11679 // for isotropic refinement
11680 const double allowed = 0.25;
11681
11682 if (dist > allowed)
11683 cell->flag_for_face_refinement(face_no);
11684 } // if flagged for anistropic refinement
11685 } // if (cell->face(face)->at_boundary())
11686 } // for all cells
11687 }
11688
11689
11702 template <int dim, int spacedim>
11703 static void
11705 {
11706 Assert(dim < 3,
11707 ExcMessage("Wrong function called -- there should "
11708 "be a specialization."));
11709 }
11710
11711
11712 template <int spacedim>
11713 static void
11716 {
11717 const unsigned int dim = 3;
11718 using raw_line_iterator =
11720
11721 // variable to store whether the mesh was changed in the
11722 // present loop and in the whole process
11723 bool mesh_changed = false;
11724
11725 do
11726 {
11727 mesh_changed = false;
11728
11729 // for this following, we need to know which cells are
11730 // going to be coarsened, if we had to make a
11731 // decision. the following function sets these flags:
11732 triangulation.fix_coarsen_flags();
11733
11734 // first clear flags on lines, since we need them to determine
11735 // which lines will be refined
11736 triangulation.clear_user_flags_line();
11737
11738 // flag those lines that are refined and will not be
11739 // coarsened and those that will be refined
11740 for (const auto &cell : triangulation.cell_iterators())
11741 if (cell->refine_flag_set())
11742 {
11743 const std::array<unsigned int, 12> line_indices =
11744 TriaAccessorImplementation::Implementation::
11745 get_line_indices_of_cell(*cell);
11746 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11748 cell->refine_flag_set(), l) ==
11750 {
11751 raw_line_iterator line(&triangulation,
11752 0,
11753 line_indices[l]);
11754 // flag a line, that will be refined
11755 line->set_user_flag();
11756 }
11757 }
11758 else if (cell->has_children() &&
11759 !cell->child(0)->coarsen_flag_set())
11760 {
11761 const std::array<unsigned int, 12> line_indices =
11762 TriaAccessorImplementation::Implementation::
11763 get_line_indices_of_cell(*cell);
11764 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11766 cell->refinement_case(), l) ==
11768 {
11769 raw_line_iterator line(&triangulation,
11770 0,
11771 line_indices[l]);
11772 // flag a line, that is refined and will stay so
11773 line->set_user_flag();
11774 }
11775 }
11776 else if (cell->has_children() &&
11777 cell->child(0)->coarsen_flag_set())
11778 cell->set_user_flag();
11779
11780
11781 // now check whether there are cells with lines that are
11782 // more than once refined or that will be more than once
11783 // refined. The first thing should never be the case, in
11784 // the second case we flag the cell for refinement
11786 cell = triangulation.last_active();
11787 cell != triangulation.end();
11788 --cell)
11789 {
11790 const std::array<unsigned int, 12> line_indices =
11791 TriaAccessorImplementation::Implementation::
11792 get_line_indices_of_cell(*cell);
11793 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11794 {
11795 raw_line_iterator line(&triangulation, 0, line_indices[l]);
11796 if (line->has_children())
11797 {
11798 // if this line is refined, its children should
11799 // not have further children
11800 //
11801 // however, if any of the children is flagged
11802 // for further refinement, we need to refine
11803 // this cell also (at least, if the cell is not
11804 // already flagged)
11805 bool offending_line_found = false;
11806
11807 for (unsigned int c = 0; c < 2; ++c)
11808 {
11809 Assert(line->child(c)->has_children() == false,
11811
11812 if (line->child(c)->user_flag_set() &&
11814 cell->refine_flag_set(), l) ==
11816 {
11817 // tag this cell for refinement
11818 cell->clear_coarsen_flag();
11819 // if anisotropic coarsening is allowed:
11820 // extend the refine_flag in the needed
11821 // direction, else set refine_flag
11822 // (isotropic)
11823 if (triangulation.smooth_grid &
11825 allow_anisotropic_smoothing)
11826 cell->flag_for_line_refinement(l);
11827 else
11828 cell->set_refine_flag();
11829
11830 for (unsigned int k = 0; k < cell->n_lines();
11831 ++k)
11833 cell->refine_flag_set(), l) ==
11835 // flag a line, that will be refined
11836 raw_line_iterator(&triangulation,
11837 0,
11838 line_indices[k])
11839 ->set_user_flag();
11840
11841 // note that we have changed the grid
11842 offending_line_found = true;
11843
11844 // it may save us several loop
11845 // iterations if we flag all lines of
11846 // this cell now (and not at the outset
11847 // of the next iteration) for refinement
11848 for (unsigned int k = 0; k < cell->n_lines();
11849 ++k)
11850 {
11851 const auto line =
11852 raw_line_iterator(&triangulation,
11853 0,
11854 line_indices[k]);
11855 if (!line->has_children() &&
11857 line_refinement_case(
11858 cell->refine_flag_set(), k) !=
11860 line->set_user_flag();
11861 }
11862
11863 break;
11864 }
11865 }
11866
11867 if (offending_line_found)
11868 {
11869 mesh_changed = true;
11870 break;
11871 }
11872 }
11873 }
11874 }
11875
11876
11877 // there is another thing here: if any of the lines will
11878 // be refined, then we may not coarsen the present cell
11879 // similarly, if any of the lines *is* already refined, we
11880 // may not coarsen the current cell. however, there's a
11881 // catch: if the line is refined, but the cell behind it
11882 // is going to be coarsened, then the situation
11883 // changes. if we forget this second condition, the
11884 // refine_and_coarsen_3d test will start to fail. note
11885 // that to know which cells are going to be coarsened, the
11886 // call for fix_coarsen_flags above is necessary
11888 triangulation.last();
11889 cell != triangulation.end();
11890 --cell)
11891 if (cell->user_flag_set())
11892 {
11893 const std::array<unsigned int, 12> line_indices =
11894 TriaAccessorImplementation::Implementation::
11895 get_line_indices_of_cell(*cell);
11896 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11897 {
11898 raw_line_iterator line(&triangulation,
11899 0,
11900 line_indices[l]);
11901 if (line->has_children() &&
11902 (line->child(0)->user_flag_set() ||
11903 line->child(1)->user_flag_set()))
11904 {
11905 for (unsigned int c = 0; c < cell->n_children(); ++c)
11906 cell->child(c)->clear_coarsen_flag();
11907 cell->clear_user_flag();
11908 for (unsigned int k = 0; k < cell->n_lines(); ++k)
11910 cell->refinement_case(), k) ==
11912 // flag a line, that is refined and will
11913 // stay so
11914 raw_line_iterator(&triangulation,
11915 0,
11916 line_indices[k])
11917 ->set_user_flag();
11918 mesh_changed = true;
11919 break;
11920 }
11921 }
11922 }
11923 }
11924 while (mesh_changed == true);
11925 }
11926
11927
11928
11935 template <int dim, int spacedim>
11936 static bool
11939 {
11940 // in 1d, coarsening is always allowed since we don't enforce
11941 // the 2:1 constraint there
11942 if (dim == 1)
11943 return true;
11944
11945 const RefinementCase<dim> ref_case = cell->refinement_case();
11946 for (const unsigned int n : GeometryInfo<dim>::face_indices())
11947 {
11948 // if the cell is not refined along that face, coarsening
11949 // will not change anything, so do nothing. the same
11950 // applies, if the face is at the boundary
11951 const RefinementCase<dim - 1> face_ref_case =
11952 GeometryInfo<dim>::face_refinement_case(cell->refinement_case(),
11953 n);
11954
11955 const unsigned int n_subfaces =
11956 GeometryInfo<dim - 1>::n_children(face_ref_case);
11957
11958 if (n_subfaces == 0 || cell->at_boundary(n))
11959 continue;
11960 for (unsigned int c = 0; c < n_subfaces; ++c)
11961 {
11963 child = cell->child(
11965
11967 child_neighbor = child->neighbor(n);
11968 if (!child->neighbor_is_coarser(n))
11969 {
11970 // in 2d, if the child's neighbor is coarser, then it has
11971 // no children. however, in 3d it might be
11972 // otherwise. consider for example, that our face might be
11973 // refined with cut_x, but the neighbor is refined with
11974 // cut_xy at that face. then the neighbor pointers of the
11975 // children of our cell will point to the common neighbor
11976 // cell, not to its children. what we really want to know
11977 // in the following is, whether the neighbor cell is
11978 // refined twice with reference to our cell. that only
11979 // has to be asked, if the child's neighbor is not a
11980 // coarser one. we check whether some of the children on
11981 // the neighbor are not flagged for coarsening, in that
11982 // case we may not coarsen. it is enough to check the
11983 // first child because we have already fixed the coarsen
11984 // flags on finer levels
11985 if (child_neighbor->has_children() &&
11986 !(child_neighbor->child(0)->is_active() &&
11987 child_neighbor->child(0)->coarsen_flag_set()))
11988 return false;
11989
11990 // the same applies, if the neighbors children are not
11991 // refined but will be after refinement
11992 if (child_neighbor->refine_flag_set())
11993 return false;
11994 }
11995 }
11996 }
11997 return true;
11998 }
11999 };
12000
12001
12006 {
12007 template <int spacedim>
12008 static void
12011
12012 template <int dim, int spacedim>
12014 {
12015 std::vector<std::pair<unsigned int, unsigned int>> adjacent_cells(
12016 2 * triangulation.n_raw_faces(),
12017 {numbers::invalid_unsigned_int, numbers::invalid_unsigned_int});
12018
12019 const auto set_entry = [&](const auto &face_index, const auto &cell) {
12020 const std::pair<unsigned int, unsigned int> cell_pair = {
12021 cell->level(), cell->index()};
12022 unsigned int index;
12023
12024 if (adjacent_cells[2 * face_index].first ==
12026 adjacent_cells[2 * face_index].second ==
12028 {
12029 index = 2 * face_index + 0;
12030 }
12031 else
12032 {
12033 Assert(((adjacent_cells[2 * face_index + 1].first ==
12035 (adjacent_cells[2 * face_index + 1].second ==
12038 index = 2 * face_index + 1;
12039 }
12040
12041 adjacent_cells[index] = cell_pair;
12042 };
12043
12044 const auto get_entry =
12045 [&](const auto &face_index,
12046 const auto &cell) -> TriaIterator<CellAccessor<dim, spacedim>> {
12047 auto test = adjacent_cells[2 * face_index];
12048
12049 if (test == std::pair<unsigned int, unsigned int>(cell->level(),
12050 cell->index()))
12051 test = adjacent_cells[2 * face_index + 1];
12052
12053 if ((test.first != numbers::invalid_unsigned_int) &&
12054 (test.second != numbers::invalid_unsigned_int))
12056 test.first,
12057 test.second);
12058 else
12060 };
12061
12062 for (const auto &cell : triangulation.cell_iterators())
12063 for (const auto &face : cell->face_iterators())
12064 {
12065 set_entry(face->index(), cell);
12066
12067 if (cell->is_active() && face->has_children())
12068 for (unsigned int c = 0; c < face->n_children(); ++c)
12069 set_entry(face->child(c)->index(), cell);
12070 }
12071
12072 for (const auto &cell : triangulation.cell_iterators())
12073 for (auto f : cell->face_indices())
12074 cell->set_neighbor(f, get_entry(cell->face(f)->index(), cell));
12075 }
12076
12077 template <int dim, int spacedim>
12078 static void
12082 std::vector<unsigned int> &line_cell_count,
12083 std::vector<unsigned int> &quad_cell_count)
12084 {
12086 (void)triangulation;
12087 (void)cell;
12088 (void)line_cell_count;
12089 (void)quad_cell_count;
12090 }
12091
12092 template <int dim, int spacedim>
12095 const bool check_for_distorted_cells)
12096 {
12097 return Implementation::execute_refinement_isotropic(
12098 triangulation, check_for_distorted_cells);
12099 }
12100
12101 template <int dim, int spacedim>
12102 static void
12105 {
12106 // nothing to do since anisotropy is not supported
12107 (void)triangulation;
12108 }
12109
12110 template <int dim, int spacedim>
12111 static void
12114 {
12115 Implementation::prepare_refinement_dim_dependent(triangulation);
12116 }
12117
12118 template <int dim, int spacedim>
12119 static bool
12122 {
12124
12125 return false;
12126 }
12127 };
12128
12129
12130 template <int dim, int spacedim>
12133 {
12134 static const FlatManifold<dim, spacedim> flat_manifold;
12135 return flat_manifold;
12136 }
12137 } // namespace TriangulationImplementation
12138} // namespace internal
12139
12140#ifndef DOXYGEN
12141
12142template <int dim, int spacedim>
12145
12146
12147
12148template <int dim, int spacedim>
12151 const MeshSmoothing smooth_grid,
12152 const bool check_for_distorted_cells)
12153 : cell_attached_data({0, 0, {}, {}})
12154 , smooth_grid(smooth_grid)
12155 , anisotropic_refinement(false)
12156 , check_for_distorted_cells(check_for_distorted_cells)
12157{
12158 if (dim == 1)
12159 {
12160 vertex_to_boundary_id_map_1d =
12161 std::make_unique<std::map<unsigned int, types::boundary_id>>();
12162 vertex_to_manifold_id_map_1d =
12163 std::make_unique<std::map<unsigned int, types::manifold_id>>();
12164 }
12165
12166 // connect the any_change signal to the other top level signals
12167 signals.create.connect(signals.any_change);
12168 signals.post_refinement.connect(signals.any_change);
12169 signals.clear.connect(signals.any_change);
12170 signals.mesh_movement.connect(signals.any_change);
12171}
12172
12173
12174
12175template <int dim, int spacedim>
12178 Triangulation<dim, spacedim> &&tria) noexcept
12179 : Subscriptor(std::move(tria))
12180 , smooth_grid(tria.smooth_grid)
12181 , reference_cells(std::move(tria.reference_cells))
12182 , periodic_face_pairs_level_0(std::move(tria.periodic_face_pairs_level_0))
12183 , periodic_face_map(std::move(tria.periodic_face_map))
12184 , levels(std::move(tria.levels))
12185 , faces(std::move(tria.faces))
12186 , vertices(std::move(tria.vertices))
12187 , vertices_used(std::move(tria.vertices_used))
12188 , manifolds(std::move(tria.manifolds))
12189 , anisotropic_refinement(tria.anisotropic_refinement)
12190 , check_for_distorted_cells(tria.check_for_distorted_cells)
12191 , number_cache(std::move(tria.number_cache))
12192 , vertex_to_boundary_id_map_1d(std::move(tria.vertex_to_boundary_id_map_1d))
12193 , vertex_to_manifold_id_map_1d(std::move(tria.vertex_to_manifold_id_map_1d))
12194{
12196
12197 if (tria.policy)
12198 this->policy = tria.policy->clone();
12199}
12200
12201
12202template <int dim, int spacedim>
12205 Triangulation<dim, spacedim> &&tria) noexcept
12206{
12207 Subscriptor::operator=(std::move(tria));
12208
12209 smooth_grid = tria.smooth_grid;
12210 reference_cells = std::move(tria.reference_cells);
12211 periodic_face_pairs_level_0 = std::move(tria.periodic_face_pairs_level_0);
12212 periodic_face_map = std::move(tria.periodic_face_map);
12213 levels = std::move(tria.levels);
12214 faces = std::move(tria.faces);
12215 vertices = std::move(tria.vertices);
12216 vertices_used = std::move(tria.vertices_used);
12217 manifolds = std::move(tria.manifolds);
12218 anisotropic_refinement = tria.anisotropic_refinement;
12219 number_cache = tria.number_cache;
12220 vertex_to_boundary_id_map_1d = std::move(tria.vertex_to_boundary_id_map_1d);
12221 vertex_to_manifold_id_map_1d = std::move(tria.vertex_to_manifold_id_map_1d);
12222
12224
12225 if (tria.policy)
12226 this->policy = tria.policy->clone();
12227
12228 return *this;
12229}
12230
12231
12232
12233template <int dim, int spacedim>
12236{
12237 // notify listeners that the triangulation is going down...
12238 try
12239 {
12240 signals.clear();
12241 }
12242 catch (...)
12243 {}
12244
12245 levels.clear();
12246
12247 // the vertex_to_boundary_id_map_1d field should be unused except in
12248 // 1d. double check this here, as destruction is a good place to
12249 // ensure that what we've done over the course of the lifetime of
12250 // this object makes sense
12251 AssertNothrow((dim == 1) || (vertex_to_boundary_id_map_1d == nullptr),
12253
12254 // the vertex_to_manifold_id_map_1d field should be also unused
12255 // except in 1d. check this as well
12256 AssertNothrow((dim == 1) || (vertex_to_manifold_id_map_1d == nullptr),
12258}
12259
12260
12261
12262template <int dim, int spacedim>
12265{
12266 // notify listeners that the triangulation is going down...
12267 signals.clear();
12268
12269 // ...and then actually clear all content of it
12270 clear_despite_subscriptions();
12271 periodic_face_pairs_level_0.clear();
12272 periodic_face_map.clear();
12273 reference_cells.clear();
12274
12275 cell_attached_data = {0, 0, {}, {}};
12276 data_serializer.clear();
12277}
12278
12279template <int dim, int spacedim>
12282{
12283 return MPI_COMM_SELF;
12284}
12285
12286
12287
12288template <int dim, int spacedim>
12290std::weak_ptr<const Utilities::MPI::Partitioner> Triangulation<dim, spacedim>::
12292{
12293 return number_cache.active_cell_index_partitioner;
12294}
12295
12296
12297
12298template <int dim, int spacedim>
12300std::weak_ptr<const Utilities::MPI::Partitioner> Triangulation<dim, spacedim>::
12301 global_level_cell_index_partitioner(const unsigned int level) const
12302{
12303 AssertIndexRange(level, this->n_levels());
12304
12305 return number_cache.level_cell_index_partitioners[level];
12306}
12307
12308
12309
12310template <int dim, int spacedim>
12313 const MeshSmoothing mesh_smoothing)
12314{
12315 smooth_grid = mesh_smoothing;
12316}
12317
12318
12319
12320template <int dim, int spacedim>
12324{
12325 return smooth_grid;
12326}
12327
12328
12329
12330template <int dim, int spacedim>
12333 const types::manifold_id m_number,
12334 const Manifold<dim, spacedim> &manifold_object)
12335{
12337
12338 manifolds[m_number] = manifold_object.clone();
12339}
12340
12341
12342
12343template <int dim, int spacedim>
12346 const types::manifold_id m_number)
12347{
12349
12350 // delete the entry located at number.
12351 manifolds[m_number] =
12353 spacedim>()
12354 .clone();
12355}
12356
12357
12358template <int dim, int spacedim>
12361{
12362 for (auto &m : manifolds)
12363 m.second = internal::TriangulationImplementation::
12364 get_default_flat_manifold<dim, spacedim>()
12365 .clone();
12366}
12367
12368
12369template <int dim, int spacedim>
12372 const types::manifold_id m_number)
12373{
12374 Assert(
12375 n_cells() > 0,
12376 ExcMessage(
12377 "Error: set_all_manifold_ids() can not be called on an empty Triangulation."));
12378
12379 for (const auto &cell : this->active_cell_iterators())
12380 cell->set_all_manifold_ids(m_number);
12381}
12382
12383
12384template <int dim, int spacedim>
12387 const types::manifold_id m_number)
12388{
12389 Assert(
12390 n_cells() > 0,
12391 ExcMessage(
12392 "Error: set_all_manifold_ids_on_boundary() can not be called on an empty Triangulation."));
12393
12394 for (const auto &cell : this->active_cell_iterators())
12395 for (auto f : GeometryInfo<dim>::face_indices())
12396 if (cell->face(f)->at_boundary())
12397 cell->face(f)->set_all_manifold_ids(m_number);
12398}
12399
12400
12401template <int dim, int spacedim>
12404 const types::boundary_id b_id,
12405 const types::manifold_id m_number)
12406{
12407 Assert(
12408 n_cells() > 0,
12409 ExcMessage(
12410 "Error: set_all_manifold_ids_on_boundary() can not be called on an empty Triangulation."));
12411
12412 bool boundary_found = false;
12413
12414 for (const auto &cell : this->active_cell_iterators())
12415 {
12416 // loop on faces
12417 for (auto f : GeometryInfo<dim>::face_indices())
12418 if (cell->face(f)->at_boundary() &&
12419 cell->face(f)->boundary_id() == b_id)
12420 {
12421 boundary_found = true;
12422 cell->face(f)->set_manifold_id(m_number);
12423 }
12424
12425 // loop on edges if dim >= 3
12426 if (dim >= 3)
12427 for (unsigned int e = 0; e < GeometryInfo<dim>::lines_per_cell; ++e)
12428 if (cell->line(e)->at_boundary() &&
12429 cell->line(e)->boundary_id() == b_id)
12430 {
12431 boundary_found = true;
12432 cell->line(e)->set_manifold_id(m_number);
12433 }
12434 }
12435
12436 (void)boundary_found;
12437 Assert(boundary_found, ExcBoundaryIdNotFound(b_id));
12438}
12439
12440
12441
12442template <int dim, int spacedim>
12445 const types::manifold_id m_number) const
12446{
12447 // check if flat manifold has been queried
12448 if (m_number == numbers::flat_manifold_id)
12449 return internal::TriangulationImplementation::
12450 get_default_flat_manifold<dim, spacedim>();
12451
12452 // look, if there is a manifold stored at
12453 // manifold_id number.
12454 const auto it = manifolds.find(m_number);
12455
12456 if (it != manifolds.end())
12457 {
12458 // if we have found an entry, return it
12459 return *(it->second);
12460 }
12461
12462 Assert(
12463 false,
12464 ExcMessage(
12465 "No manifold of the manifold id " + std::to_string(m_number) +
12466 " has been attached to the triangulation. "
12467 "Please attach the right manifold with Triangulation::set_manifold()."));
12468
12469 return internal::TriangulationImplementation::
12470 get_default_flat_manifold<dim, spacedim>(); // never reached
12471}
12472
12473
12474
12475template <int dim, int spacedim>
12477std::vector<types::boundary_id> Triangulation<dim, spacedim>::get_boundary_ids()
12478 const
12479{
12480 // in 1d, we store a map of all used boundary indicators. use it for
12481 // our purposes
12482 if (dim == 1)
12483 {
12484 std::vector<types::boundary_id> boundary_ids;
12485 for (std::map<unsigned int, types::boundary_id>::const_iterator p =
12486 vertex_to_boundary_id_map_1d->begin();
12487 p != vertex_to_boundary_id_map_1d->end();
12488 ++p)
12489 boundary_ids.push_back(p->second);
12490
12491 return boundary_ids;
12492 }
12493 else
12494 {
12495 std::set<types::boundary_id> b_ids;
12496 for (auto cell : active_cell_iterators())
12497 if (cell->is_locally_owned())
12498 for (const unsigned int face : cell->face_indices())
12499 if (cell->at_boundary(face))
12500 b_ids.insert(cell->face(face)->boundary_id());
12501 std::vector<types::boundary_id> boundary_ids(b_ids.begin(), b_ids.end());
12502 return boundary_ids;
12503 }
12504}
12505
12506
12507
12508template <int dim, int spacedim>
12510std::vector<types::manifold_id> Triangulation<dim, spacedim>::get_manifold_ids()
12511 const
12512{
12513 std::set<types::manifold_id> m_ids;
12514 for (const auto &cell : active_cell_iterators())
12515 if (cell->is_locally_owned())
12516 {
12517 m_ids.insert(cell->manifold_id());
12518 for (const auto &face : cell->face_iterators())
12519 m_ids.insert(face->manifold_id());
12520 if (dim == 3)
12521 {
12522 const auto line_indices = internal::TriaAccessorImplementation::
12523 Implementation::get_line_indices_of_cell(*cell);
12524 for (unsigned int l = 0; l < cell->n_lines(); ++l)
12525 {
12526 raw_line_iterator line(this, 0, line_indices[l]);
12527 m_ids.insert(line->manifold_id());
12528 }
12529 }
12530 }
12531 return {m_ids.begin(), m_ids.end()};
12532}
12533
12534#endif
12535/*-----------------------------------------------------------------*/
12536
12537#ifndef DOXYGEN
12538
12539template <int dim, int spacedim>
12542 const Triangulation<dim, spacedim> &other_tria)
12543{
12544 Assert((vertices.empty()) && (levels.empty()) && (faces == nullptr),
12545 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
12546 Assert((other_tria.levels.size() != 0) && (other_tria.vertices.size() != 0) &&
12547 (dim == 1 || other_tria.faces != nullptr),
12548 ExcMessage(
12549 "When calling Triangulation::copy_triangulation(), "
12550 "the target triangulation must be empty but the source "
12551 "triangulation (the argument to this function) must contain "
12552 "something. Here, it seems like the source does not "
12553 "contain anything at all."));
12554
12555
12556 // copy normal elements
12557 vertices = other_tria.vertices;
12558 vertices_used = other_tria.vertices_used;
12559 anisotropic_refinement = other_tria.anisotropic_refinement;
12560 smooth_grid = other_tria.smooth_grid;
12561 reference_cells = other_tria.reference_cells;
12562
12563 if (dim > 1)
12564 faces = std::make_unique<internal::TriangulationImplementation::TriaFaces>(
12565 *other_tria.faces);
12566
12567 for (const auto &p : other_tria.manifolds)
12568 set_manifold(p.first, *p.second);
12569
12570
12571 levels.reserve(other_tria.levels.size());
12572 for (unsigned int level = 0; level < other_tria.levels.size(); ++level)
12573 levels.push_back(
12574 std::make_unique<internal::TriangulationImplementation::TriaLevel>(
12575 *other_tria.levels[level]));
12576
12577 number_cache = other_tria.number_cache;
12578
12579 if (dim == 1)
12580 {
12581 vertex_to_boundary_id_map_1d =
12582 std::make_unique<std::map<unsigned int, types::boundary_id>>(
12583 *other_tria.vertex_to_boundary_id_map_1d);
12584
12585 vertex_to_manifold_id_map_1d =
12586 std::make_unique<std::map<unsigned int, types::manifold_id>>(
12587 *other_tria.vertex_to_manifold_id_map_1d);
12588 }
12589
12590 if (other_tria.policy)
12591 this->policy = other_tria.policy->clone();
12592
12593 // periodic faces
12594 this->periodic_face_pairs_level_0.reserve(
12595 other_tria.periodic_face_pairs_level_0.size());
12596
12597 for (const auto &other_entry : other_tria.periodic_face_pairs_level_0)
12598 {
12599 auto entry = other_entry;
12600 entry.cell[0] =
12601 cell_iterator(this, entry.cell[0]->level(), entry.cell[0]->index());
12602 entry.cell[1] =
12603 cell_iterator(this, entry.cell[1]->level(), entry.cell[1]->index());
12604 periodic_face_pairs_level_0.emplace_back(entry);
12605 }
12606
12607 for (auto [first_cell_, second_cell_and_orientation] :
12608 other_tria.periodic_face_map)
12609 {
12610 auto first_cell = first_cell_; // make copy since key is const
12611 first_cell.first = cell_iterator(this,
12612 first_cell.first->level(),
12613 first_cell.first->index());
12614 second_cell_and_orientation.first.first =
12615 cell_iterator(this,
12616 second_cell_and_orientation.first.first->level(),
12617 second_cell_and_orientation.first.first->index());
12618
12619 this->periodic_face_map[first_cell] = second_cell_and_orientation;
12620 }
12621
12622 // inform those who are listening on other_tria of the copy operation
12623 other_tria.signals.copy(*this);
12624 // also inform all listeners of the current triangulation that the
12625 // triangulation has been created
12626 signals.create();
12627
12628 // note that we need not copy the
12629 // subscriptor!
12630}
12631
12632
12633
12634template <int dim, int spacedim>
12637{
12638 this->update_reference_cells();
12639
12640 if (this->all_reference_cells_are_hyper_cube())
12641 {
12642 this->policy =
12644 dim,
12645 spacedim,
12647 }
12648 else
12649 {
12650 this->policy =
12652 dim,
12653 spacedim,
12655 }
12656}
12657
12658
12659
12660template <int dim, int spacedim>
12663 const std::vector<Point<spacedim>> &v,
12664 const std::vector<CellData<dim>> &cells,
12665 const SubCellData &subcelldata)
12666{
12667 Assert((vertices.empty()) && (levels.empty()) && (faces == nullptr),
12668 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
12669 // check that no forbidden arrays
12670 // are used
12671 Assert(subcelldata.check_consistency(dim), ExcInternalError());
12672
12673 // try to create a triangulation; if this fails, we still want to
12674 // throw an exception but if we just do so we'll get into trouble
12675 // because sometimes other objects are already attached to it:
12676 try
12677 {
12679 create_triangulation(v, cells, subcelldata, *this);
12680 }
12681 catch (...)
12682 {
12683 clear_despite_subscriptions();
12684 throw;
12685 }
12686
12687 reset_policy();
12688
12689 // update our counts of the various elements of a triangulation, and set
12690 // active_cell_indices of all cells
12691 reset_cell_vertex_indices_cache();
12693 *this, levels.size(), number_cache);
12694 reset_active_cell_indices();
12695 reset_global_cell_indices();
12696
12697 // now verify that there are indeed no distorted cells. as per the
12698 // documentation of this class, we first collect all distorted cells
12699 // and then throw an exception if there are any
12700 if (check_for_distorted_cells)
12701 {
12702 DistortedCellList distorted_cells = collect_distorted_coarse_cells(*this);
12703 // throw the array (and fill the various location fields) if
12704 // there are distorted cells. otherwise, just fall off the end
12705 // of the function
12706 AssertThrow(distorted_cells.distorted_cells.empty(), distorted_cells);
12707 }
12708
12709
12710 /*
12711 When the triangulation is a manifold (dim < spacedim) and made of
12712 quadrilaterals, the normal field provided from the map class depends on
12713 the order of the vertices. It may happen that this normal field is
12714 discontinuous. The following code takes care that this is not the case by
12715 setting the cell direction flag on those cell that produce the wrong
12716 orientation.
12717
12718 To determine if 2 neighbors have the same or opposite orientation we use
12719 a truth table. Its entries are indexed by the local indices of the
12720 common face. For example if two elements share a face, and this face is
12721 face 0 for element 0 and face 1 for element 1, then table(0,1) will tell
12722 whether the orientation are the same (true) or opposite (false).
12723
12724 Even though there may be a combinatorial/graph theory argument to get this
12725 table in any dimension, I tested by hand all the different possible cases
12726 in 1D and 2D to generate the table.
12727
12728 Assuming that a surface respects the standard orientation for 2d meshes,
12729 the truth tables are symmetric and their true values are the following
12730
12731 - 1D curves: (0,1)
12732 - 2D surface: (0,1),(0,2),(1,3),(2,3)
12733
12734 We store this data using an n_faces x n_faces full matrix, which is
12735 actually much bigger than the minimal data required, but it makes the code
12736 more readable.
12737
12738 */
12739 if ((dim == spacedim - 1) && all_reference_cells_are_hyper_cube())
12740 {
12743 switch (dim)
12744 {
12745 case 1:
12746 {
12747 const bool values[][2] = {{false, true}, {true, false}};
12748 for (const unsigned int i : GeometryInfo<dim>::face_indices())
12749 for (const unsigned int j : GeometryInfo<dim>::face_indices())
12750 correct(i, j) = values[i][j];
12751 break;
12752 }
12753 case 2:
12754 {
12755 const bool values[][4] = {{false, true, true, false},
12756 {true, false, false, true},
12757 {true, false, false, true},
12758 {false, true, true, false}};
12759 for (const unsigned int i : GeometryInfo<dim>::face_indices())
12760 for (const unsigned int j : GeometryInfo<dim>::face_indices())
12761 correct(i, j) = (values[i][j]);
12762 break;
12763 }
12764 default:
12766 }
12767
12768
12769 std::list<active_cell_iterator> this_round, next_round;
12770 active_cell_iterator neighbor;
12771
12772 // Start with the first cell and (arbitrarily) decide that its
12773 // direction flag should be 'true':
12774 this_round.push_back(begin_active());
12775 begin_active()->set_direction_flag(true);
12776 begin_active()->set_user_flag();
12777
12778 while (this_round.size() > 0)
12779 {
12780 for (const auto &cell : this_round)
12781 {
12782 for (const unsigned int i : cell->face_indices())
12783 {
12784 if (cell->face(i)->at_boundary() == false)
12785 {
12786 // Consider the i'th neighbor of a cell for
12787 // which we have already set the direction:
12788 neighbor = cell->neighbor(i);
12789
12790 const unsigned int nb_of_nb =
12791 cell->neighbor_of_neighbor(i);
12792
12793 // If we already saw this neighboring cell,
12794 // check that everything is fine:
12795 if (neighbor->user_flag_set())
12796 {
12797 Assert(
12798 !(correct(i, nb_of_nb) ^
12799 (neighbor->direction_flag() ==
12800 cell->direction_flag())),
12801 ExcMessage(
12802 "The triangulation you are trying to create is not orientable."));
12803 }
12804 else
12805 {
12806 // We had not seen this cell yet. Set its
12807 // orientation flag (if necessary), mark it
12808 // as treated via the user flag, and push it
12809 // onto the list of cells to start work from
12810 // the next time around:
12811 if (correct(i, nb_of_nb) ^
12812 (neighbor->direction_flag() ==
12813 cell->direction_flag()))
12814 neighbor->set_direction_flag(
12815 !neighbor->direction_flag());
12816 neighbor->set_user_flag();
12817 next_round.push_back(neighbor);
12818 }
12819 }
12820 }
12821 }
12822
12823 // Before we quit let's check that if the triangulation is
12824 // disconnected that we still get all cells by starting
12825 // again from the first cell we haven't treated yet -- that
12826 // is, the first cell of the next disconnected component we
12827 // had not yet touched.
12828 if (next_round.empty())
12829 for (const auto &cell : this->active_cell_iterators())
12830 if (cell->user_flag_set() == false)
12831 {
12832 next_round.push_back(cell);
12833 cell->set_direction_flag(true);
12834 cell->set_user_flag();
12835 break;
12836 }
12837
12838 // Go on to the next round:
12839 next_round.swap(this_round);
12840 next_round.clear();
12841 }
12842 clear_user_flags();
12843 }
12844
12845 // inform all listeners that the triangulation has been created
12846 signals.create();
12847}
12848
12849
12850
12851template <int dim, int spacedim>
12855{
12856 // 1) create coarse grid
12858 construction_data.coarse_cells,
12859 SubCellData());
12860
12861 // create a copy of cell_infos such that we can sort them
12862 auto cell_infos = construction_data.cell_infos;
12863
12864 // sort cell_infos on each level separately
12865 for (auto &cell_info : cell_infos)
12866 std::sort(
12867 cell_info.begin(),
12868 cell_info.end(),
12871 const CellId a_id(a.id);
12872 const CellId b_id(b.id);
12873
12874 const auto a_coarse_cell_index =
12875 this->coarse_cell_id_to_coarse_cell_index(a_id.get_coarse_cell_id());
12876 const auto b_coarse_cell_index =
12877 this->coarse_cell_id_to_coarse_cell_index(b_id.get_coarse_cell_id());
12878
12879 // according to their coarse-cell index and if that is
12880 // same according to their cell id (the result is that
12881 // cells on each level are sorted according to their
12882 // index on that level - what we need in the following
12883 // operations)
12884 if (a_coarse_cell_index != b_coarse_cell_index)
12885 return a_coarse_cell_index < b_coarse_cell_index;
12886 else
12887 return a_id < b_id;
12888 });
12889
12890 // 2) create all levels via a sequence of refinements. note that
12891 // we must make sure that we actually have cells on this level,
12892 // which is not clear in a parallel context for some processes
12893 for (unsigned int level = 0;
12894 level < cell_infos.size() && !cell_infos[level].empty();
12895 ++level)
12896 {
12897 // a) set manifold ids here (because new vertices have to be
12898 // positioned correctly during each refinement step)
12899 {
12900 auto cell = this->begin(level);
12901 auto cell_info = cell_infos[level].begin();
12902 for (; cell_info != cell_infos[level].end(); ++cell_info)
12903 {
12904 while (cell_info->id != cell->id().template to_binary<dim>())
12905 ++cell;
12906 if (dim == 2)
12907 for (const auto face : cell->face_indices())
12908 cell->face(face)->set_manifold_id(
12909 cell_info->manifold_line_ids[face]);
12910 else if (dim == 3)
12911 {
12912 for (const auto face : cell->face_indices())
12913 cell->face(face)->set_manifold_id(
12914 cell_info->manifold_quad_ids[face]);
12915
12916 const auto line_indices = internal::TriaAccessorImplementation::
12917 Implementation::get_line_indices_of_cell(*cell);
12918 for (unsigned int l = 0; l < cell->n_lines(); ++l)
12919 {
12920 raw_line_iterator line(this, 0, line_indices[l]);
12921 line->set_manifold_id(cell_info->manifold_line_ids[l]);
12922 }
12923 }
12924
12925 cell->set_manifold_id(cell_info->manifold_id);
12926 }
12927 }
12928
12929 // b) perform refinement on all levels but on the finest
12930 if (level + 1 != cell_infos.size())
12931 {
12932 // find cells that should have children and mark them for
12933 // refinement
12934 auto coarse_cell = this->begin(level);
12935 auto fine_cell_info = cell_infos[level + 1].begin();
12936
12937 // loop over all cells on the next level
12938 for (; fine_cell_info != cell_infos[level + 1].end();
12939 ++fine_cell_info)
12940 {
12941 // find the parent of that cell
12942 while (
12943 !coarse_cell->id().is_parent_of(CellId(fine_cell_info->id)))
12944 ++coarse_cell;
12945
12946 // set parent for refinement
12947 coarse_cell->set_refine_flag();
12948 }
12949
12950 // execute refinement
12951 ::Triangulation<dim,
12952 spacedim>::execute_coarsening_and_refinement();
12953 }
12954 }
12955
12956 // 3) set boundary ids
12957 for (unsigned int level = 0;
12958 level < cell_infos.size() && !cell_infos[level].empty();
12959 ++level)
12960 {
12961 auto cell = this->begin(level);
12962 auto cell_info = cell_infos[level].begin();
12963 for (; cell_info != cell_infos[level].end(); ++cell_info)
12964 {
12965 // find cell that has the correct cell
12966 while (cell_info->id != cell->id().template to_binary<dim>())
12967 ++cell;
12968
12969 // boundary ids
12970 for (auto pair : cell_info->boundary_ids)
12971 if (cell->face(pair.first)->at_boundary())
12972 cell->face(pair.first)->set_boundary_id(pair.second);
12973 }
12974 }
12975
12976 // inform all listeners that the triangulation has been created
12977 signals.create();
12978}
12979
12980
12981template <int dim, int spacedim>
12984{
12985 AssertThrow(dim + 1 == spacedim,
12986 ExcMessage(
12987 "This function can only be called if dim == spacedim-1."));
12988 for (const auto &cell : this->active_cell_iterators())
12989 cell->set_direction_flag(!cell->direction_flag());
12990}
12991
12992
12993
12994template <int dim, int spacedim>
12997{
12998 Assert(n_cells() > 0,
12999 ExcMessage("Error: An empty Triangulation can not be refined."));
13000
13001 for (const auto &cell : this->active_cell_iterators())
13002 {
13003 cell->clear_coarsen_flag();
13004 cell->set_refine_flag();
13005 }
13006}
13007
13008
13009
13010template <int dim, int spacedim>
13012void Triangulation<dim, spacedim>::refine_global(const unsigned int times)
13013{
13014 for (unsigned int i = 0; i < times; ++i)
13015 {
13016 set_all_refine_flags();
13017 execute_coarsening_and_refinement();
13018 }
13019}
13020
13021
13022
13023template <int dim, int spacedim>
13025void Triangulation<dim, spacedim>::coarsen_global(const unsigned int times)
13026{
13027 for (unsigned int i = 0; i < times; ++i)
13028 {
13029 for (const auto &cell : this->active_cell_iterators())
13030 {
13031 cell->clear_refine_flag();
13032 cell->set_coarsen_flag();
13033 }
13034 execute_coarsening_and_refinement();
13035 }
13036}
13037
13038
13039#endif
13040/*-------------------- refine/coarsen flags -------------------------*/
13041
13042#ifndef DOXYGEN
13043
13044template <int dim, int spacedim>
13046void Triangulation<dim, spacedim>::save_refine_flags(std::vector<bool> &v) const
13047{
13048 v.resize(dim * n_active_cells(), false);
13049 std::vector<bool>::iterator i = v.begin();
13050
13051 for (const auto &cell : this->active_cell_iterators())
13052 for (unsigned int j = 0; j < dim; ++j, ++i)
13053 if (cell->refine_flag_set() & (1 << j))
13054 *i = true;
13055
13056 Assert(i == v.end(), ExcInternalError());
13057}
13058
13059
13060
13061template <int dim, int spacedim>
13063void Triangulation<dim, spacedim>::save_refine_flags(std::ostream &out) const
13064{
13065 std::vector<bool> v;
13066 save_refine_flags(v);
13067 write_bool_vector(mn_tria_refine_flags_begin,
13068 v,
13070 out);
13071}
13072
13073
13074
13075template <int dim, int spacedim>
13078{
13079 std::vector<bool> v;
13080 read_bool_vector(mn_tria_refine_flags_begin, v, mn_tria_refine_flags_end, in);
13081 load_refine_flags(v);
13082}
13083
13084
13085
13086template <int dim, int spacedim>
13088void Triangulation<dim, spacedim>::load_refine_flags(const std::vector<bool> &v)
13089{
13090 AssertThrow(v.size() == dim * n_active_cells(), ExcGridReadError());
13091
13092 std::vector<bool>::const_iterator i = v.begin();
13093 for (const auto &cell : this->active_cell_iterators())
13094 {
13095 unsigned int ref_case = 0;
13096
13097 for (unsigned int j = 0; j < dim; ++j, ++i)
13098 if (*i == true)
13099 ref_case += 1 << j;
13101 ExcGridReadError());
13102 if (ref_case > 0)
13103 cell->set_refine_flag(RefinementCase<dim>(ref_case));
13104 else
13105 cell->clear_refine_flag();
13106 }
13107
13108 Assert(i == v.end(), ExcInternalError());
13109}
13110
13111
13112
13113template <int dim, int spacedim>
13116 std::vector<bool> &v) const
13117{
13118 v.resize(n_active_cells(), false);
13119 std::vector<bool>::iterator i = v.begin();
13120 for (const auto &cell : this->active_cell_iterators())
13121 {
13122 *i = cell->coarsen_flag_set();
13123 ++i;
13124 }
13125
13126 Assert(i == v.end(), ExcInternalError());
13127}
13128
13129
13130
13131template <int dim, int spacedim>
13133void Triangulation<dim, spacedim>::save_coarsen_flags(std::ostream &out) const
13134{
13135 std::vector<bool> v;
13136 save_coarsen_flags(v);
13137 write_bool_vector(mn_tria_coarsen_flags_begin,
13138 v,
13140 out);
13141}
13142
13143
13144
13145template <int dim, int spacedim>
13148{
13149 std::vector<bool> v;
13150 read_bool_vector(mn_tria_coarsen_flags_begin,
13151 v,
13153 in);
13154 load_coarsen_flags(v);
13155}
13156
13157
13158
13159template <int dim, int spacedim>
13162 const std::vector<bool> &v)
13163{
13164 Assert(v.size() == n_active_cells(), ExcGridReadError());
13165
13166 std::vector<bool>::const_iterator i = v.begin();
13167 for (const auto &cell : this->active_cell_iterators())
13168 {
13169 if (*i == true)
13170 cell->set_coarsen_flag();
13171 else
13172 cell->clear_coarsen_flag();
13173 ++i;
13174 }
13175
13176 Assert(i == v.end(), ExcInternalError());
13177}
13178
13179
13180template <int dim, int spacedim>
13183{
13184 return anisotropic_refinement;
13185}
13186
13187
13188#endif
13189
13190namespace internal
13191{
13192 namespace
13193 {
13194 std::vector<std::vector<bool>>
13195 extract_raw_coarsen_flags(
13196 const std::vector<std::unique_ptr<
13198 {
13199 std::vector<std::vector<bool>> coarsen_flags(levels.size());
13200 for (unsigned int level = 0; level < levels.size(); ++level)
13201 coarsen_flags[level] = levels[level]->coarsen_flags;
13202 return coarsen_flags;
13203 }
13204
13205 std::vector<std::vector<std::uint8_t>>
13206 extract_raw_refine_flags(
13207 const std::vector<std::unique_ptr<
13209 {
13210 std::vector<std::vector<std::uint8_t>> refine_flags(levels.size());
13211 for (unsigned int level = 0; level < levels.size(); ++level)
13212 refine_flags[level] = levels[level]->refine_flags;
13213 return refine_flags;
13214 }
13215 } // namespace
13216} // namespace internal
13217
13218
13219/*-------------------- user data/flags -------------------------*/
13220
13221
13222namespace
13223{
13224 // clear user data of cells
13225 void
13226 clear_user_data(std::vector<std::unique_ptr<
13228 {
13229 for (auto &level : levels)
13230 level->cells.clear_user_data();
13231 }
13232
13233
13234 // clear user data of faces
13235 void
13237 {
13238 if (faces->dim == 2)
13239 {
13240 faces->lines.clear_user_data();
13241 }
13242
13243
13244 if (faces->dim == 3)
13245 {
13246 faces->lines.clear_user_data();
13247 faces->quads.clear_user_data();
13248 }
13249 }
13250} // namespace
13251
13252#ifndef DOXYGEN
13253
13254template <int dim, int spacedim>
13257{
13258 // let functions in anonymous namespace do their work
13259 ::clear_user_data(levels);
13260 if (dim > 1)
13261 ::clear_user_data(faces.get());
13262}
13263
13264
13265
13266namespace
13267{
13268 void
13269 clear_user_flags_line(
13270 unsigned int dim,
13271 std::vector<
13272 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
13273 &levels,
13275 {
13276 if (dim == 1)
13277 {
13278 for (const auto &level : levels)
13279 level->cells.clear_user_flags();
13280 }
13281 else if (dim == 2 || dim == 3)
13282 {
13283 faces->lines.clear_user_flags();
13284 }
13285 else
13286 {
13288 }
13289 }
13290} // namespace
13291
13292
13293template <int dim, int spacedim>
13296{
13297 ::clear_user_flags_line(dim, levels, faces.get());
13298}
13299
13300
13301
13302namespace
13303{
13304 void
13305 clear_user_flags_quad(
13306 unsigned int dim,
13307 std::vector<
13308 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
13309 &levels,
13311 {
13312 if (dim == 1)
13313 {
13314 // nothing to do in 1d
13315 }
13316 else if (dim == 2)
13317 {
13318 for (const auto &level : levels)
13319 level->cells.clear_user_flags();
13320 }
13321 else if (dim == 3)
13322 {
13323 faces->quads.clear_user_flags();
13324 }
13325 else
13326 {
13328 }
13329 }
13330} // namespace
13331
13332
13333template <int dim, int spacedim>
13336{
13337 ::clear_user_flags_quad(dim, levels, faces.get());
13338}
13339
13340
13341
13342namespace
13343{
13344 void
13345 clear_user_flags_hex(
13346 unsigned int dim,
13347 std::vector<
13348 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
13349 &levels,
13351 {
13352 if (dim == 1)
13353 {
13354 // nothing to do in 1d
13355 }
13356 else if (dim == 2)
13357 {
13358 // nothing to do in 2d
13359 }
13360 else if (dim == 3)
13361 {
13362 for (const auto &level : levels)
13363 level->cells.clear_user_flags();
13364 }
13365 else
13366 {
13368 }
13369 }
13370} // namespace
13371
13372
13373template <int dim, int spacedim>
13376{
13377 ::clear_user_flags_hex(dim, levels, faces.get());
13378}
13379
13380
13381
13382template <int dim, int spacedim>
13385{
13386 clear_user_flags_line();
13387 clear_user_flags_quad();
13388 clear_user_flags_hex();
13389}
13390
13391
13392
13393template <int dim, int spacedim>
13395void Triangulation<dim, spacedim>::save_user_flags(std::ostream &out) const
13396{
13397 save_user_flags_line(out);
13398
13399 if (dim >= 2)
13400 save_user_flags_quad(out);
13401
13402 if (dim >= 3)
13403 save_user_flags_hex(out);
13404
13405 if (dim >= 4)
13407}
13408
13409
13410
13411template <int dim, int spacedim>
13413void Triangulation<dim, spacedim>::save_user_flags(std::vector<bool> &v) const
13414{
13415 // clear vector and append
13416 // all the stuff later on
13417 v.clear();
13418
13419 std::vector<bool> tmp;
13420
13421 save_user_flags_line(tmp);
13422 v.insert(v.end(), tmp.begin(), tmp.end());
13423
13424 if (dim >= 2)
13425 {
13426 save_user_flags_quad(tmp);
13427 v.insert(v.end(), tmp.begin(), tmp.end());
13428 }
13429
13430 if (dim >= 3)
13431 {
13432 save_user_flags_hex(tmp);
13433 v.insert(v.end(), tmp.begin(), tmp.end());
13434 }
13435
13436 if (dim >= 4)
13438}
13439
13440
13441
13442template <int dim, int spacedim>
13445{
13446 load_user_flags_line(in);
13447
13448 if (dim >= 2)
13449 load_user_flags_quad(in);
13450
13451 if (dim >= 3)
13452 load_user_flags_hex(in);
13453
13454 if (dim >= 4)
13456}
13457
13458
13459
13460template <int dim, int spacedim>
13462void Triangulation<dim, spacedim>::load_user_flags(const std::vector<bool> &v)
13463{
13464 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
13465 std::vector<bool> tmp;
13466
13467 // first extract the flags
13468 // belonging to lines
13469 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
13470 // and set the lines
13471 load_user_flags_line(tmp);
13472
13473 if (dim >= 2)
13474 {
13475 tmp.clear();
13476 tmp.insert(tmp.end(),
13477 v.begin() + n_lines(),
13478 v.begin() + n_lines() + n_quads());
13479 load_user_flags_quad(tmp);
13480 }
13481
13482 if (dim >= 3)
13483 {
13484 tmp.clear();
13485 tmp.insert(tmp.end(),
13486 v.begin() + n_lines() + n_quads(),
13487 v.begin() + n_lines() + n_quads() + n_hexs());
13488 load_user_flags_hex(tmp);
13489 }
13490
13491 if (dim >= 4)
13493}
13494
13495
13496
13497template <int dim, int spacedim>
13500 std::vector<bool> &v) const
13501{
13502 v.resize(n_lines(), false);
13503 std::vector<bool>::iterator i = v.begin();
13504 line_iterator line = begin_line(), endl = end_line();
13505 for (; line != endl; ++line, ++i)
13506 *i = line->user_flag_set();
13507
13508 Assert(i == v.end(), ExcInternalError());
13509}
13510
13511
13512
13513template <int dim, int spacedim>
13515void Triangulation<dim, spacedim>::save_user_flags_line(std::ostream &out) const
13516{
13517 std::vector<bool> v;
13518 save_user_flags_line(v);
13519 write_bool_vector(mn_tria_line_user_flags_begin,
13520 v,
13522 out);
13523}
13524
13525
13526
13527template <int dim, int spacedim>
13530{
13531 std::vector<bool> v;
13532 read_bool_vector(mn_tria_line_user_flags_begin,
13533 v,
13535 in);
13536 load_user_flags_line(v);
13537}
13538
13539
13540
13541template <int dim, int spacedim>
13544 const std::vector<bool> &v)
13545{
13546 Assert(v.size() == n_lines(), ExcGridReadError());
13547
13548 line_iterator line = begin_line(), endl = end_line();
13549 std::vector<bool>::const_iterator i = v.begin();
13550 for (; line != endl; ++line, ++i)
13551 if (*i == true)
13552 line->set_user_flag();
13553 else
13554 line->clear_user_flag();
13555
13556 Assert(i == v.end(), ExcInternalError());
13557}
13558
13559#endif
13560
13561namespace
13562{
13563 template <typename Iterator>
13564 bool
13565 get_user_flag(const Iterator &i)
13566 {
13567 return i->user_flag_set();
13568 }
13569
13570
13571
13572 template <int structdim, int dim, int spacedim>
13573 bool
13575 {
13577 return false;
13578 }
13579
13580
13581
13582 template <typename Iterator>
13583 void
13584 set_user_flag(const Iterator &i)
13585 {
13586 i->set_user_flag();
13587 }
13588
13589
13590
13591 template <int structdim, int dim, int spacedim>
13592 void
13594 {
13596 }
13597
13598
13599
13600 template <typename Iterator>
13601 void
13602 clear_user_flag(const Iterator &i)
13603 {
13604 i->clear_user_flag();
13605 }
13606
13607
13608
13609 template <int structdim, int dim, int spacedim>
13610 void
13611 clear_user_flag(
13613 {
13615 }
13616} // namespace
13617
13618#ifndef DOXYGEN
13619
13620template <int dim, int spacedim>
13623 std::vector<bool> &v) const
13624{
13625 v.resize(n_quads(), false);
13626
13627 if (dim >= 2)
13628 {
13629 std::vector<bool>::iterator i = v.begin();
13630 quad_iterator quad = begin_quad(), endq = end_quad();
13631 for (; quad != endq; ++quad, ++i)
13632 *i = get_user_flag(quad);
13633
13634 Assert(i == v.end(), ExcInternalError());
13635 }
13636}
13637
13638
13639
13640template <int dim, int spacedim>
13642void Triangulation<dim, spacedim>::save_user_flags_quad(std::ostream &out) const
13643{
13644 std::vector<bool> v;
13645 save_user_flags_quad(v);
13646 write_bool_vector(mn_tria_quad_user_flags_begin,
13647 v,
13649 out);
13650}
13651
13652
13653
13654template <int dim, int spacedim>
13657{
13658 std::vector<bool> v;
13659 read_bool_vector(mn_tria_quad_user_flags_begin,
13660 v,
13662 in);
13663 load_user_flags_quad(v);
13664}
13665
13666
13667
13668template <int dim, int spacedim>
13671 const std::vector<bool> &v)
13672{
13673 Assert(v.size() == n_quads(), ExcGridReadError());
13674
13675 if (dim >= 2)
13676 {
13677 quad_iterator quad = begin_quad(), endq = end_quad();
13678 std::vector<bool>::const_iterator i = v.begin();
13679 for (; quad != endq; ++quad, ++i)
13680 if (*i == true)
13681 set_user_flag(quad);
13682 else
13683 clear_user_flag(quad);
13684
13685 Assert(i == v.end(), ExcInternalError());
13686 }
13687}
13688
13689
13690
13691template <int dim, int spacedim>
13694 std::vector<bool> &v) const
13695{
13696 v.resize(n_hexs(), false);
13697
13698 if (dim >= 3)
13699 {
13700 std::vector<bool>::iterator i = v.begin();
13701 hex_iterator hex = begin_hex(), endh = end_hex();
13702 for (; hex != endh; ++hex, ++i)
13703 *i = get_user_flag(hex);
13704
13705 Assert(i == v.end(), ExcInternalError());
13706 }
13707}
13708
13709
13710
13711template <int dim, int spacedim>
13713void Triangulation<dim, spacedim>::save_user_flags_hex(std::ostream &out) const
13714{
13715 std::vector<bool> v;
13716 save_user_flags_hex(v);
13717 write_bool_vector(mn_tria_hex_user_flags_begin,
13718 v,
13720 out);
13721}
13722
13723
13724
13725template <int dim, int spacedim>
13728{
13729 std::vector<bool> v;
13730 read_bool_vector(mn_tria_hex_user_flags_begin,
13731 v,
13733 in);
13734 load_user_flags_hex(v);
13735}
13736
13737
13738
13739template <int dim, int spacedim>
13742 const std::vector<bool> &v)
13743{
13744 Assert(v.size() == n_hexs(), ExcGridReadError());
13745
13746 if (dim >= 3)
13747 {
13748 hex_iterator hex = begin_hex(), endh = end_hex();
13749 std::vector<bool>::const_iterator i = v.begin();
13750 for (; hex != endh; ++hex, ++i)
13751 if (*i == true)
13752 set_user_flag(hex);
13753 else
13754 clear_user_flag(hex);
13755
13756 Assert(i == v.end(), ExcInternalError());
13757 }
13758}
13759
13760
13761
13762template <int dim, int spacedim>
13765 std::vector<unsigned int> &v) const
13766{
13767 // clear vector and append all the
13768 // stuff later on
13769 v.clear();
13770
13771 std::vector<unsigned int> tmp;
13772
13773 save_user_indices_line(tmp);
13774 v.insert(v.end(), tmp.begin(), tmp.end());
13775
13776 if (dim >= 2)
13777 {
13778 save_user_indices_quad(tmp);
13779 v.insert(v.end(), tmp.begin(), tmp.end());
13780 }
13781
13782 if (dim >= 3)
13783 {
13784 save_user_indices_hex(tmp);
13785 v.insert(v.end(), tmp.begin(), tmp.end());
13786 }
13787
13788 if (dim >= 4)
13790}
13791
13792
13793
13794template <int dim, int spacedim>
13797 const std::vector<unsigned int> &v)
13798{
13799 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
13800 std::vector<unsigned int> tmp;
13801
13802 // first extract the indices
13803 // belonging to lines
13804 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
13805 // and set the lines
13806 load_user_indices_line(tmp);
13807
13808 if (dim >= 2)
13809 {
13810 tmp.clear();
13811 tmp.insert(tmp.end(),
13812 v.begin() + n_lines(),
13813 v.begin() + n_lines() + n_quads());
13814 load_user_indices_quad(tmp);
13815 }
13816
13817 if (dim >= 3)
13818 {
13819 tmp.clear();
13820 tmp.insert(tmp.end(),
13821 v.begin() + n_lines() + n_quads(),
13822 v.begin() + n_lines() + n_quads() + n_hexs());
13823 load_user_indices_hex(tmp);
13824 }
13825
13826 if (dim >= 4)
13828}
13829
13830template <int dim, int spacedim>
13832void Triangulation<dim, spacedim>::save(const std::string &filename) const
13833{
13834 // Create boost archive then call alternative version of the save function
13835 std::ofstream ofs(filename);
13836 boost::archive::text_oarchive oa(ofs, boost::archive::no_header);
13837 save(oa, 0);
13838}
13839
13840template <int dim, int spacedim>
13842void Triangulation<dim, spacedim>::load(const std::string &filename)
13843{
13844 // Create boost archive then call alternative version of the load function
13845 std::ifstream ifs(filename);
13846 boost::archive::text_iarchive ia(ifs, boost::archive::no_header);
13847 load(ia, 0);
13848}
13849
13850#endif
13851namespace
13852{
13853 template <typename Iterator>
13854 unsigned int
13855 get_user_index(const Iterator &i)
13856 {
13857 return i->user_index();
13858 }
13859
13860
13861
13862 template <int structdim, int dim, int spacedim>
13863 unsigned int
13864 get_user_index(
13866 {
13869 }
13870
13871
13872
13873 template <typename Iterator>
13874 void
13875 set_user_index(const Iterator &i, const unsigned int x)
13876 {
13877 i->set_user_index(x);
13878 }
13879
13880
13881
13882 template <int structdim, int dim, int spacedim>
13883 void
13884 set_user_index(
13886 const unsigned int)
13887 {
13889 }
13890} // namespace
13891
13892#ifndef DOXYGEN
13893
13894template <int dim, int spacedim>
13897 std::vector<unsigned int> &v) const
13898{
13899 v.resize(n_lines(), 0);
13900 std::vector<unsigned int>::iterator i = v.begin();
13901 line_iterator line = begin_line(), endl = end_line();
13902 for (; line != endl; ++line, ++i)
13903 *i = line->user_index();
13904}
13905
13906
13907
13908template <int dim, int spacedim>
13911 const std::vector<unsigned int> &v)
13912{
13913 Assert(v.size() == n_lines(), ExcGridReadError());
13914
13915 line_iterator line = begin_line(), endl = end_line();
13916 std::vector<unsigned int>::const_iterator i = v.begin();
13917 for (; line != endl; ++line, ++i)
13918 line->set_user_index(*i);
13919}
13920
13921
13922template <int dim, int spacedim>
13925 std::vector<unsigned int> &v) const
13926{
13927 v.resize(n_quads(), 0);
13928
13929 if (dim >= 2)
13930 {
13931 std::vector<unsigned int>::iterator i = v.begin();
13932 quad_iterator quad = begin_quad(), endq = end_quad();
13933 for (; quad != endq; ++quad, ++i)
13934 *i = get_user_index(quad);
13935 }
13936}
13937
13938
13939
13940template <int dim, int spacedim>
13943 const std::vector<unsigned int> &v)
13944{
13945 Assert(v.size() == n_quads(), ExcGridReadError());
13946
13947 if (dim >= 2)
13948 {
13949 quad_iterator quad = begin_quad(), endq = end_quad();
13950 std::vector<unsigned int>::const_iterator i = v.begin();
13951 for (; quad != endq; ++quad, ++i)
13952 set_user_index(quad, *i);
13953 }
13954}
13955
13956
13957template <int dim, int spacedim>
13960 std::vector<unsigned int> &v) const
13961{
13962 v.resize(n_hexs(), 0);
13963
13964 if (dim >= 3)
13965 {
13966 std::vector<unsigned int>::iterator i = v.begin();
13967 hex_iterator hex = begin_hex(), endh = end_hex();
13968 for (; hex != endh; ++hex, ++i)
13969 *i = get_user_index(hex);
13970 }
13971}
13972
13973
13974
13975template <int dim, int spacedim>
13978 const std::vector<unsigned int> &v)
13979{
13980 Assert(v.size() == n_hexs(), ExcGridReadError());
13981
13982 if (dim >= 3)
13983 {
13984 hex_iterator hex = begin_hex(), endh = end_hex();
13985 std::vector<unsigned int>::const_iterator i = v.begin();
13986 for (; hex != endh; ++hex, ++i)
13987 set_user_index(hex, *i);
13988 }
13989}
13990
13991#endif
13992
13993
13994//---------------- user pointers ----------------------------------------//
13995
13996
13997namespace
13998{
13999 template <typename Iterator>
14000 void *
14001 get_user_pointer(const Iterator &i)
14002 {
14003 return i->user_pointer();
14004 }
14005
14006
14007
14008 template <int structdim, int dim, int spacedim>
14009 void *
14010 get_user_pointer(
14012 {
14014 return nullptr;
14015 }
14016
14017
14018
14019 template <typename Iterator>
14020 void
14021 set_user_pointer(const Iterator &i, void *x)
14022 {
14023 i->set_user_pointer(x);
14024 }
14025
14026
14027
14028 template <int structdim, int dim, int spacedim>
14029 void
14030 set_user_pointer(
14032 void *)
14033 {
14035 }
14036} // namespace
14037
14038#ifndef DOXYGEN
14039
14040template <int dim, int spacedim>
14043 std::vector<void *> &v) const
14044{
14045 // clear vector and append all the
14046 // stuff later on
14047 v.clear();
14048
14049 std::vector<void *> tmp;
14050
14051 save_user_pointers_line(tmp);
14052 v.insert(v.end(), tmp.begin(), tmp.end());
14053
14054 if (dim >= 2)
14055 {
14056 save_user_pointers_quad(tmp);
14057 v.insert(v.end(), tmp.begin(), tmp.end());
14058 }
14059
14060 if (dim >= 3)
14061 {
14062 save_user_pointers_hex(tmp);
14063 v.insert(v.end(), tmp.begin(), tmp.end());
14064 }
14065
14066 if (dim >= 4)
14068}
14069
14070
14071
14072template <int dim, int spacedim>
14075 const std::vector<void *> &v)
14076{
14077 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
14078 std::vector<void *> tmp;
14079
14080 // first extract the pointers
14081 // belonging to lines
14082 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
14083 // and set the lines
14084 load_user_pointers_line(tmp);
14085
14086 if (dim >= 2)
14087 {
14088 tmp.clear();
14089 tmp.insert(tmp.end(),
14090 v.begin() + n_lines(),
14091 v.begin() + n_lines() + n_quads());
14092 load_user_pointers_quad(tmp);
14093 }
14094
14095 if (dim >= 3)
14096 {
14097 tmp.clear();
14098 tmp.insert(tmp.end(),
14099 v.begin() + n_lines() + n_quads(),
14100 v.begin() + n_lines() + n_quads() + n_hexs());
14101 load_user_pointers_hex(tmp);
14102 }
14103
14104 if (dim >= 4)
14106}
14107
14108
14109
14110template <int dim, int spacedim>
14113 std::vector<void *> &v) const
14114{
14115 v.resize(n_lines(), nullptr);
14116 std::vector<void *>::iterator i = v.begin();
14117 line_iterator line = begin_line(), endl = end_line();
14118 for (; line != endl; ++line, ++i)
14119 *i = line->user_pointer();
14120}
14121
14122
14123
14124template <int dim, int spacedim>
14127 const std::vector<void *> &v)
14128{
14129 Assert(v.size() == n_lines(), ExcGridReadError());
14130
14131 line_iterator line = begin_line(), endl = end_line();
14132 std::vector<void *>::const_iterator i = v.begin();
14133 for (; line != endl; ++line, ++i)
14134 line->set_user_pointer(*i);
14135}
14136
14137
14138
14139template <int dim, int spacedim>
14142 std::vector<void *> &v) const
14143{
14144 v.resize(n_quads(), nullptr);
14145
14146 if (dim >= 2)
14147 {
14148 std::vector<void *>::iterator i = v.begin();
14149 quad_iterator quad = begin_quad(), endq = end_quad();
14150 for (; quad != endq; ++quad, ++i)
14151 *i = get_user_pointer(quad);
14152 }
14153}
14154
14155
14156
14157template <int dim, int spacedim>
14160 const std::vector<void *> &v)
14161{
14162 Assert(v.size() == n_quads(), ExcGridReadError());
14163
14164 if (dim >= 2)
14165 {
14166 quad_iterator quad = begin_quad(), endq = end_quad();
14167 std::vector<void *>::const_iterator i = v.begin();
14168 for (; quad != endq; ++quad, ++i)
14169 set_user_pointer(quad, *i);
14170 }
14171}
14172
14173
14174template <int dim, int spacedim>
14177 std::vector<void *> &v) const
14178{
14179 v.resize(n_hexs(), nullptr);
14180
14181 if (dim >= 3)
14182 {
14183 std::vector<void *>::iterator i = v.begin();
14184 hex_iterator hex = begin_hex(), endh = end_hex();
14185 for (; hex != endh; ++hex, ++i)
14186 *i = get_user_pointer(hex);
14187 }
14188}
14189
14190
14191
14192template <int dim, int spacedim>
14195 const std::vector<void *> &v)
14196{
14197 Assert(v.size() == n_hexs(), ExcGridReadError());
14198
14199 if (dim >= 3)
14200 {
14201 hex_iterator hex = begin_hex(), endh = end_hex();
14202 std::vector<void *>::const_iterator i = v.begin();
14203 for (; hex != endh; ++hex, ++i)
14204 set_user_pointer(hex, *i);
14205 }
14206}
14207
14208#endif
14209
14210/*------------------------ Cell iterator functions ------------------------*/
14211
14212#ifndef DOXYGEN
14213
14214template <int dim, int spacedim>
14217 Triangulation<dim, spacedim>::begin_raw(const unsigned int level) const
14218{
14219 switch (dim)
14220 {
14221 case 1:
14222 return begin_raw_line(level);
14223 case 2:
14224 return begin_raw_quad(level);
14225 case 3:
14226 return begin_raw_hex(level);
14227 default:
14229 return raw_cell_iterator();
14230 }
14231}
14232
14233
14234
14235template <int dim, int spacedim>
14238 Triangulation<dim, spacedim>::begin(const unsigned int level) const
14239{
14240 switch (dim)
14241 {
14242 case 1:
14243 return begin_line(level);
14244 case 2:
14245 return begin_quad(level);
14246 case 3:
14247 return begin_hex(level);
14248 default:
14249 Assert(false, ExcImpossibleInDim(dim));
14250 return cell_iterator();
14251 }
14252}
14253
14254
14255
14256template <int dim, int spacedim>
14259 Triangulation<dim, spacedim>::begin_active(const unsigned int level) const
14260{
14261 switch (dim)
14262 {
14263 case 1:
14264 return begin_active_line(level);
14265 case 2:
14266 return begin_active_quad(level);
14267 case 3:
14268 return begin_active_hex(level);
14269 default:
14271 return active_cell_iterator();
14272 }
14273}
14274
14275
14276
14277template <int dim, int spacedim>
14281{
14282 const unsigned int level = levels.size() - 1;
14283 if (levels[level]->cells.n_objects() == 0)
14284 return end(level);
14285
14286 // find the last raw iterator on
14287 // this level
14288 raw_cell_iterator ri(const_cast<Triangulation<dim, spacedim> *>(this),
14289 level,
14290 levels[level]->cells.n_objects() - 1);
14291
14292 // then move to the last used one
14293 if (ri->used() == true)
14294 return ri;
14295 while ((--ri).state() == IteratorState::valid)
14296 if (ri->used() == true)
14297 return ri;
14298 return ri;
14299}
14300
14301
14302
14303template <int dim, int spacedim>
14307{
14308 // get the last used cell
14309 cell_iterator cell = last();
14310
14311 if (cell != end())
14312 {
14313 // then move to the last active one
14314 if (cell->is_active() == true)
14315 return cell;
14316 while ((--cell).state() == IteratorState::valid)
14317 if (cell->is_active() == true)
14318 return cell;
14319 }
14320 return cell;
14321}
14322
14323
14324
14325template <int dim, int spacedim>
14329 const CellId &cell_id) const
14330{
14331 Assert(
14332 this->contains_cell(cell_id),
14333 ExcMessage(
14334 "CellId is invalid for this triangulation.\n"
14335 "Either the provided CellId does not correspond to a cell in this "
14336 "triangulation object, or, in case you are using a parallel "
14337 "triangulation, may correspond to an artificial cell that is less "
14338 "refined on this processor. In the case of "
14339 "parallel::fullydistributed::Triangulation, the corresponding coarse "
14340 "cell might not be accessible by the current process."));
14341
14342 cell_iterator cell(
14343 this, 0, coarse_cell_id_to_coarse_cell_index(cell_id.get_coarse_cell_id()));
14344
14345 for (const auto &child_index : cell_id.get_child_indices())
14346 cell = cell->child(static_cast<unsigned int>(child_index));
14347
14348 return cell;
14349}
14350
14351
14352
14353template <int dim, int spacedim>
14355bool Triangulation<dim, spacedim>::contains_cell(const CellId &cell_id) const
14356{
14357 const auto coarse_cell_index =
14358 coarse_cell_id_to_coarse_cell_index(cell_id.get_coarse_cell_id());
14359
14360 if (coarse_cell_index == numbers::invalid_unsigned_int)
14361 return false;
14362
14363 cell_iterator cell(this, 0, coarse_cell_index);
14364
14365 for (const auto &child_index : cell_id.get_child_indices())
14366 {
14367 if (cell->has_children() == false)
14368 return false;
14369 cell = cell->child(static_cast<unsigned int>(child_index));
14370 }
14371
14372 return true;
14373}
14374
14375
14376
14377template <int dim, int spacedim>
14381{
14382 return cell_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14383 -1,
14384 -1);
14385}
14386
14387
14388
14389template <int dim, int spacedim>
14392 Triangulation<dim, spacedim>::end_raw(const unsigned int level) const
14393{
14394 // This function may be called on parallel triangulations on levels
14395 // that exist globally, but not on the local portion of the
14396 // triangulation. In that case, just return the end iterator.
14397 //
14398 // We need to use levels.size() instead of n_levels() because the
14399 // latter function uses the cache, but we need to be able to call
14400 // this function at a time when the cache is not currently up to
14401 // date.
14402 if (level >= levels.size())
14403 {
14404 Assert(level < n_global_levels(),
14405 ExcInvalidLevel(level, n_global_levels()));
14406 return end();
14407 }
14408
14409 // Query whether the given level is valid for the local portion of the
14410 // triangulation.
14411 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14412 if (level < levels.size() - 1)
14413 return begin_raw(level + 1);
14414 else
14415 return end();
14416}
14417
14418
14419template <int dim, int spacedim>
14422 Triangulation<dim, spacedim>::end(const unsigned int level) const
14423{
14424 // This function may be called on parallel triangulations on levels
14425 // that exist globally, but not on the local portion of the
14426 // triangulation. In that case, just return the end iterator.
14427 //
14428 // We need to use levels.size() instead of n_levels() because the
14429 // latter function uses the cache, but we need to be able to call
14430 // this function at a time when the cache is not currently up to
14431 // date.
14432 if (level >= levels.size())
14433 {
14434 Assert(level < n_global_levels(),
14435 ExcInvalidLevel(level, n_global_levels()));
14436 return end();
14437 }
14438
14439 // Query whether the given level is valid for the local portion of the
14440 // triangulation.
14441 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14442 if (level < levels.size() - 1)
14443 return begin(level + 1);
14444 else
14445 return end();
14446}
14447
14448
14449template <int dim, int spacedim>
14452 Triangulation<dim, spacedim>::end_active(const unsigned int level) const
14453{
14454 // This function may be called on parallel triangulations on levels
14455 // that exist globally, but not on the local portion of the
14456 // triangulation. In that case, just return the end iterator.
14457 //
14458 // We need to use levels.size() instead of n_levels() because the
14459 // latter function uses the cache, but we need to be able to call
14460 // this function at a time when the cache is not currently up to
14461 // date.
14462 if (level >= levels.size())
14463 {
14464 Assert(level < n_global_levels(),
14465 ExcInvalidLevel(level, n_global_levels()));
14466 return end();
14467 }
14468
14469 // Query whether the given level is valid for the local portion of the
14470 // triangulation.
14471 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14472 return (level >= levels.size() - 1 ? active_cell_iterator(end()) :
14473 begin_active(level + 1));
14474}
14475
14476
14477
14478template <int dim, int spacedim>
14482 const
14483{
14485 begin(), end());
14486}
14487
14488
14489template <int dim, int spacedim>
14492 active_cell_iterator> Triangulation<dim, spacedim>::
14494{
14495 return IteratorRange<
14497 end());
14498}
14499
14500
14501
14502template <int dim, int spacedim>
14505 cell_iterator> Triangulation<dim, spacedim>::
14506 cell_iterators_on_level(const unsigned int level) const
14507{
14509 begin(level), end(level));
14510}
14511
14512
14513
14514template <int dim, int spacedim>
14517 active_cell_iterator> Triangulation<dim, spacedim>::
14518 active_cell_iterators_on_level(const unsigned int level) const
14519{
14520 return IteratorRange<
14522 begin_active(level), end_active(level));
14523}
14524#endif
14525
14526/*------------------------ Face iterator functions ------------------------*/
14527
14528#ifndef DOXYGEN
14529
14530template <int dim, int spacedim>
14534{
14535 switch (dim)
14536 {
14537 case 1:
14538 Assert(false, ExcImpossibleInDim(1));
14539 return raw_face_iterator();
14540 case 2:
14541 return begin_line();
14542 case 3:
14543 return begin_quad();
14544 default:
14546 return face_iterator();
14547 }
14548}
14549
14550
14551
14552template <int dim, int spacedim>
14556{
14557 switch (dim)
14558 {
14559 case 1:
14560 Assert(false, ExcImpossibleInDim(1));
14561 return raw_face_iterator();
14562 case 2:
14563 return begin_active_line();
14564 case 3:
14565 return begin_active_quad();
14566 default:
14568 return active_face_iterator();
14569 }
14570}
14571
14572
14573
14574template <int dim, int spacedim>
14578{
14579 switch (dim)
14580 {
14581 case 1:
14582 Assert(false, ExcImpossibleInDim(1));
14583 return raw_face_iterator();
14584 case 2:
14585 return end_line();
14586 case 3:
14587 return end_quad();
14588 default:
14590 return raw_face_iterator();
14591 }
14592}
14593
14594
14595
14596template <int dim, int spacedim>
14599 active_face_iterator> Triangulation<dim, spacedim>::
14601{
14602 return IteratorRange<
14604 begin_active_face(), end_face());
14605}
14606
14607/*------------------------ Vertex iterator functions ------------------------*/
14608
14609
14610template <int dim, int spacedim>
14614{
14615 vertex_iterator i =
14616 raw_vertex_iterator(const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
14617 if (i.state() != IteratorState::valid)
14618 return i;
14619 // This loop will end because every triangulation has used vertices.
14620 while (i->used() == false)
14621 if ((++i).state() != IteratorState::valid)
14622 return i;
14623 return i;
14624}
14625
14626
14627
14628template <int dim, int spacedim>
14632{
14633 // every vertex is active
14634 return begin_vertex();
14635}
14636
14637
14638
14639template <int dim, int spacedim>
14643{
14644 return raw_vertex_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14645 -1,
14647}
14648
14649#endif
14650
14651
14652/*------------------------ Line iterator functions ------------------------*/
14653
14654#ifndef DOXYGEN
14655
14656template <int dim, int spacedim>
14659 Triangulation<dim, spacedim>::begin_raw_line(const unsigned int level) const
14660{
14661 // This function may be called on parallel triangulations on levels
14662 // that exist globally, but not on the local portion of the
14663 // triangulation. In that case, just return the end iterator.
14664 //
14665 // We need to use levels.size() instead of n_levels() because the
14666 // latter function uses the cache, but we need to be able to call
14667 // this function at a time when the cache is not currently up to
14668 // date.
14669 if (level >= levels.size())
14670 {
14671 Assert(level < n_global_levels(),
14672 ExcInvalidLevel(level, n_global_levels()));
14673 return end_line();
14674 }
14675
14676 switch (dim)
14677 {
14678 case 1:
14679 // Query whether the given level is valid for the local portion of the
14680 // triangulation.
14681 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14682
14683 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
14684 return end_line();
14685
14686 return raw_line_iterator(
14687 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
14688
14689 default:
14690 Assert(level == 0, ExcFacesHaveNoLevel());
14691 return raw_line_iterator(
14692 const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
14693 }
14694}
14695
14696
14697template <int dim, int spacedim>
14700 Triangulation<dim, spacedim>::begin_line(const unsigned int level) const
14701{
14702 // level is checked in begin_raw
14703 raw_line_iterator ri = begin_raw_line(level);
14704 if (ri.state() != IteratorState::valid)
14705 return ri;
14706 while (ri->used() == false)
14707 if ((++ri).state() != IteratorState::valid)
14708 return ri;
14709 return ri;
14710}
14711
14712
14713
14714template <int dim, int spacedim>
14718 const unsigned int level) const
14719{
14720 // level is checked in begin_raw
14721 line_iterator i = begin_line(level);
14722 if (i.state() != IteratorState::valid)
14723 return i;
14724 while (i->has_children())
14725 if ((++i).state() != IteratorState::valid)
14726 return i;
14727 return i;
14728}
14729
14730
14731
14732template <int dim, int spacedim>
14736{
14737 return raw_line_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14738 -1,
14739 -1);
14740}
14741
14742#endif
14743
14744/*------------------------ Quad iterator functions ------------------------*/
14745
14746#ifndef DOXYGEN
14747
14748template <int dim, int spacedim>
14751 Triangulation<dim, spacedim>::begin_raw_quad(const unsigned int level) const
14752{
14753 // This function may be called on parallel triangulations on levels
14754 // that exist globally, but not on the local portion of the
14755 // triangulation. In that case, just return the end iterator.
14756 //
14757 // We need to use levels.size() instead of n_levels() because the
14758 // latter function uses the cache, but we need to be able to call
14759 // this function at a time when the cache is not currently up to
14760 // date.
14761 if (level >= levels.size())
14762 {
14763 Assert(level < n_global_levels(),
14764 ExcInvalidLevel(level, n_global_levels()));
14765 return end_quad();
14766 }
14767
14768 switch (dim)
14769 {
14770 case 1:
14771 Assert(false, ExcImpossibleInDim(1));
14772 return raw_hex_iterator();
14773 case 2:
14774 {
14775 // Query whether the given level is valid for the local portion of the
14776 // triangulation.
14777 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14778
14779 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
14780 return end_quad();
14781
14782 return raw_quad_iterator(
14783 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
14784 }
14785
14786 case 3:
14787 {
14788 Assert(level == 0, ExcFacesHaveNoLevel());
14789
14790 return raw_quad_iterator(
14791 const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
14792 }
14793
14794
14795 default:
14797 return raw_hex_iterator();
14798 }
14799}
14800
14801
14802
14803template <int dim, int spacedim>
14806 Triangulation<dim, spacedim>::begin_quad(const unsigned int level) const
14807{
14808 // level is checked in begin_raw
14809 raw_quad_iterator ri = begin_raw_quad(level);
14810 if (ri.state() != IteratorState::valid)
14811 return ri;
14812 while (ri->used() == false)
14813 if ((++ri).state() != IteratorState::valid)
14814 return ri;
14815 return ri;
14816}
14817
14818
14819
14820template <int dim, int spacedim>
14824 const unsigned int level) const
14825{
14826 // level is checked in begin_raw
14827 quad_iterator i = begin_quad(level);
14828 if (i.state() != IteratorState::valid)
14829 return i;
14830 while (i->has_children())
14831 if ((++i).state() != IteratorState::valid)
14832 return i;
14833 return i;
14834}
14835
14836
14837
14838template <int dim, int spacedim>
14842{
14843 return raw_quad_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14844 -1,
14845 -1);
14846}
14847
14848#endif
14849
14850/*------------------------ Hex iterator functions ------------------------*/
14851
14852#ifndef DOXYGEN
14853
14854template <int dim, int spacedim>
14857 Triangulation<dim, spacedim>::begin_raw_hex(const unsigned int level) const
14858{
14859 // This function may be called on parallel triangulations on levels
14860 // that exist globally, but not on the local portion of the
14861 // triangulation. In that case, just return the end iterator.
14862 //
14863 // We need to use levels.size() instead of n_levels() because the
14864 // latter function uses the cache, but we need to be able to call
14865 // this function at a time when the cache is not currently up to
14866 // date.
14867 if (level >= levels.size())
14868 {
14869 Assert(level < n_global_levels(),
14870 ExcInvalidLevel(level, n_global_levels()));
14871 return end_hex();
14872 }
14873
14874 switch (dim)
14875 {
14876 case 1:
14877 case 2:
14878 Assert(false, ExcImpossibleInDim(1));
14879 return raw_hex_iterator();
14880 case 3:
14881 {
14882 // Query whether the given level is valid for the local portion of the
14883 // triangulation.
14884 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14885
14886 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
14887 return end_hex();
14888
14889 return raw_hex_iterator(
14890 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
14891 }
14892
14893 default:
14895 return raw_hex_iterator();
14896 }
14897}
14898
14899
14900
14901template <int dim, int spacedim>
14904 Triangulation<dim, spacedim>::begin_hex(const unsigned int level) const
14905{
14906 // level is checked in begin_raw
14907 raw_hex_iterator ri = begin_raw_hex(level);
14908 if (ri.state() != IteratorState::valid)
14909 return ri;
14910 while (ri->used() == false)
14911 if ((++ri).state() != IteratorState::valid)
14912 return ri;
14913 return ri;
14914}
14915
14916
14917
14918template <int dim, int spacedim>
14922{
14923 // level is checked in begin_raw
14924 hex_iterator i = begin_hex(level);
14925 if (i.state() != IteratorState::valid)
14926 return i;
14927 while (i->has_children())
14928 if ((++i).state() != IteratorState::valid)
14929 return i;
14930 return i;
14931}
14932
14933
14934
14935template <int dim, int spacedim>
14939{
14940 return raw_hex_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14941 -1,
14942 -1);
14943}
14944
14945#endif
14946
14947// -------------------------------- number of cells etc ---------------
14948
14949
14950namespace internal
14951{
14952 namespace TriangulationImplementation
14953 {
14954 inline unsigned int
14956 {
14957 return c.n_lines;
14958 }
14959
14960
14961 inline unsigned int
14964 {
14965 return c.n_active_lines;
14966 }
14967
14968
14969 inline unsigned int
14971 {
14972 return c.n_quads;
14973 }
14974
14975
14976 inline unsigned int
14979 {
14980 return c.n_active_quads;
14981 }
14982
14983
14984 inline unsigned int
14986 {
14987 return c.n_hexes;
14988 }
14989
14990
14991 inline unsigned int
14994 {
14995 return c.n_active_hexes;
14996 }
14997 } // namespace TriangulationImplementation
14998} // namespace internal
14999
15000#ifndef DOXYGEN
15001
15002template <int dim, int spacedim>
15004unsigned int Triangulation<dim, spacedim>::n_cells() const
15005{
15007}
15008
15009
15010template <int dim, int spacedim>
15013{
15015}
15016
15017template <int dim, int spacedim>
15021{
15022 return n_active_cells();
15023}
15024
15025template <int dim, int spacedim>
15029{
15030 return n_cells(0);
15031}
15032
15033template <int dim, int spacedim>
15035unsigned int Triangulation<dim, spacedim>::n_faces() const
15036{
15037 switch (dim)
15038 {
15039 case 1:
15040 return n_used_vertices();
15041 case 2:
15042 return n_lines();
15043 case 3:
15044 return n_quads();
15045 default:
15047 }
15048 return 0;
15049}
15050
15051
15052template <int dim, int spacedim>
15055{
15056 switch (dim)
15057 {
15058 case 1:
15059 return n_vertices();
15060 case 2:
15061 return n_raw_lines();
15062 case 3:
15063 return n_raw_quads();
15064 default:
15066 }
15067 return 0;
15068}
15069
15070
15071template <int dim, int spacedim>
15074{
15075 switch (dim)
15076 {
15077 case 1:
15078 return n_used_vertices();
15079 case 2:
15080 return n_active_lines();
15081 case 3:
15082 return n_active_quads();
15083 default:
15085 }
15086 return 0;
15087}
15088
15089
15090template <int dim, int spacedim>
15093 const unsigned int level) const
15094{
15095 switch (dim)
15096 {
15097 case 1:
15098 return n_raw_lines(level);
15099 case 2:
15100 return n_raw_quads(level);
15101 case 3:
15102 return n_raw_hexs(level);
15103 default:
15105 }
15106 return 0;
15107}
15108
15109
15110
15111template <int dim, int spacedim>
15114 const unsigned int level) const
15115{
15116 switch (dim)
15117 {
15118 case 1:
15119 return n_lines(level);
15120 case 2:
15121 return n_quads(level);
15122 case 3:
15123 return n_hexs(level);
15124 default:
15126 }
15127 return 0;
15128}
15129
15130
15131
15132template <int dim, int spacedim>
15135 const unsigned int level) const
15136{
15137 switch (dim)
15138 {
15139 case 1:
15140 return n_active_lines(level);
15141 case 2:
15142 return n_active_quads(level);
15143 case 3:
15144 return n_active_hexs(level);
15145 default:
15147 }
15148 return 0;
15149}
15150
15151
15152template <int dim, int spacedim>
15155{
15156 if (anisotropic_refinement == false)
15157 {
15158 for (unsigned int lvl = 0; lvl < n_global_levels() - 1; ++lvl)
15159 if (n_active_cells(lvl) != 0)
15160 return true;
15161 }
15162 else
15163 {
15164 for (const auto &cell : active_cell_iterators())
15165 for (const auto &i : cell->face_indices())
15166 if (cell->face(i)->has_children())
15167 return true;
15168 }
15169 return false;
15170}
15171
15172
15173template <int dim, int spacedim>
15175unsigned int Triangulation<dim, spacedim>::n_lines() const
15176{
15177 return number_cache.n_lines;
15178}
15179
15180
15181
15182template <int dim, int spacedim>
15185 const unsigned int level) const
15186{
15187 if (dim == 1)
15188 {
15189 AssertIndexRange(level, n_levels());
15190 return levels[level]->cells.n_objects();
15191 }
15192
15193 Assert(false, ExcFacesHaveNoLevel());
15194 return 0;
15195}
15196
15197
15198template <int dim, int spacedim>
15201{
15202 if (dim == 1)
15203 {
15205 return 0;
15206 }
15207
15208 return faces->lines.n_objects();
15209}
15210
15211
15212template <int dim, int spacedim>
15215 const unsigned int level) const
15216{
15217 AssertIndexRange(level, number_cache.n_lines_level.size());
15218 Assert(dim == 1, ExcFacesHaveNoLevel());
15219 return number_cache.n_lines_level[level];
15220}
15221
15222
15223template <int dim, int spacedim>
15226{
15227 return number_cache.n_active_lines;
15228}
15229
15230
15231template <int dim, int spacedim>
15234 const unsigned int level) const
15235{
15236 AssertIndexRange(level, number_cache.n_lines_level.size());
15237 Assert(dim == 1, ExcFacesHaveNoLevel());
15238
15239 return number_cache.n_active_lines_level[level];
15240}
15241#endif
15242
15243template <>
15244unsigned int
15246{
15247 return 0;
15248}
15249
15250
15251template <>
15252unsigned int
15253Triangulation<1, 1>::n_quads(const unsigned int) const
15254{
15255 return 0;
15256}
15257
15258
15259template <>
15260unsigned int
15261Triangulation<1, 1>::n_raw_quads(const unsigned int) const
15262{
15263 return 0;
15264}
15265
15266
15267template <>
15268unsigned int
15269Triangulation<1, 1>::n_raw_hexs(const unsigned int) const
15270{
15271 return 0;
15272}
15273
15274
15275template <>
15276unsigned int
15278{
15279 return 0;
15280}
15281
15282
15283template <>
15284unsigned int
15286{
15287 return 0;
15288}
15289
15290
15291
15292template <>
15293unsigned int
15295{
15296 return 0;
15297}
15298
15299
15300template <>
15301unsigned int
15302Triangulation<1, 2>::n_quads(const unsigned int) const
15303{
15304 return 0;
15305}
15306
15307
15308template <>
15309unsigned int
15310Triangulation<1, 2>::n_raw_quads(const unsigned int) const
15311{
15312 return 0;
15313}
15314
15315
15316template <>
15317unsigned int
15318Triangulation<1, 2>::n_raw_hexs(const unsigned int) const
15319{
15320 return 0;
15321}
15322
15323
15324template <>
15325unsigned int
15327{
15328 return 0;
15329}
15330
15331
15332template <>
15333unsigned int
15335{
15336 return 0;
15337}
15338
15339
15340template <>
15341unsigned int
15343{
15344 return 0;
15345}
15346
15347
15348template <>
15349unsigned int
15350Triangulation<1, 3>::n_quads(const unsigned int) const
15351{
15352 return 0;
15353}
15354
15355
15356template <>
15357unsigned int
15358Triangulation<1, 3>::n_raw_quads(const unsigned int) const
15359{
15360 return 0;
15361}
15362
15363
15364template <>
15365unsigned int
15366Triangulation<1, 3>::n_raw_hexs(const unsigned int) const
15367{
15368 return 0;
15369}
15370
15371
15372template <>
15373unsigned int
15375{
15376 return 0;
15377}
15378
15379
15380template <>
15381unsigned int
15383{
15384 return 0;
15385}
15386
15387#ifndef DOXYGEN
15388
15389template <int dim, int spacedim>
15391unsigned int Triangulation<dim, spacedim>::n_quads() const
15392{
15393 return number_cache.n_quads;
15394}
15395
15396
15397template <int dim, int spacedim>
15400 const unsigned int level) const
15401{
15402 Assert(dim == 2, ExcFacesHaveNoLevel());
15403 AssertIndexRange(level, number_cache.n_quads_level.size());
15404 return number_cache.n_quads_level[level];
15405}
15406
15407#endif
15408
15409template <>
15410unsigned int
15412{
15413 AssertIndexRange(level, n_levels());
15414 return levels[level]->cells.n_objects();
15415}
15416
15417
15418
15419template <>
15420unsigned int
15422{
15423 AssertIndexRange(level, n_levels());
15424 return levels[level]->cells.n_objects();
15425}
15426
15427
15428template <>
15429unsigned int
15430Triangulation<3, 3>::n_raw_quads(const unsigned int) const
15431{
15432 Assert(false, ExcFacesHaveNoLevel());
15433 return 0;
15434}
15435
15436#ifndef DOXYGEN
15437
15438template <int dim, int spacedim>
15441{
15443 return 0;
15444}
15445
15446#endif
15447
15448template <>
15449unsigned int
15451{
15452 return faces->quads.n_objects();
15453}
15454
15455#ifndef DOXYGEN
15456
15457template <int dim, int spacedim>
15460{
15461 return number_cache.n_active_quads;
15462}
15463
15464
15465template <int dim, int spacedim>
15468 const unsigned int level) const
15469{
15470 AssertIndexRange(level, number_cache.n_quads_level.size());
15471 Assert(dim == 2, ExcFacesHaveNoLevel());
15472
15473 return number_cache.n_active_quads_level[level];
15474}
15475
15476
15477template <int dim, int spacedim>
15479unsigned int Triangulation<dim, spacedim>::n_hexs() const
15480{
15481 return 0;
15482}
15483
15484
15485
15486template <int dim, int spacedim>
15488unsigned int Triangulation<dim, spacedim>::n_hexs(const unsigned int) const
15489{
15490 return 0;
15491}
15492
15493
15494
15495template <int dim, int spacedim>
15497unsigned int Triangulation<dim, spacedim>::n_raw_hexs(const unsigned int) const
15498{
15499 return 0;
15500}
15501
15502
15503template <int dim, int spacedim>
15506{
15507 return 0;
15508}
15509
15510
15511
15512template <int dim, int spacedim>
15515 const unsigned int) const
15516{
15517 return 0;
15518}
15519
15520#endif
15521
15522template <>
15523unsigned int
15525{
15526 return number_cache.n_hexes;
15527}
15528
15529
15530
15531template <>
15532unsigned int
15533Triangulation<3, 3>::n_hexs(const unsigned int level) const
15534{
15535 AssertIndexRange(level, number_cache.n_hexes_level.size());
15536
15537 return number_cache.n_hexes_level[level];
15538}
15539
15540
15541
15542template <>
15543unsigned int
15545{
15546 AssertIndexRange(level, n_levels());
15547 return levels[level]->cells.n_objects();
15548}
15549
15550
15551template <>
15552unsigned int
15554{
15555 return number_cache.n_active_hexes;
15556}
15557
15558
15559
15560template <>
15561unsigned int
15563{
15564 AssertIndexRange(level, number_cache.n_hexes_level.size());
15565
15566 return number_cache.n_active_hexes_level[level];
15567}
15568
15569#ifndef DOXYGEN
15570
15571template <int dim, int spacedim>
15574{
15575 return std::count(vertices_used.begin(), vertices_used.end(), true);
15576}
15577
15578
15579
15580template <int dim, int spacedim>
15582const std::vector<bool> &Triangulation<dim, spacedim>::get_used_vertices() const
15583{
15584 return vertices_used;
15585}
15586
15587#endif
15588
15589template <>
15590unsigned int
15592{
15593 return 2;
15594}
15595
15596
15597
15598template <>
15599unsigned int
15601{
15602 return 2;
15603}
15604
15605
15606template <>
15607unsigned int
15609{
15610 return 2;
15611}
15612
15613#ifndef DOXYGEN
15614
15615template <int dim, int spacedim>
15618{
15619 cell_iterator cell = begin(0),
15620 endc = (n_levels() > 1 ? begin(1) : cell_iterator(end()));
15621 // store the largest index of the
15622 // vertices used on level 0
15623 unsigned int max_vertex_index = 0;
15624 for (; cell != endc; ++cell)
15625 for (const unsigned int vertex : GeometryInfo<dim>::vertex_indices())
15626 if (cell->vertex_index(vertex) > max_vertex_index)
15627 max_vertex_index = cell->vertex_index(vertex);
15628
15629 // store the number of times a cell
15630 // touches a vertex. An unsigned
15631 // int should suffice, even for
15632 // larger dimensions
15633 std::vector<unsigned short int> usage_count(max_vertex_index + 1, 0);
15634 // touch a vertex's usage count
15635 // every time we find an adjacent
15636 // element
15637 for (cell = begin(); cell != endc; ++cell)
15638 for (const unsigned int vertex : GeometryInfo<dim>::vertex_indices())
15639 ++usage_count[cell->vertex_index(vertex)];
15640
15642 static_cast<unsigned int>(
15643 *std::max_element(usage_count.begin(), usage_count.end())));
15644}
15645
15646
15647
15648template <int dim, int spacedim>
15652{
15654}
15655
15656
15657
15658template <int dim, int spacedim>
15661{
15662 return *this;
15663}
15664
15665
15666
15667template <int dim, int spacedim>
15671{
15672 return *this;
15673}
15674
15675
15676
15677template <int dim, int spacedim>
15681 &periodicity_vector)
15682{
15683 periodic_face_pairs_level_0.insert(periodic_face_pairs_level_0.end(),
15684 periodicity_vector.begin(),
15685 periodicity_vector.end());
15686
15687 // Now initialize periodic_face_map
15688 update_periodic_face_map();
15689}
15690
15691
15692
15693template <int dim, int spacedim>
15695const typename std::map<
15696 std::pair<typename Triangulation<dim, spacedim>::cell_iterator, unsigned int>,
15697 std::pair<std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
15698 unsigned int>,
15699 unsigned char>>
15701{
15702 return periodic_face_map;
15703}
15704
15705
15706
15707template <int dim, int spacedim>
15710{
15711 // Call our version of prepare_coarsening_and_refinement() even if a derived
15712 // class like parallel::distributed::Triangulation overrides it. Their
15713 // function will be called in their execute_coarsening_and_refinement()
15714 // function. Even in a distributed computation our job here is to reconstruct
15715 // the local part of the mesh and as such checking our flags is enough.
15717
15718 // verify a case with which we have had
15719 // some difficulty in the past (see the
15720 // deal.II/coarsening_* tests)
15721 if (smooth_grid & limit_level_difference_at_vertices)
15722 Assert(satisfies_level1_at_vertex_rule(*this) == true, ExcInternalError());
15723
15724 // Inform all listeners about beginning of refinement.
15725 signals.pre_refinement();
15726
15727 execute_coarsening();
15728
15729 const DistortedCellList cells_with_distorted_children = execute_refinement();
15730
15731 reset_cell_vertex_indices_cache();
15732
15733 // verify a case with which we have had
15734 // some difficulty in the past (see the
15735 // deal.II/coarsening_* tests)
15736 if (smooth_grid & limit_level_difference_at_vertices)
15737 Assert(satisfies_level1_at_vertex_rule(*this) == true, ExcInternalError());
15738
15739 // finally build up neighbor connectivity information, and set
15740 // active cell indices
15741 this->policy->update_neighbors(*this);
15742 reset_active_cell_indices();
15743
15744 reset_global_cell_indices(); // TODO: better place?
15745
15746 // Inform all listeners about end of refinement.
15747 signals.post_refinement();
15748
15749 AssertThrow(cells_with_distorted_children.distorted_cells.empty(),
15750 cells_with_distorted_children);
15751
15752 update_periodic_face_map();
15753
15754# ifdef DEBUG
15755
15756 // In debug mode, we want to check for some consistency of the
15757 // result of this function. Because there are multiple exit
15758 // paths, put this check into a ScopeExit object that is
15759 // executed on each of the exit paths.
15760 //
15761 // Specifically, check on exit of this function that if a quad
15762 // cell has been refined, all of its children have neighbors
15763 // in all directions in which the parent cell has neighbors as
15764 // well. The children's neighbors are either the parent
15765 // neighbor or the parent neighbor's children, or simply one of
15766 // the other children of the current cell. This check is
15767 // useful because if one creates a triangulation with an
15768 // inconsistently ordered set of cells (e.g., because one has
15769 // forgotten to call GridTools::consistently_order_cells()),
15770 // then this relatively simple invariant is violated -- so the
15771 // check here can be used to catch that case, at least
15772 // sometimes.
15773 //
15774 // In 1d, this situation cannot happen. In 3d, we have explicit
15775 // orientation flags to ensure that it is not necessary to re-orient
15776 // cells at the beginning. But in both cases, the invariant should
15777 // still hold as long as the cell is a hypercube.
15778 for (const auto &cell : cell_iterators())
15779 {
15780 if (cell->has_children() && cell->reference_cell().is_hyper_cube())
15781 for (const unsigned int f : cell->face_indices())
15782 if (cell->at_boundary(f) == false)
15783 {
15784 for (const auto &child : cell->child_iterators())
15785 {
15786 Assert(
15787 child->at_boundary(f) == false,
15788 ExcMessage(
15789 "We ended up with a triangulation whose child cells "
15790 "are not connected to their neighbors as expected. "
15791 "When you created the triangulation, did you forget "
15792 "to call GridTools::consistently_order_cells() "
15793 "before calling Triangulation::create_triangulation()?"));
15794 }
15795 }
15796 }
15797# endif
15798}
15799
15800
15801
15802template <int dim, int spacedim>
15805{
15806 unsigned int active_cell_index = 0;
15807 for (raw_cell_iterator cell = begin_raw(); cell != end(); ++cell)
15808 if ((cell->used() == false) || cell->has_children())
15809 cell->set_active_cell_index(numbers::invalid_unsigned_int);
15810 else
15811 {
15812 cell->set_active_cell_index(active_cell_index);
15813 ++active_cell_index;
15814 }
15815
15816 Assert(active_cell_index == n_active_cells(), ExcInternalError());
15817}
15818
15819
15820
15821template <int dim, int spacedim>
15824{
15825 {
15827 for (const auto &cell : active_cell_iterators())
15828 cell->set_global_active_cell_index(cell_index++);
15829 }
15830
15831 for (unsigned int l = 0; l < levels.size(); ++l)
15832 {
15834 for (const auto &cell : cell_iterators_on_level(l))
15835 cell->set_global_level_cell_index(cell_index++);
15836 }
15837}
15838
15839
15840
15841template <int dim, int spacedim>
15844{
15845 for (unsigned int l = 0; l < levels.size(); ++l)
15846 {
15847 constexpr unsigned int max_vertices_per_cell = 1 << dim;
15848 std::vector<unsigned int> &cache = levels[l]->cell_vertex_indices_cache;
15849 cache.clear();
15850 cache.resize(levels[l]->refine_flags.size() * max_vertices_per_cell,
15852 for (const auto &cell : cell_iterators_on_level(l))
15853 {
15854 const unsigned int my_index = cell->index() * max_vertices_per_cell;
15855
15856 // to reduce the cost of this function when passing down into quads,
15857 // then lines, then vertices, we use a more low-level access method
15858 // for hexahedral cells, where we can streamline most of the logic
15859 const ReferenceCell ref_cell = cell->reference_cell();
15860 if (ref_cell == ReferenceCells::Hexahedron)
15861 for (unsigned int face = 4; face < 6; ++face)
15862 {
15863 const auto face_iter = cell->face(face);
15864 const std::array<bool, 2> line_orientations{
15865 {face_iter->line_orientation(0),
15866 face_iter->line_orientation(1)}};
15867 std::array<unsigned int, 4> raw_vertex_indices{
15868 {face_iter->line(0)->vertex_index(1 - line_orientations[0]),
15869 face_iter->line(1)->vertex_index(1 - line_orientations[1]),
15870 face_iter->line(0)->vertex_index(line_orientations[0]),
15871 face_iter->line(1)->vertex_index(line_orientations[1])}};
15872
15873 const unsigned char combined_orientation =
15874 levels[l]->face_orientations.get_combined_orientation(
15875 cell->index() * GeometryInfo<3>::faces_per_cell + face);
15876 std::array<unsigned int, 4> vertex_order{
15877 {ref_cell.standard_to_real_face_vertex(0,
15878 face,
15879 combined_orientation),
15881 face,
15882 combined_orientation),
15884 face,
15885 combined_orientation),
15887 3, face, combined_orientation)}};
15888
15889 const unsigned int index = my_index + 4 * (face - 4);
15890 for (unsigned int i = 0; i < 4; ++i)
15891 cache[index + i] = raw_vertex_indices[vertex_order[i]];
15892 }
15893 else if (ref_cell == ReferenceCells::Quadrilateral)
15894 {
15895 const std::array<bool, 2> line_orientations{
15896 {cell->line_orientation(0), cell->line_orientation(1)}};
15897 std::array<unsigned int, 4> raw_vertex_indices{
15898 {cell->line(0)->vertex_index(1 - line_orientations[0]),
15899 cell->line(1)->vertex_index(1 - line_orientations[1]),
15900 cell->line(0)->vertex_index(line_orientations[0]),
15901 cell->line(1)->vertex_index(line_orientations[1])}};
15902 for (unsigned int i = 0; i < 4; ++i)
15903 cache[my_index + i] = raw_vertex_indices[i];
15904 }
15905 else
15906 for (const unsigned int i : cell->vertex_indices())
15907 cache[my_index + i] = internal::TriaAccessorImplementation::
15908 Implementation::vertex_index(*cell, i);
15909 }
15910 }
15911}
15912
15913
15914
15915template <int dim, int spacedim>
15918{
15919 // first empty the currently stored objects
15920 periodic_face_map.clear();
15921
15922 typename std::vector<
15924 for (it = periodic_face_pairs_level_0.begin();
15925 it != periodic_face_pairs_level_0.end();
15926 ++it)
15927 {
15928 update_periodic_face_map_recursively<dim, spacedim>(it->cell[0],
15929 it->cell[1],
15930 it->face_idx[0],
15931 it->face_idx[1],
15932 it->orientation,
15933 periodic_face_map);
15934
15935 const auto face_reference_cell =
15936 it->cell[0]->reference_cell().face_reference_cell(it->face_idx[0]);
15937 // for the other way, we need to invert the orientation
15938 update_periodic_face_map_recursively<dim, spacedim>(
15939 it->cell[1],
15940 it->cell[0],
15941 it->face_idx[1],
15942 it->face_idx[0],
15943 face_reference_cell.get_inverse_combined_orientation(it->orientation),
15944 periodic_face_map);
15945 }
15946
15947 // check consistency
15948 typename std::map<std::pair<cell_iterator, unsigned int>,
15949 std::pair<std::pair<cell_iterator, unsigned int>,
15950 unsigned char>>::const_iterator it_test;
15951 for (it_test = periodic_face_map.begin(); it_test != periodic_face_map.end();
15952 ++it_test)
15953 {
15955 it_test->first.first;
15957 it_test->second.first.first;
15958 if (cell_1->level() == cell_2->level())
15959 {
15960 // if both cells have the same neighbor, then the same pair
15961 // order swapped has to be in the map
15962 Assert(periodic_face_map[it_test->second.first].first ==
15963 it_test->first,
15965 }
15966 }
15967}
15968
15969
15970
15971template <int dim, int spacedim>
15974{
15975 std::set<ReferenceCell> reference_cells_set;
15976 for (auto cell : active_cell_iterators())
15977 if (cell->is_locally_owned())
15978 reference_cells_set.insert(cell->reference_cell());
15979
15980 this->reference_cells =
15981 std::vector<ReferenceCell>(reference_cells_set.begin(),
15982 reference_cells_set.end());
15983}
15984
15985
15986
15987template <int dim, int spacedim>
15989const std::vector<ReferenceCell>
15991{
15992 return this->reference_cells;
15993}
15994
15995
15996
15997template <int dim, int spacedim>
16000{
16001 Assert(this->reference_cells.size() > 0,
16002 ExcMessage("You can't ask about the kinds of reference "
16003 "cells used by this triangulation if the "
16004 "triangulation doesn't yet have any cells in it."));
16005 return (this->reference_cells.size() == 1 &&
16006 this->reference_cells[0].is_hyper_cube());
16007}
16008
16009
16010
16011template <int dim, int spacedim>
16014{
16015 Assert(this->reference_cells.size() > 0,
16016 ExcMessage("You can't ask about the kinds of reference "
16017 "cells used by this triangulation if the "
16018 "triangulation doesn't yet have any cells in it."));
16019 return (this->reference_cells.size() == 1 &&
16020 this->reference_cells[0].is_simplex());
16021}
16022
16023
16024
16025template <int dim, int spacedim>
16028{
16029 Assert(this->reference_cells.size() > 0,
16030 ExcMessage("You can't ask about the kinds of reference "
16031 "cells used by this triangulation if the "
16032 "triangulation doesn't yet have any cells in it."));
16033 return reference_cells.size() > 1 ||
16034 ((reference_cells[0].is_hyper_cube() == false) &&
16035 (reference_cells[0].is_simplex() == false));
16036}
16037
16038
16039
16040template <int dim, int spacedim>
16043 const std::function<std::vector<char>(const cell_iterator &,
16044 const ::CellStatus)>
16045 &pack_callback,
16046 const bool returns_variable_size_data)
16047{
16048 unsigned int handle = numbers::invalid_unsigned_int;
16049
16050 // Add new callback function to the corresponding register.
16051 // Encode handles according to returns_variable_size_data.
16052 if (returns_variable_size_data)
16053 {
16054 handle = 2 * this->cell_attached_data.pack_callbacks_variable.size();
16055 this->cell_attached_data.pack_callbacks_variable.push_back(pack_callback);
16056 }
16057 else
16058 {
16059 handle = 2 * this->cell_attached_data.pack_callbacks_fixed.size() + 1;
16060 this->cell_attached_data.pack_callbacks_fixed.push_back(pack_callback);
16061 }
16062
16063 // Increase overall counter.
16064 ++this->cell_attached_data.n_attached_data_sets;
16065
16066 return handle;
16067}
16068
16069
16070
16071template <int dim, int spacedim>
16074 const unsigned int handle,
16075 const std::function<
16076 void(const cell_iterator &,
16077 const ::CellStatus,
16078 const boost::iterator_range<std::vector<char>::const_iterator> &)>
16079 &unpack_callback)
16080{
16081 // perform unpacking
16082 this->data_serializer.unpack_data(this->local_cell_relations,
16083 handle,
16084 unpack_callback);
16085
16086 // decrease counters
16087 --this->cell_attached_data.n_attached_data_sets;
16088 if (this->cell_attached_data.n_attached_deserialize > 0)
16089 --this->cell_attached_data.n_attached_deserialize;
16090
16091 // important: only remove data if we are not in the deserialization
16092 // process. There, each SolutionTransfer registers and unpacks before
16093 // the next one does this, so n_attached_data_sets is only 1 here. This
16094 // would destroy the saved data before the second SolutionTransfer can
16095 // get it. This created a bug that is documented in
16096 // tests/mpi/p4est_save_03 with more than one SolutionTransfer.
16097
16098 if (this->cell_attached_data.n_attached_data_sets == 0 &&
16099 this->cell_attached_data.n_attached_deserialize == 0)
16100 {
16101 // everybody got their data, time for cleanup!
16102 this->cell_attached_data.pack_callbacks_fixed.clear();
16103 this->cell_attached_data.pack_callbacks_variable.clear();
16104 this->data_serializer.clear();
16105
16106 // reset all cell_status entries after coarsening/refinement
16107 for (auto &cell_rel : this->local_cell_relations)
16108 cell_rel.second = ::CellStatus::cell_will_persist;
16109 }
16110}
16111
16112
16113
16114template <int dim, int spacedim>
16117 const unsigned int global_first_cell,
16118 const unsigned int global_num_cells,
16119 const std::string &filename) const
16120{
16121 // cast away constness
16122 auto tria = const_cast<Triangulation<dim, spacedim> *>(this);
16123
16124 if (this->cell_attached_data.n_attached_data_sets > 0)
16125 {
16126 // pack attached data first
16131 this->get_communicator());
16132
16133 // then store buffers in file
16134 tria->data_serializer.save(global_first_cell,
16135 global_num_cells,
16136 filename,
16137 this->get_communicator());
16138
16139 // and release the memory afterwards
16141 }
16142
16143 // clear all of the callback data, as explained in the documentation of
16144 // register_data_attach()
16145 {
16149 }
16150}
16151
16152
16153template <int dim, int spacedim>
16156 const unsigned int global_first_cell,
16157 const unsigned int global_num_cells,
16158 const unsigned int local_num_cells,
16159 const std::string &filename,
16160 const unsigned int n_attached_deserialize_fixed,
16161 const unsigned int n_attached_deserialize_variable)
16162{
16163 // load saved data, if any was stored
16164 if (this->cell_attached_data.n_attached_deserialize > 0)
16165 {
16166 this->data_serializer.load(global_first_cell,
16167 global_num_cells,
16168 local_num_cells,
16169 filename,
16170 n_attached_deserialize_fixed,
16171 n_attached_deserialize_variable,
16172 this->get_communicator());
16173
16174 this->data_serializer.unpack_cell_status(this->local_cell_relations);
16175
16176 // the CellStatus of all stored cells should always be
16177 // CellStatus::cell_will_persist.
16178 for (const auto &cell_rel : this->local_cell_relations)
16179 {
16180 (void)cell_rel;
16181 Assert((cell_rel.second == // cell_status
16184 }
16185 }
16186}
16187
16188
16189template <int dim, int spacedim>
16192{
16193 levels.clear();
16194 faces.reset();
16195
16196 vertices.clear();
16197 vertices_used.clear();
16198
16199 manifolds.clear();
16200
16201 // In 1d, also reset vertex-to-(boundary|manifold) maps to empty maps
16202 if (dim == 1)
16203 {
16204 Assert(vertex_to_boundary_id_map_1d != nullptr, ExcInternalError());
16205 vertex_to_boundary_id_map_1d->clear();
16206
16207 Assert(vertex_to_manifold_id_map_1d != nullptr, ExcInternalError());
16208 vertex_to_manifold_id_map_1d->clear();
16209 }
16210 else
16211 {
16212 // For dim>1, these maps should simply not exist.
16213 Assert(vertex_to_boundary_id_map_1d == nullptr, ExcInternalError());
16214 Assert(vertex_to_manifold_id_map_1d == nullptr, ExcInternalError());
16215 }
16216
16217
16219}
16220
16221
16222
16223template <int dim, int spacedim>
16227{
16228 const DistortedCellList cells_with_distorted_children =
16229 this->policy->execute_refinement(*this, check_for_distorted_cells);
16230
16231
16232
16233 // re-compute number of lines
16235 *this, levels.size(), number_cache);
16236
16237# ifdef DEBUG
16238 for (const auto &level : levels)
16239 monitor_memory(level->cells, dim);
16240
16241 // check whether really all refinement flags are reset (also of
16242 // previously non-active cells which we may not have touched. If the
16243 // refinement flag of a non-active cell is set, something went wrong
16244 // since the cell-accessors should have caught this)
16245 for (const auto &cell : this->cell_iterators())
16246 Assert(!cell->refine_flag_set(), ExcInternalError());
16247# endif
16248
16249 return cells_with_distorted_children;
16250}
16251
16252
16253
16254template <int dim, int spacedim>
16257{
16258 // first find out if there are any cells at all to be coarsened in the
16259 // loop below
16260 const cell_iterator endc = end();
16261 bool do_coarsen = false;
16262 if (levels.size() >= 2)
16263 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
16264 if (!cell->is_active() && cell->child(0)->coarsen_flag_set())
16265 {
16266 do_coarsen = true;
16267 break;
16268 }
16269
16270 if (!do_coarsen)
16271 return;
16272
16273 // create a vector counting for each line and quads how many cells contain
16274 // the respective object. this is used later to decide which lines can be
16275 // deleted after coarsening a cell.
16276 std::vector<unsigned int> line_cell_count(dim > 1 ? this->n_raw_lines() : 0);
16277 std::vector<unsigned int> quad_cell_count(dim > 2 ? this->n_raw_quads() : 0);
16278 if (dim > 1)
16279 for (const auto &cell : this->cell_iterators())
16280 {
16281 if (dim > 2)
16282 {
16283 const auto line_indices = internal::TriaAccessorImplementation::
16284 Implementation::get_line_indices_of_cell(*cell);
16285 // avoid a compiler warning by fixing the max number of
16286 // loop iterations to 12
16287 const unsigned int n_lines = std::min(cell->n_lines(), 12u);
16288 for (unsigned int l = 0; l < n_lines; ++l)
16289 ++line_cell_count[line_indices[l]];
16290 for (const unsigned int q : cell->face_indices())
16291 ++quad_cell_count[cell->face_index(q)];
16292 }
16293 else
16294 for (unsigned int l = 0; l < cell->n_lines(); ++l)
16295 ++line_cell_count[cell->line(l)->index()];
16296 }
16297
16298 // Since the loop goes over used cells we only need not worry about
16299 // deleting some cells since the ++operator will then just hop over them
16300 // if we should hit one. Do the loop in the reverse way since we may
16301 // only delete some cells if their neighbors have already been deleted
16302 // (if the latter are on a higher level for example). In effect, only
16303 // those cells are deleted of which originally all children were flagged
16304 // and for which all children are on the same refinement level. Note
16305 // that because of the effects of
16306 // @p{fix_coarsen_flags}, of a cell either all or no children must be
16307 // flagged for coarsening, so it is ok to only check the first child
16308 //
16309 // since we delete the *children* of cells, we can ignore cells on the
16310 // highest level, i.e., level must be less than or equal to
16311 // n_levels()-2.
16312 if (levels.size() >= 2)
16313 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
16314 if (!cell->is_active() && cell->child(0)->coarsen_flag_set())
16315 {
16316 for (unsigned int child = 0; child < cell->n_children(); ++child)
16317 {
16318 Assert(cell->child(child)->coarsen_flag_set(),
16320 cell->child(child)->clear_coarsen_flag();
16321 }
16322 // inform all listeners that cell coarsening is going to happen
16323 signals.pre_coarsening_on_cell(cell);
16324 // use a separate function, since this is dimension specific
16325 this->policy->delete_children(*this,
16326 cell,
16327 line_cell_count,
16328 quad_cell_count);
16329 }
16330
16331 // re-compute number of lines and quads
16333 *this, levels.size(), number_cache);
16334}
16335
16336
16337
16338template <int dim, int spacedim>
16341{
16342 // copy a piece of code from prepare_coarsening_and_refinement that
16343 // ensures that the level difference at vertices is limited if so
16344 // desired. we need this code here since at least in 1d we don't
16345 // call the dimension-independent version of
16346 // prepare_coarsening_and_refinement function. in 2d and 3d, having
16347 // this hunk here makes our lives a bit easier as well as it takes
16348 // care of these cases earlier than it would otherwise happen.
16349 //
16350 // the main difference to the code in p_c_and_r is that here we
16351 // absolutely have to make sure that we get things right, i.e. that
16352 // in particular we set flags right if
16353 // limit_level_difference_at_vertices is set. to do so we iterate
16354 // until the flags don't change any more
16355 auto previous_coarsen_flags = internal::extract_raw_coarsen_flags(levels);
16356
16357 bool continue_iterating = true;
16358
16359 do
16360 {
16361 if (smooth_grid & limit_level_difference_at_vertices)
16362 {
16363 Assert(!anisotropic_refinement,
16364 ExcMessage("In case of anisotropic refinement the "
16365 "limit_level_difference_at_vertices flag for "
16366 "mesh smoothing must not be set!"));
16367
16368 // store highest level one of the cells adjacent to a vertex
16369 // belongs to
16370 std::vector<int> vertex_level(vertices.size(), 0);
16371 for (const auto &cell : this->active_cell_iterators())
16372 {
16373 if (cell->refine_flag_set())
16374 for (const unsigned int vertex :
16376 vertex_level[cell->vertex_index(vertex)] =
16377 std::max(vertex_level[cell->vertex_index(vertex)],
16378 cell->level() + 1);
16379 else if (!cell->coarsen_flag_set())
16380 for (const unsigned int vertex :
16382 vertex_level[cell->vertex_index(vertex)] =
16383 std::max(vertex_level[cell->vertex_index(vertex)],
16384 cell->level());
16385 else
16386 {
16387 // if coarsen flag is set then tentatively assume
16388 // that the cell will be coarsened. this isn't
16389 // always true (the coarsen flag could be removed
16390 // again) and so we may make an error here. we try
16391 // to correct this by iterating over the entire
16392 // process until we are converged
16393 Assert(cell->coarsen_flag_set(), ExcInternalError());
16394 for (const unsigned int vertex :
16396 vertex_level[cell->vertex_index(vertex)] =
16397 std::max(vertex_level[cell->vertex_index(vertex)],
16398 cell->level() - 1);
16399 }
16400 }
16401
16402
16403 // loop over all cells in reverse order. do so because we
16404 // can then update the vertex levels on the adjacent
16405 // vertices and maybe already flag additional cells in this
16406 // loop
16407 //
16408 // note that not only may we have to add additional
16409 // refinement flags, but we will also have to remove
16410 // coarsening flags on cells adjacent to vertices that will
16411 // see refinement
16412 active_cell_iterator endc = end();
16413 for (active_cell_iterator cell = last_active(); cell != endc; --cell)
16414 if (cell->refine_flag_set() == false)
16415 {
16416 for (const unsigned int vertex :
16418 if (vertex_level[cell->vertex_index(vertex)] >=
16419 cell->level() + 1)
16420 {
16421 // remove coarsen flag...
16422 cell->clear_coarsen_flag();
16423
16424 // ...and if necessary also refine the current
16425 // cell, at the same time updating the level
16426 // information about vertices
16427 if (vertex_level[cell->vertex_index(vertex)] >
16428 cell->level() + 1)
16429 {
16430 cell->set_refine_flag();
16431
16432 for (const unsigned int v :
16434 vertex_level[cell->vertex_index(v)] =
16435 std::max(vertex_level[cell->vertex_index(v)],
16436 cell->level() + 1);
16437 }
16438
16439 // continue and see whether we may, for example,
16440 // go into the inner 'if' above based on a
16441 // different vertex
16442 }
16443 }
16444 }
16445
16446 // loop over all cells and remove the coarsen flags for those cells that
16447 // have sister cells not marked for coarsening, or where some neighbors
16448 // are more refined.
16449
16450 // Coarsen flags of cells with no mother cell, i.e. on the
16451 // coarsest level, are deleted explicitly.
16452 for (const auto &acell : this->active_cell_iterators_on_level(0))
16453 acell->clear_coarsen_flag();
16454
16455 const cell_iterator endc = end();
16456 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
16457 {
16458 // nothing to do if we are already on the finest level
16459 if (cell->is_active())
16460 continue;
16461
16462 const unsigned int n_children = cell->n_children();
16463 unsigned int flagged_children = 0;
16464 for (unsigned int child = 0; child < n_children; ++child)
16465 {
16466 const auto child_cell = cell->child(child);
16467 if (child_cell->is_active() && child_cell->coarsen_flag_set())
16468 {
16469 ++flagged_children;
16470 // clear flag since we don't need it anymore
16471 child_cell->clear_coarsen_flag();
16472 }
16473 }
16474
16475 // flag the children for coarsening again if all children were
16476 // flagged and if the policy allows it
16477 if (flagged_children == n_children &&
16478 this->policy->coarsening_allowed(cell))
16479 for (unsigned int c = 0; c < n_children; ++c)
16480 {
16481 Assert(cell->child(c)->refine_flag_set() == false,
16483
16484 cell->child(c)->set_coarsen_flag();
16485 }
16486 }
16487
16488 // now see if anything has changed in the last iteration of this
16489 // function
16490 auto current_coarsen_flags = internal::extract_raw_coarsen_flags(levels);
16491
16492 continue_iterating = (current_coarsen_flags != previous_coarsen_flags);
16493 previous_coarsen_flags.swap(current_coarsen_flags);
16494 }
16495 while (continue_iterating == true);
16496}
16497
16498#endif
16499
16500// TODO: merge the following 3 functions since they are the same
16501template <>
16502bool
16504{
16505 // save the flags to determine whether something was changed in the
16506 // course of this function
16507 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
16508
16509 // do nothing in 1d, except setting the coarsening flags correctly
16510 fix_coarsen_flags();
16511
16512 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
16513
16514 return (flags_before != flags_after);
16515}
16516
16517
16518
16519template <>
16520bool
16522{
16523 // save the flags to determine whether something was changed in the
16524 // course of this function
16525 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
16526
16527 // do nothing in 1d, except setting the coarsening flags correctly
16528 fix_coarsen_flags();
16529
16530 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
16531
16532 return (flags_before != flags_after);
16533}
16534
16535
16536
16537template <>
16538bool
16540{
16541 // save the flags to determine whether something was changed in the
16542 // course of this function
16543 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
16544
16545 // do nothing in 1d, except setting the coarsening flags correctly
16546 fix_coarsen_flags();
16547
16548 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
16549
16550 return (flags_before != flags_after);
16551}
16552
16553
16554
16555namespace
16556{
16557 // check if the given @param cell marked for coarsening would
16558 // produce an unrefined island. To break up long chains of these
16559 // cells we recursively check our neighbors in case we change this
16560 // cell. This reduces the number of outer iterations dramatically.
16561 template <int dim, int spacedim>
16562 void
16563 possibly_do_not_produce_unrefined_islands(
16565 {
16566 Assert(cell->has_children(), ExcInternalError());
16567
16568 unsigned int n_neighbors = 0;
16569 // count all neighbors that will be refined along the face of our
16570 // cell after the next step
16571 unsigned int count = 0;
16572 for (const unsigned int n : GeometryInfo<dim>::face_indices())
16573 {
16574 const typename Triangulation<dim, spacedim>::cell_iterator neighbor =
16575 cell->neighbor(n);
16576 if (neighbor.state() == IteratorState::valid)
16577 {
16578 ++n_neighbors;
16579 if (face_will_be_refined_by_neighbor(cell, n))
16580 ++count;
16581 }
16582 }
16583 // clear coarsen flags if either all existing neighbors will be
16584 // refined or all but one will be and the cell is in the interior
16585 // of the domain
16586 if (count == n_neighbors ||
16587 (count >= n_neighbors - 1 &&
16588 n_neighbors == GeometryInfo<dim>::faces_per_cell))
16589 {
16590 for (unsigned int c = 0; c < cell->n_children(); ++c)
16591 cell->child(c)->clear_coarsen_flag();
16592
16593 for (const unsigned int face : GeometryInfo<dim>::face_indices())
16594 if (!cell->at_boundary(face) &&
16595 (!cell->neighbor(face)->is_active()) &&
16596 (cell_will_be_coarsened(cell->neighbor(face))))
16597 possibly_do_not_produce_unrefined_islands<dim, spacedim>(
16598 cell->neighbor(face));
16599 }
16600 }
16601
16602
16603 // see if the current cell needs to be refined to avoid unrefined
16604 // islands.
16605 //
16606 // there are sometimes chains of cells that induce refinement of
16607 // each other. to avoid running the loop in
16608 // prepare_coarsening_and_refinement over and over again for each
16609 // one of them, at least for the isotropic refinement case we seek
16610 // to flag neighboring elements as well as necessary. this takes
16611 // care of (slightly pathological) cases like
16612 // deal.II/mesh_smoothing_03
16613 template <int dim, int spacedim>
16614 void
16615 possibly_refine_unrefined_island(
16617 const bool allow_anisotropic_smoothing)
16618 {
16619 Assert(cell->is_active(), ExcInternalError());
16620
16621#ifdef DEBUG
16622 // If this is not a parallel::distributed::Triangulation, then we really
16623 // should only get here if the cell is marked for refinement:
16625 *>(&cell->get_triangulation()) == nullptr)
16626 Assert(cell->refine_flag_set() == false, ExcInternalError());
16627 else
16628 // But if this is a p::d::Triangulation, then we don't have that
16629 // much control and we can get here because mesh smoothing is
16630 // requested but can not be honored because p4est controls
16631 // what gets refined. In that case, we can at least provide
16632 // a better error message.
16633 Assert(cell->refine_flag_set() == false,
16634 ExcMessage(
16635 "The triangulation is trying to avoid unrefined islands "
16636 "during mesh refinement/coarsening, as you had requested "
16637 " by passing the appropriate 'smoothing flags' to the "
16638 "constructor of the triangulation. However, for objects "
16639 "of type parallel::distributed::Triangulation, control "
16640 "over which cells get refined rests with p4est, not the "
16641 "deal.II triangulation, and consequently it is not "
16642 "always possible to avoid unrefined islands in the mesh. "
16643 "Please remove the constructor argument to the triangulation "
16644 "object that requests mesh smoothing."));
16645#endif
16646
16647 // now we provide two algorithms. the first one is the standard
16648 // one, coming from the time, where only isotropic refinement was
16649 // possible. it simply counts the neighbors that are or will be
16650 // refined and compares to the number of other ones. the second
16651 // one does this check independently for each direction: if all
16652 // neighbors in one direction (normally two, at the boundary only
16653 // one) are refined, the current cell is flagged to be refined in
16654 // an according direction.
16655
16656 if (allow_anisotropic_smoothing == false)
16657 {
16658 // use first algorithm
16659 unsigned int refined_neighbors = 0, unrefined_neighbors = 0;
16660 for (const unsigned int face : GeometryInfo<dim>::face_indices())
16661 if (!cell->at_boundary(face))
16662 {
16663 if (face_will_be_refined_by_neighbor(cell, face))
16664 ++refined_neighbors;
16665 else
16666 ++unrefined_neighbors;
16667 }
16668
16669 if (unrefined_neighbors < refined_neighbors)
16670 {
16671 cell->clear_coarsen_flag();
16672 cell->set_refine_flag();
16673
16674 // ok, so now we have flagged this cell. if we know that
16675 // there were any unrefined neighbors at all, see if any
16676 // of those will have to be refined as well
16677 if (unrefined_neighbors > 0)
16678 for (const unsigned int face : GeometryInfo<dim>::face_indices())
16679 if (!cell->at_boundary(face) &&
16680 (face_will_be_refined_by_neighbor(cell, face) == false) &&
16681 (cell->neighbor(face)->has_children() == false) &&
16682 (cell->neighbor(face)->refine_flag_set() == false))
16683 possibly_refine_unrefined_island<dim, spacedim>(
16684 cell->neighbor(face), allow_anisotropic_smoothing);
16685 }
16686 }
16687 else
16688 {
16689 // variable to store the cell refine case needed to fulfill
16690 // all smoothing requirements
16691 RefinementCase<dim> smoothing_cell_refinement_case =
16693
16694 // use second algorithm, do the check individually for each
16695 // direction
16696 for (unsigned int face_pair = 0;
16697 face_pair < GeometryInfo<dim>::faces_per_cell / 2;
16698 ++face_pair)
16699 {
16700 // variable to store the cell refine case needed to refine
16701 // at the current face pair in the same way as the
16702 // neighbors do...
16703 RefinementCase<dim> directional_cell_refinement_case =
16705
16706 for (unsigned int face_index = 0; face_index < 2; ++face_index)
16707 {
16708 unsigned int face = 2 * face_pair + face_index;
16709 // variable to store the refine case (to come) of the
16710 // face under consideration
16711 RefinementCase<dim - 1> expected_face_ref_case =
16712 RefinementCase<dim - 1>::no_refinement;
16713
16714 if (cell->neighbor(face).state() == IteratorState::valid)
16715 face_will_be_refined_by_neighbor<dim, spacedim>(
16716 cell, face, expected_face_ref_case);
16717 // now extract which refine case would be necessary to
16718 // achieve the same face refinement. set the
16719 // intersection with other requirements for the same
16720 // direction.
16721
16722 // note: using the intersection is not an obvious
16723 // decision, we could also argue that it is more
16724 // natural to use the union. however, intersection is
16725 // the less aggressive tactic and favours a smaller
16726 // number of refined cells over an intensive
16727 // smoothing. this way we try not to lose too much of
16728 // the effort we put in anisotropic refinement
16729 // indicators due to overly aggressive smoothing...
16730 directional_cell_refinement_case =
16731 (directional_cell_refinement_case &
16734 expected_face_ref_case,
16735 face,
16736 cell->face_orientation(face),
16737 cell->face_flip(face),
16738 cell->face_rotation(face)));
16739 } // for both face indices
16740 // if both requirements sum up to something useful, add
16741 // this to the refine case for smoothing. note: if
16742 // directional_cell_refinement_case is isotropic still,
16743 // then something went wrong...
16744 Assert(directional_cell_refinement_case <
16747 smoothing_cell_refinement_case =
16748 smoothing_cell_refinement_case | directional_cell_refinement_case;
16749 } // for all face_pairs
16750 // no we collected contributions from all directions. combine
16751 // the new flags with the existing refine case, but only if
16752 // smoothing is required
16753 if (smoothing_cell_refinement_case)
16754 {
16755 cell->clear_coarsen_flag();
16756 cell->set_refine_flag(cell->refine_flag_set() |
16757 smoothing_cell_refinement_case);
16758 }
16759 }
16760 }
16761} // namespace
16762
16763#ifndef DOXYGEN
16764template <int dim, int spacedim>
16767{
16768 // save the flags to determine whether something was changed in the
16769 // course of this function
16770 const auto coarsen_flags_before = internal::extract_raw_coarsen_flags(levels);
16771 const auto refine_flags_before = internal::extract_raw_refine_flags(levels);
16772
16773 // save the flags at the outset of each loop. we do so in order to
16774 // find out whether something was changed in the present loop, in
16775 // which case we would have to re-run the loop. the other
16776 // possibility to find this out would be to set a flag
16777 // @p{something_changed} to true each time we change something.
16778 // however, sometimes one change in one of the parts of the loop is
16779 // undone by another one, so we might end up in an endless loop. we
16780 // could be tempted to break this loop at an arbitrary number of
16781 // runs, but that would not be a clean solution, since we would
16782 // either have to 1/ break the loop too early, in which case the
16783 // promise that a second call to this function immediately after the
16784 // first one does not change anything, would be broken, or 2/ we do
16785 // as many loops as there are levels. we know that information is
16786 // transported over one level in each run of the loop, so this is
16787 // enough. Unfortunately, each loop is rather expensive, so we chose
16788 // the way presented here
16789 auto coarsen_flags_before_loop = coarsen_flags_before;
16790 auto refine_flags_before_loop = refine_flags_before;
16791
16792 // now for what is done in each loop: we have to fulfill several
16793 // tasks at the same time, namely several mesh smoothing algorithms
16794 // and mesh regularization, by which we mean that the next mesh
16795 // fulfills several requirements such as no double refinement at
16796 // each face or line, etc.
16797 //
16798 // since doing these things at once seems almost impossible (in the
16799 // first year of this library, they were done in two functions, one
16800 // for refinement and one for coarsening, and most things within
16801 // these were done at once, so the code was rather impossible to
16802 // join into this, only, function), we do them one after each
16803 // other. the order in which we do them is such that the important
16804 // tasks, namely regularization, are done last and the least
16805 // important things are done the first. the following order is
16806 // chosen:
16807 //
16808 // 0/ Only if coarsest_level_1 or patch_level_1 is set: clear all
16809 // coarsen flags on level 1 to avoid level 0 cells being created
16810 // by coarsening. As coarsen flags will never be added, this can
16811 // be done once and for all before the actual loop starts.
16812 //
16813 // 1/ do not coarsen a cell if 'most of the neighbors' will be
16814 // refined after the step. This is to prevent occurrence of
16815 // unrefined islands.
16816 //
16817 // 2/ eliminate refined islands in the interior and at the
16818 // boundary. since they don't do much harm besides increasing the
16819 // number of degrees of freedom, doing this has a rather low
16820 // priority.
16821 //
16822 // 3/ limit the level difference of neighboring cells at each
16823 // vertex.
16824 //
16825 // 4/ eliminate unrefined islands. this has higher priority since
16826 // this diminishes the approximation properties not only of the
16827 // unrefined island, but also of the surrounding patch.
16828 //
16829 // 5/ ensure patch level 1. Then the triangulation consists of
16830 // patches, i.e. of cells that are refined once. It follows that
16831 // if at least one of the children of a cell is or will be
16832 // refined than all children need to be refined. This step only
16833 // sets refinement flags and does not set coarsening flags. If
16834 // the patch_level_1 flag is set, then
16835 // eliminate_unrefined_islands, eliminate_refined_inner_islands
16836 // and eliminate_refined_boundary_islands will be fulfilled
16837 // automatically and do not need to be enforced separately.
16838 //
16839 // 6/ take care of the requirement that no double refinement is done
16840 // at each face
16841 //
16842 // 7/ take care that no double refinement is done at each line in 3d
16843 // or higher dimensions.
16844 //
16845 // 8/ make sure that all children of each cell are either flagged
16846 // for coarsening or none of the children is
16847 //
16848 // For some of these steps, it is known that they interact. Namely,
16849 // it is not possible to guarantee that after step 6 another step 5
16850 // would have no effect; the same holds for the opposite order and
16851 // also when taking into account step 7. however, it is important to
16852 // guarantee that step five or six do not undo something that step 5
16853 // did, and step 7 not something of step 6, otherwise the
16854 // requirements will not be satisfied even if the loop
16855 // terminates. this is accomplished by the fact that steps 5 and 6
16856 // only *add* refinement flags and delete coarsening flags
16857 // (therefore, step 6 can't undo something that step 4 already did),
16858 // and step 7 only deletes coarsening flags, never adds some. step 7
16859 // needs also take care that it won't tag cells for refinement for
16860 // which some neighbors are more refined or will be refined.
16861
16862 //------------------------------------
16863 // STEP 0:
16864 // Only if coarsest_level_1 or patch_level_1 is set: clear all
16865 // coarsen flags on level 1 to avoid level 0 cells being created
16866 // by coarsening.
16867 if (((smooth_grid & coarsest_level_1) || (smooth_grid & patch_level_1)) &&
16868 n_levels() >= 2)
16869 {
16870 for (const auto &cell : active_cell_iterators_on_level(1))
16871 cell->clear_coarsen_flag();
16872 }
16873
16874 bool mesh_changed_in_this_loop = false;
16875 do
16876 {
16877 //------------------------------------
16878 // STEP 1:
16879 // do not coarsen a cell if 'most of the neighbors' will be
16880 // refined after the step. This is to prevent the occurrence
16881 // of unrefined islands. If patch_level_1 is set, this will
16882 // be automatically fulfilled.
16883 if (smooth_grid & do_not_produce_unrefined_islands &&
16884 !(smooth_grid & patch_level_1))
16885 {
16886 for (const auto &cell : cell_iterators())
16887 {
16888 // only do something if this
16889 // cell will be coarsened
16890 if (!cell->is_active() && cell_will_be_coarsened(cell))
16891 possibly_do_not_produce_unrefined_islands<dim, spacedim>(cell);
16892 }
16893 }
16894
16895
16896 //------------------------------------
16897 // STEP 2:
16898 // eliminate refined islands in the interior and at the
16899 // boundary. since they don't do much harm besides increasing
16900 // the number of degrees of freedom, doing this has a rather
16901 // low priority. If patch_level_1 is set, this will be
16902 // automatically fulfilled.
16903 //
16904 // there is one corner case to consider: if this is a
16905 // distributed triangulation, there may be refined islands on
16906 // the boundary of which we own only part (e.g. a single cell
16907 // in the corner of a domain). the rest of the island is
16908 // ghost cells and it *looks* like the area around it
16909 // (artificial cells) are coarser but this is only because
16910 // they may actually be equally fine on other
16911 // processors. it's hard to detect this case but we can do
16912 // the following: only set coarsen flags to remove this
16913 // refined island if all cells we want to set flags on are
16914 // locally owned
16915 if (smooth_grid & (eliminate_refined_inner_islands |
16916 eliminate_refined_boundary_islands) &&
16917 !(smooth_grid & patch_level_1))
16918 {
16919 for (const auto &cell : cell_iterators())
16920 if (!cell->is_active() ||
16921 (cell->is_active() && cell->refine_flag_set() &&
16922 cell->is_locally_owned()))
16923 {
16924 // check whether all children are active, i.e. not
16925 // refined themselves. This is a precondition that the
16926 // children may be coarsened away. If the cell is only
16927 // flagged for refinement, then all future children
16928 // will be active
16929 bool all_children_active = true;
16930 if (!cell->is_active())
16931 for (unsigned int c = 0; c < cell->n_children(); ++c)
16932 if (!cell->child(c)->is_active() ||
16933 cell->child(c)->is_ghost() ||
16934 cell->child(c)->is_artificial())
16935 {
16936 all_children_active = false;
16937 break;
16938 }
16939
16940 if (all_children_active)
16941 {
16942 // count number of refined and unrefined neighbors
16943 // of cell. neighbors on lower levels are counted
16944 // as unrefined since they can only get to the
16945 // same level as this cell by the next refinement
16946 // cycle
16947 unsigned int unrefined_neighbors = 0, total_neighbors = 0;
16948
16949 // Keep track if this cell is at a periodic
16950 // boundary or not. TODO: We do not currently run
16951 // the algorithm for inner islands at a periodic
16952 // boundary (remains to be implemented), but we
16953 // also don't want to consider them
16954 // boundary_island cells as this can interfere
16955 // with 2:1 refinement across periodic faces.
16956 // Instead: just ignore those cells for this
16957 // smoothing operation below.
16958 bool at_periodic_boundary = false;
16959
16960 for (const unsigned int n :
16961 GeometryInfo<dim>::face_indices())
16962 {
16963 const cell_iterator neighbor = cell->neighbor(n);
16964 if (neighbor.state() == IteratorState::valid)
16965 {
16966 ++total_neighbors;
16967
16968 if (!face_will_be_refined_by_neighbor(cell, n))
16969 ++unrefined_neighbors;
16970 }
16971 else if (cell->has_periodic_neighbor(n))
16972 {
16973 ++total_neighbors;
16974 at_periodic_boundary = true;
16975 }
16976 }
16977
16978 // if all neighbors unrefined: mark this cell for
16979 // coarsening or don't refine if marked for that
16980 //
16981 // also do the distinction between the two
16982 // versions of the eliminate_refined_*_islands
16983 // flag
16984 //
16985 // the last check is whether there are any
16986 // neighbors at all. if not so, then we are (e.g.)
16987 // on the coarsest grid with one cell, for which,
16988 // of course, we do not remove the refine flag.
16989 if ((unrefined_neighbors == total_neighbors) &&
16990 ((!cell->at_boundary() &&
16991 (smooth_grid & eliminate_refined_inner_islands)) ||
16992 (cell->at_boundary() && !at_periodic_boundary &&
16993 (smooth_grid &
16994 eliminate_refined_boundary_islands))) &&
16995 (total_neighbors != 0))
16996 {
16997 if (!cell->is_active())
16998 for (unsigned int c = 0; c < cell->n_children(); ++c)
16999 {
17000 cell->child(c)->clear_refine_flag();
17001 cell->child(c)->set_coarsen_flag();
17002 }
17003 else
17004 cell->clear_refine_flag();
17005 }
17006 }
17007 }
17008 }
17009
17010 //------------------------------------
17011 // STEP 3:
17012 // limit the level difference of neighboring cells at each
17013 // vertex.
17014 //
17015 // in case of anisotropic refinement this does not make
17016 // sense. as soon as one cell is anisotropically refined, an
17017 // Assertion is thrown. therefore we can ignore this problem
17018 // later on
17019 if (smooth_grid & limit_level_difference_at_vertices)
17020 {
17021 Assert(!anisotropic_refinement,
17022 ExcMessage("In case of anisotropic refinement the "
17023 "limit_level_difference_at_vertices flag for "
17024 "mesh smoothing must not be set!"));
17025
17026 // store highest level one of the cells adjacent to a vertex
17027 // belongs to
17028 std::vector<int> vertex_level(vertices.size(), 0);
17029 for (const auto &cell : active_cell_iterators())
17030 {
17031 if (cell->refine_flag_set())
17032 for (const unsigned int vertex :
17034 vertex_level[cell->vertex_index(vertex)] =
17035 std::max(vertex_level[cell->vertex_index(vertex)],
17036 cell->level() + 1);
17037 else if (!cell->coarsen_flag_set())
17038 for (const unsigned int vertex :
17040 vertex_level[cell->vertex_index(vertex)] =
17041 std::max(vertex_level[cell->vertex_index(vertex)],
17042 cell->level());
17043 else
17044 {
17045 // if coarsen flag is set then tentatively assume
17046 // that the cell will be coarsened. this isn't
17047 // always true (the coarsen flag could be removed
17048 // again) and so we may make an error here
17049 Assert(cell->coarsen_flag_set(), ExcInternalError());
17050 for (const unsigned int vertex :
17052 vertex_level[cell->vertex_index(vertex)] =
17053 std::max(vertex_level[cell->vertex_index(vertex)],
17054 cell->level() - 1);
17055 }
17056 }
17057
17058
17059 // loop over all cells in reverse order. do so because we
17060 // can then update the vertex levels on the adjacent
17061 // vertices and maybe already flag additional cells in this
17062 // loop
17063 //
17064 // note that not only may we have to add additional
17065 // refinement flags, but we will also have to remove
17066 // coarsening flags on cells adjacent to vertices that will
17067 // see refinement
17068 for (active_cell_iterator cell = last_active(); cell != end(); --cell)
17069 if (cell->refine_flag_set() == false)
17070 {
17071 for (const unsigned int vertex :
17073 if (vertex_level[cell->vertex_index(vertex)] >=
17074 cell->level() + 1)
17075 {
17076 // remove coarsen flag...
17077 cell->clear_coarsen_flag();
17078
17079 // ...and if necessary also refine the current
17080 // cell, at the same time updating the level
17081 // information about vertices
17082 if (vertex_level[cell->vertex_index(vertex)] >
17083 cell->level() + 1)
17084 {
17085 cell->set_refine_flag();
17086
17087 for (const unsigned int v :
17089 vertex_level[cell->vertex_index(v)] =
17090 std::max(vertex_level[cell->vertex_index(v)],
17091 cell->level() + 1);
17092 }
17093
17094 // continue and see whether we may, for example,
17095 // go into the inner'if'
17096 // above based on a
17097 // different vertex
17098 }
17099 }
17100 }
17101
17102 //-----------------------------------
17103 // STEP 4:
17104 // eliminate unrefined islands. this has higher priority
17105 // since this diminishes the approximation properties not
17106 // only of the unrefined island, but also of the surrounding
17107 // patch.
17108 //
17109 // do the loop from finest to coarsest cells since we may
17110 // trigger a cascade by marking cells for refinement which
17111 // may trigger more cells further down below
17112 if (smooth_grid & eliminate_unrefined_islands)
17113 {
17114 for (active_cell_iterator cell = last_active(); cell != end(); --cell)
17115 // only do something if cell is not already flagged for
17116 // (isotropic) refinement
17117 if (cell->refine_flag_set() !=
17119 possibly_refine_unrefined_island<dim, spacedim>(
17120 cell, (smooth_grid & allow_anisotropic_smoothing) != 0);
17121 }
17122
17123 //-------------------------------
17124 // STEP 5:
17125 // ensure patch level 1.
17126 //
17127 // Introduce some terminology:
17128 // - a cell that is refined
17129 // once is a patch of
17130 // level 1 simply called patch.
17131 // - a cell that is globally
17132 // refined twice is called
17133 // a patch of level 2.
17134 // - patch level n says that
17135 // the triangulation consists
17136 // of patches of level n.
17137 // This makes sense only
17138 // if the grid is already at
17139 // least n times globally
17140 // refined.
17141 //
17142 // E.g. from patch level 1 follows: if at least one of the
17143 // children of a cell is or will be refined than enforce all
17144 // children to be refined.
17145
17146 // This step 4 only sets refinement flags and does not set
17147 // coarsening flags.
17148 if (smooth_grid & patch_level_1)
17149 {
17150 // An important assumption (A) is that before calling this
17151 // function the grid was already of patch level 1.
17152
17153 // loop over all cells whose children are all active. (By
17154 // assumption (A) either all or none of the children are
17155 // active). If the refine flag of at least one of the
17156 // children is set then set_refine_flag and
17157 // clear_coarsen_flag of all children.
17158 for (const auto &cell : cell_iterators())
17159 if (!cell->is_active())
17160 {
17161 // ensure the invariant. we can then check whether all
17162 // of its children are further refined or not by
17163 // simply looking at the first child
17164 Assert(cell_is_patch_level_1(cell), ExcInternalError());
17165 if (cell->child(0)->has_children() == true)
17166 continue;
17167
17168 // cell is found to be a patch. combine the refine
17169 // cases of all children
17170 RefinementCase<dim> combined_ref_case =
17172 for (unsigned int i = 0; i < cell->n_children(); ++i)
17173 combined_ref_case =
17174 combined_ref_case | cell->child(i)->refine_flag_set();
17175 if (combined_ref_case != RefinementCase<dim>::no_refinement)
17176 for (unsigned int i = 0; i < cell->n_children(); ++i)
17177 {
17178 cell_iterator child = cell->child(i);
17179
17180 child->clear_coarsen_flag();
17181 child->set_refine_flag(combined_ref_case);
17182 }
17183 }
17184
17185 // The code above dealt with the case where we may get a
17186 // non-patch_level_1 mesh from refinement. Now also deal
17187 // with the case where we could get such a mesh by
17188 // coarsening. Coarsen the children (and remove the
17189 // grandchildren) only if all cell->grandchild(i)
17190 // ->coarsen_flag_set() are set.
17191 //
17192 // for a case where this is a bit tricky, take a look at the
17193 // mesh_smoothing_0[12] testcases
17194 for (const auto &cell : cell_iterators())
17195 {
17196 // check if this cell has active grandchildren. note
17197 // that we know that it is patch_level_1, i.e. if one of
17198 // its children is active then so are all, and it isn't
17199 // going to have any grandchildren at all:
17200 if (cell->is_active() || cell->child(0)->is_active())
17201 continue;
17202
17203 // cell is not active, and so are none of its
17204 // children. check the grandchildren. note that the
17205 // children are also patch_level_1, and so we only ever
17206 // need to check their first child
17207 const unsigned int n_children = cell->n_children();
17208 bool has_active_grandchildren = false;
17209
17210 for (unsigned int i = 0; i < n_children; ++i)
17211 if (cell->child(i)->child(0)->is_active())
17212 {
17213 has_active_grandchildren = true;
17214 break;
17215 }
17216
17217 if (has_active_grandchildren == false)
17218 continue;
17219
17220
17221 // ok, there are active grandchildren. see if either all
17222 // or none of them are flagged for coarsening
17223 unsigned int n_grandchildren = 0;
17224
17225 // count all coarsen flags of the grandchildren.
17226 unsigned int n_coarsen_flags = 0;
17227
17228 // cell is not a patch (of level 1) as it has a
17229 // grandchild. Is cell a patch of level 2?? Therefore:
17230 // find out whether all cell->child(i) are patches
17231 for (unsigned int c = 0; c < n_children; ++c)
17232 {
17233 // get at the child. by assumption (A), and the
17234 // check by which we got here, the child is not
17235 // active
17236 cell_iterator child = cell->child(c);
17237
17238 const unsigned int nn_children = child->n_children();
17239 n_grandchildren += nn_children;
17240
17241 // if child is found to be a patch of active cells
17242 // itself, then add up how many of its children are
17243 // supposed to be coarsened
17244 if (child->child(0)->is_active())
17245 for (unsigned int cc = 0; cc < nn_children; ++cc)
17246 if (child->child(cc)->coarsen_flag_set())
17247 ++n_coarsen_flags;
17248 }
17249
17250 // if not all grandchildren are supposed to be coarsened
17251 // (e.g. because some simply don't have the flag set, or
17252 // because they are not active and therefore cannot
17253 // carry the flag), then remove the coarsen flag from
17254 // all of the active grandchildren. note that there may
17255 // be coarsen flags on the grandgrandchildren -- we
17256 // don't clear them here, but we'll get to them in later
17257 // iterations if necessary
17258 //
17259 // there is nothing we have to do if no coarsen flags
17260 // have been set at all
17261 if ((n_coarsen_flags != n_grandchildren) && (n_coarsen_flags > 0))
17262 for (unsigned int c = 0; c < n_children; ++c)
17263 {
17264 const cell_iterator child = cell->child(c);
17265 if (child->child(0)->is_active())
17266 for (unsigned int cc = 0; cc < child->n_children(); ++cc)
17267 child->child(cc)->clear_coarsen_flag();
17268 }
17269 }
17270 }
17271
17272 //--------------------------------
17273 //
17274 // at the boundary we could end up with cells with negative
17275 // volume or at least with a part, that is negative, if the
17276 // cell is refined anisotropically. we have to check, whether
17277 // that can happen
17278 this->policy->prevent_distorted_boundary_cells(*this);
17279
17280 //-------------------------------
17281 // STEP 6:
17282 // take care of the requirement that no
17283 // double refinement is done at each face
17284 //
17285 // in case of anisotropic refinement it is only likely, but
17286 // not sure, that the cells, which are more refined along a
17287 // certain face common to two cells are on a higher
17288 // level. therefore we cannot be sure, that the requirement
17289 // of no double refinement is fulfilled after a single pass
17290 // of the following actions. We could just wait for the next
17291 // global loop. when this function terminates, the
17292 // requirement will be fulfilled. However, it might be faster
17293 // to insert an inner loop here.
17294 bool changed = true;
17295 while (changed)
17296 {
17297 changed = false;
17298 active_cell_iterator cell = last_active(), endc = end();
17299
17300 for (; cell != endc; --cell)
17301 if (cell->refine_flag_set())
17302 {
17303 // loop over neighbors of cell
17304 for (const auto i : cell->face_indices())
17305 {
17306 // only do something if the face is not at the
17307 // boundary and if the face will be refined with
17308 // the RefineCase currently flagged for
17309 const bool has_periodic_neighbor =
17310 cell->has_periodic_neighbor(i);
17311 const bool has_neighbor_or_periodic_neighbor =
17312 !cell->at_boundary(i) || has_periodic_neighbor;
17313 if (has_neighbor_or_periodic_neighbor &&
17315 cell->refine_flag_set(), i) !=
17317 {
17318 // 1) if the neighbor has children: nothing to
17319 // worry about. 2) if the neighbor is active
17320 // and a coarser one, ensure, that its
17321 // refine_flag is set 3) if the neighbor is
17322 // active and as refined along the face as our
17323 // current cell, make sure, that no
17324 // coarsen_flag is set. if we remove the
17325 // coarsen flag of our neighbor,
17326 // fix_coarsen_flags() makes sure, that the
17327 // mother cell will not be coarsened
17328 if (cell->neighbor_or_periodic_neighbor(i)->is_active())
17329 {
17330 if ((!has_periodic_neighbor &&
17331 cell->neighbor_is_coarser(i)) ||
17332 (has_periodic_neighbor &&
17333 cell->periodic_neighbor_is_coarser(i)))
17334 {
17335 if (cell->neighbor_or_periodic_neighbor(i)
17336 ->coarsen_flag_set())
17337 cell->neighbor_or_periodic_neighbor(i)
17338 ->clear_coarsen_flag();
17339 // we'll set the refine flag for this
17340 // neighbor below. we note, that we
17341 // have changed something by setting
17342 // the changed flag to true. We do not
17343 // need to do so, if we just removed
17344 // the coarsen flag, as the changed
17345 // flag only indicates the need to
17346 // re-run the inner loop. however, we
17347 // only loop over cells flagged for
17348 // refinement here, so nothing to
17349 // worry about if we remove coarsen
17350 // flags
17351
17352 if (dim == 2)
17353 {
17354 if (smooth_grid &
17355 allow_anisotropic_smoothing)
17356 changed =
17357 has_periodic_neighbor ?
17358 cell->periodic_neighbor(i)
17359 ->flag_for_face_refinement(
17360 cell
17361 ->periodic_neighbor_of_coarser_periodic_neighbor(
17362 i)
17363 .first,
17365 cell->neighbor(i)
17366 ->flag_for_face_refinement(
17367 cell
17368 ->neighbor_of_coarser_neighbor(
17369 i)
17370 .first,
17372 else
17373 {
17374 if (!cell
17375 ->neighbor_or_periodic_neighbor(
17376 i)
17377 ->refine_flag_set())
17378 changed = true;
17379 cell->neighbor_or_periodic_neighbor(i)
17380 ->set_refine_flag();
17381 }
17382 }
17383 else // i.e. if (dim==3)
17384 {
17385 // ugly situations might arise here,
17386 // consider the following situation, which
17387 // shows neighboring cells at the common
17388 // face, where the upper right element is
17389 // coarser at the given face. Now the upper
17390 // child element of the lower left wants to
17391 // refine according to cut_z, such that
17392 // there is a 'horizontal' refinement of the
17393 // face marked with #####
17394 //
17395 // / /
17396 // / /
17397 // *---------------*
17398 // | |
17399 // | |
17400 // | |
17401 // | |
17402 // | |
17403 // | | /
17404 // | |/
17405 // *---------------*
17406 //
17407 //
17408 // *---------------*
17409 // /| /|
17410 // / | ##### / |
17411 // | |
17412 // *---------------*
17413 // /| /|
17414 // / | / |
17415 // | |
17416 // *---------------*
17417 // / /
17418 // / /
17419 //
17420 // this introduces too many hanging nodes
17421 // and the neighboring (coarser) cell (upper
17422 // right) has to be refined. If it is only
17423 // refined according to cut_z, then
17424 // everything is ok:
17425 //
17426 // / /
17427 // / /
17428 // *---------------*
17429 // | |
17430 // | | /
17431 // | |/
17432 // *---------------*
17433 // | |
17434 // | | /
17435 // | |/
17436 // *---------------*
17437 //
17438 //
17439 // *---------------*
17440 // /| /|
17441 // / *---------------*
17442 // /| /|
17443 // *---------------*
17444 // /| /|
17445 // / | / |
17446 // | |
17447 // *---------------*
17448 // / /
17449 // / /
17450 //
17451 // if however the cell wants to refine
17452 // itself in an other way, or if we disallow
17453 // anisotropic smoothing, then simply
17454 // refining the neighbor isotropically is
17455 // not going to work, since this introduces
17456 // a refinement of face ##### with both
17457 // cut_x and cut_y, which is not possible:
17458 //
17459 // / / /
17460 // / / /
17461 // *-------*-------*
17462 // | | |
17463 // | | | /
17464 // | | |/
17465 // *-------*-------*
17466 // | | |
17467 // | | | /
17468 // | | |/
17469 // *-------*-------*
17470 //
17471 //
17472 // *---------------*
17473 // /| /|
17474 // / *---------------*
17475 // /| /|
17476 // *---------------*
17477 // /| /|
17478 // / | / |
17479 // | |
17480 // *---------------*
17481 // / /
17482 // / /
17483 //
17484 // thus, in this case we also need to refine
17485 // our current cell in the new direction:
17486 //
17487 // / / /
17488 // / / /
17489 // *-------*-------*
17490 // | | |
17491 // | | | /
17492 // | | |/
17493 // *-------*-------*
17494 // | | |
17495 // | | | /
17496 // | | |/
17497 // *-------*-------*
17498 //
17499 //
17500 // *-------*-------*
17501 // /| /| /|
17502 // / *-------*-------*
17503 // /| /| /|
17504 // *-------*-------*
17505 // /| / /|
17506 // / | / |
17507 // | |
17508 // *---------------*
17509 // / /
17510 // / /
17511
17512 std::pair<unsigned int, unsigned int>
17513 nb_indices =
17514 has_periodic_neighbor ?
17515 cell
17516 ->periodic_neighbor_of_coarser_periodic_neighbor(
17517 i) :
17518 cell->neighbor_of_coarser_neighbor(i);
17519 unsigned int refined_along_x = 0,
17520 refined_along_y = 0,
17521 to_be_refined_along_x = 0,
17522 to_be_refined_along_y = 0;
17523
17524 const int this_face_index =
17525 cell->face_index(i);
17526
17527 // step 1: detect, along which axis the face
17528 // is currently refined
17529
17530 // first, we need an iterator pointing to
17531 // the parent face. This requires a slight
17532 // detour in case the neighbor is behind a
17533 // periodic face.
17534 const auto parent_face = [&]() {
17535 if (has_periodic_neighbor)
17536 {
17537 const auto neighbor =
17538 cell->periodic_neighbor(i);
17539 const auto parent_face_no =
17540 neighbor
17541 ->periodic_neighbor_of_periodic_neighbor(
17542 nb_indices.first);
17543 auto parent =
17544 neighbor->periodic_neighbor(
17545 nb_indices.first);
17546 return parent->face(parent_face_no);
17547 }
17548 else
17549 return cell->neighbor(i)->face(
17550 nb_indices.first);
17551 }();
17552
17553 if ((this_face_index ==
17554 parent_face->child_index(0)) ||
17555 (this_face_index ==
17556 parent_face->child_index(1)))
17557 {
17558 // this might be an
17559 // anisotropic child. get the
17560 // face refine case of the
17561 // neighbors face and count
17562 // refinements in x and y
17563 // direction.
17564 RefinementCase<dim - 1> frc =
17565 parent_face->refinement_case();
17567 ++refined_along_x;
17569 ++refined_along_y;
17570 }
17571 else
17572 // this has to be an isotropic
17573 // child
17574 {
17575 ++refined_along_x;
17576 ++refined_along_y;
17577 }
17578 // step 2: detect, along which axis the face
17579 // has to be refined given the current
17580 // refine flag
17581 RefinementCase<dim - 1> flagged_frc =
17583 cell->refine_flag_set(),
17584 i,
17585 cell->face_orientation(i),
17586 cell->face_flip(i),
17587 cell->face_rotation(i));
17588 if (flagged_frc &
17590 ++to_be_refined_along_x;
17591 if (flagged_frc &
17593 ++to_be_refined_along_y;
17594
17595 // step 3: set the refine flag of the
17596 // (coarser and active) neighbor.
17597 if ((smooth_grid &
17598 allow_anisotropic_smoothing) ||
17599 cell->neighbor_or_periodic_neighbor(i)
17600 ->refine_flag_set())
17601 {
17602 if (refined_along_x +
17603 to_be_refined_along_x >
17604 1)
17605 changed |=
17606 cell
17607 ->neighbor_or_periodic_neighbor(i)
17608 ->flag_for_face_refinement(
17609 nb_indices.first,
17610 RefinementCase<dim -
17611 1>::cut_axis(0));
17612 if (refined_along_y +
17613 to_be_refined_along_y >
17614 1)
17615 changed |=
17616 cell
17617 ->neighbor_or_periodic_neighbor(i)
17618 ->flag_for_face_refinement(
17619 nb_indices.first,
17620 RefinementCase<dim -
17621 1>::cut_axis(1));
17622 }
17623 else
17624 {
17625 if (cell
17626 ->neighbor_or_periodic_neighbor(i)
17627 ->refine_flag_set() !=
17629 dim>::isotropic_refinement)
17630 changed = true;
17631 cell->neighbor_or_periodic_neighbor(i)
17632 ->set_refine_flag();
17633 }
17634
17635 // step 4: if necessary (see above) add to
17636 // the refine flag of the current cell
17637 cell_iterator nb =
17638 cell->neighbor_or_periodic_neighbor(i);
17639 RefinementCase<dim - 1> nb_frc =
17641 nb->refine_flag_set(),
17642 nb_indices.first,
17643 nb->face_orientation(nb_indices.first),
17644 nb->face_flip(nb_indices.first),
17645 nb->face_rotation(nb_indices.first));
17646 if ((nb_frc & RefinementCase<dim>::cut_x) &&
17647 !((refined_along_x != 0u) ||
17648 (to_be_refined_along_x != 0u)))
17649 changed |= cell->flag_for_face_refinement(
17650 i,
17652 if ((nb_frc & RefinementCase<dim>::cut_y) &&
17653 !((refined_along_y != 0u) ||
17654 (to_be_refined_along_y != 0u)))
17655 changed |= cell->flag_for_face_refinement(
17656 i,
17658 }
17659 } // if neighbor is coarser
17660 else // -> now the neighbor is not coarser
17661 {
17662 cell->neighbor_or_periodic_neighbor(i)
17663 ->clear_coarsen_flag();
17664 const unsigned int nb_nb =
17665 has_periodic_neighbor ?
17666 cell
17667 ->periodic_neighbor_of_periodic_neighbor(
17668 i) :
17669 cell->neighbor_of_neighbor(i);
17670 const cell_iterator neighbor =
17671 cell->neighbor_or_periodic_neighbor(i);
17672 RefinementCase<dim - 1> face_ref_case =
17674 neighbor->refine_flag_set(),
17675 nb_nb,
17676 neighbor->face_orientation(nb_nb),
17677 neighbor->face_flip(nb_nb),
17678 neighbor->face_rotation(nb_nb));
17679 RefinementCase<dim - 1> needed_face_ref_case =
17681 cell->refine_flag_set(),
17682 i,
17683 cell->face_orientation(i),
17684 cell->face_flip(i),
17685 cell->face_rotation(i));
17686 // if the neighbor wants to refine the
17687 // face with cut_x and we want cut_y
17688 // or vice versa, we have to refine
17689 // isotropically at the given face
17690 if ((face_ref_case ==
17692 needed_face_ref_case ==
17694 (face_ref_case ==
17696 needed_face_ref_case ==
17698 {
17699 changed = cell->flag_for_face_refinement(
17700 i, face_ref_case);
17701 neighbor->flag_for_face_refinement(
17702 nb_nb, needed_face_ref_case);
17703 }
17704 }
17705 }
17706 else //-> the neighbor is not active
17707 {
17708 RefinementCase<dim - 1>
17709 face_ref_case = cell->face(i)->refinement_case(),
17710 needed_face_ref_case =
17712 cell->refine_flag_set(),
17713 i,
17714 cell->face_orientation(i),
17715 cell->face_flip(i),
17716 cell->face_rotation(i));
17717 // if the face is refined with cut_x and
17718 // we want cut_y or vice versa, we have to
17719 // refine isotropically at the given face
17720 if ((face_ref_case == RefinementCase<dim>::cut_x &&
17721 needed_face_ref_case ==
17723 (face_ref_case == RefinementCase<dim>::cut_y &&
17724 needed_face_ref_case ==
17726 changed =
17727 cell->flag_for_face_refinement(i,
17728 face_ref_case);
17729 }
17730 }
17731 }
17732 }
17733 }
17734
17735 //------------------------------------
17736 // STEP 7:
17737 // take care that no double refinement is done at each line in 3d or
17738 // higher dimensions.
17739 this->policy->prepare_refinement_dim_dependent(*this);
17740
17741 //------------------------------------
17742 // STEP 8:
17743 // make sure that all children of each cell are either flagged for
17744 // coarsening or none of the children is
17745 fix_coarsen_flags();
17746
17747 // get the refinement and coarsening flags
17748 auto coarsen_flags_after_loop =
17749 internal::extract_raw_coarsen_flags(levels);
17750 auto refine_flags_after_loop = internal::extract_raw_refine_flags(levels);
17751
17752 // find out whether something was changed in this loop
17753 mesh_changed_in_this_loop =
17754 ((coarsen_flags_before_loop != coarsen_flags_after_loop) ||
17755 (refine_flags_before_loop != refine_flags_after_loop));
17756
17757 // set the flags for the next loop already
17758 coarsen_flags_before_loop.swap(coarsen_flags_after_loop);
17759 refine_flags_before_loop.swap(refine_flags_after_loop);
17760 }
17761 while (mesh_changed_in_this_loop);
17762
17763
17764 // find out whether something was really changed in this
17765 // function. Note that @p{..._flags_before_loop} represents the state
17766 // after the last loop, i.e., the present state
17767 return ((coarsen_flags_before != coarsen_flags_before_loop) ||
17768 (refine_flags_before != refine_flags_before_loop));
17769}
17770
17771
17772
17773template <int dim, int spacedim>
17776 const unsigned int magic_number1,
17777 const std::vector<bool> &v,
17778 const unsigned int magic_number2,
17779 std::ostream &out)
17780{
17781 const unsigned int N = v.size();
17782 unsigned char *flags = new unsigned char[N / 8 + 1];
17783 for (unsigned int i = 0; i < N / 8 + 1; ++i)
17784 flags[i] = 0;
17785
17786 for (unsigned int position = 0; position < N; ++position)
17787 flags[position / 8] |= (v[position] ? (1 << (position % 8)) : 0);
17788
17789 AssertThrow(out.fail() == false, ExcIO());
17790
17791 // format:
17792 // 0. magic number
17793 // 1. number of flags
17794 // 2. the flags
17795 // 3. magic number
17796 out << magic_number1 << ' ' << N << std::endl;
17797 for (unsigned int i = 0; i < N / 8 + 1; ++i)
17798 out << static_cast<unsigned int>(flags[i]) << ' ';
17799
17800 out << std::endl << magic_number2 << std::endl;
17801
17802 delete[] flags;
17803
17804 AssertThrow(out.fail() == false, ExcIO());
17805}
17806
17807
17808template <int dim, int spacedim>
17811 const unsigned int magic_number1,
17812 std::vector<bool> &v,
17813 const unsigned int magic_number2,
17814 std::istream &in)
17815{
17816 AssertThrow(in.fail() == false, ExcIO());
17817
17818 unsigned int magic_number;
17819 in >> magic_number;
17820 AssertThrow(magic_number == magic_number1, ExcGridReadError());
17821
17822 unsigned int N;
17823 in >> N;
17824 v.resize(N);
17825
17826 unsigned char *flags = new unsigned char[N / 8 + 1];
17827 unsigned short int tmp;
17828 for (unsigned int i = 0; i < N / 8 + 1; ++i)
17829 {
17830 in >> tmp;
17831 flags[i] = tmp;
17832 }
17833
17834 for (unsigned int position = 0; position != N; ++position)
17835 v[position] = ((flags[position / 8] & (1 << (position % 8))) != 0);
17836
17837 in >> magic_number;
17838 AssertThrow(magic_number == magic_number2, ExcGridReadError());
17839
17840 delete[] flags;
17841
17842 AssertThrow(in.fail() == false, ExcIO());
17843}
17844
17845
17846
17847template <int dim, int spacedim>
17850{
17851 std::size_t mem = 0;
17852 mem += sizeof(MeshSmoothing);
17853 mem += MemoryConsumption::memory_consumption(reference_cells);
17854 mem += MemoryConsumption::memory_consumption(periodic_face_pairs_level_0);
17856 for (const auto &level : levels)
17859 mem += MemoryConsumption::memory_consumption(vertices_used);
17860 mem += sizeof(manifolds);
17861 mem += sizeof(smooth_grid);
17862 mem += MemoryConsumption::memory_consumption(number_cache);
17863 mem += sizeof(faces);
17864 if (faces)
17866
17867 return mem;
17868}
17869
17870
17871
17872template <int dim, int spacedim>
17875 default;
17876
17877#endif
17878
17879// explicit instantiations
17880#include "tria.inst"
17881
ArrayView< typename std::remove_reference< typename std::iterator_traits< Iterator >::reference >::type, 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
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
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
Subscriptor & operator=(const Subscriptor &)
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
typename IteratorSelector::raw_line_iterator raw_line_iterator
Definition tria.h:4088
active_vertex_iterator begin_active_vertex() const
virtual MPI_Comm get_communicator() 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:4464
virtual void clear()
bool anisotropic_refinement
Definition tria.h:4476
std::map< std::pair< cell_iterator, unsigned int >, std::pair< std::pair< cell_iterator, unsigned int >, unsigned char > > periodic_face_map
Definition tria.h:4073
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:4534
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
std::vector< typename internal::CellAttachedDataSerializer< dim, spacedim >::cell_relation_t > local_cell_relations
Definition tria.h:3906
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()
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:4459
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:4483
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:4511
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:4004
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:4453
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:4089
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:4494
void save_user_indices_hex(std::vector< unsigned int > &v) const
DistortedCellList execute_refinement()
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)
cell_iterator end() const
virtual bool has_hanging_nodes() const
std::vector< GridTools::PeriodicFacePair< cell_iterator > > periodic_face_pairs_level_0
Definition tria.h:4065
unsigned int n_raw_cells(const unsigned int level) const
bool contains_cell(const CellId &cell_id) const
internal::CellAttachedData< dim, spacedim > cell_attached_data
Definition tria.h:3856
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 save_attached_data(const unsigned int global_first_cell, const unsigned int global_num_cells, const std::string &filename) 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()
const std::vector< bool > & get_used_vertices() const
typename IteratorSelector::raw_hex_iterator raw_hex_iterator
Definition tria.h:4090
std::map< types::manifold_id, std::unique_ptr< const Manifold< dim, spacedim > > > manifolds
Definition tria.h:4471
MeshSmoothing smooth_grid
Definition tria.h:3998
void save_refine_flags(std::ostream &out) const
std::unique_ptr< ::internal::TriangulationImplementation::Policy< dim, spacedim > > policy
Definition tria.h:4056
Triangulation< dim, spacedim > & get_triangulation()
void save_user_flags_quad(std::ostream &out) const
Signals signals
Definition tria.h:2509
internal::CellAttachedDataSerializer< dim, spacedim > data_serializer
Definition tria.h:3908
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:4445
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()
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 &filename, const unsigned int n_attached_deserialize_fixed, const unsigned int n_attached_deserialize_variable)
void save(const unsigned int global_first_cell, const unsigned int global_num_cells, const std::string &filename, const MPI_Comm &mpi_communicator) const
Definition tria.cc:672
void pack_data(const std::vector< cell_relation_t > &cell_relations, const std::vector< typename internal::CellAttachedData< dim, spacedim >::pack_callback_t > &pack_callbacks_fixed, const std::vector< typename internal::CellAttachedData< dim, spacedim >::pack_callback_t > &pack_callbacks_variable, const MPI_Comm &mpi_communicator)
Definition tria.cc:141
typename std::pair< cell_iterator, CellStatus > cell_relation_t
Definition tria.h:387
void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation) override
Definition tria.cc:2549
void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation) override
Definition tria.cc:2556
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:2532
void update_neighbors(Triangulation< dim, spacedim > &tria) override
Definition tria.cc:2526
bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell) override
Definition tria.cc:2563
Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells) override
Definition tria.cc:2542
std::unique_ptr< Policy< dim, spacedim > > clone() override
Definition tria.cc:2571
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:502
#define DEAL_II_CXX20_REQUIRES(condition)
Definition config.h:177
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:503
Point< 3 > vertices[4]
Point< 2 > second
Definition grid_out.cc:4624
Point< 2 > first
Definition grid_out.cc:4623
unsigned int level
Definition grid_out.cc:4626
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:539
#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:562
#define DeclException1(Exception1, type1, outsequence)
Definition exceptions.h:516
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:611
#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:1685
typename IteratorSelector::active_quad_iterator active_quad_iterator
Definition tria.h:1676
typename IteratorSelector::active_hex_iterator active_hex_iterator
Definition tria.h:1696
typename IteratorSelector::quad_iterator quad_iterator
Definition tria.h:1661
typename IteratorSelector::line_iterator line_iterator
Definition tria.h:1637
TriaIterator< CellAccessor< dim, spacedim > > cell_iterator
Definition tria.h:1550
typename IteratorSelector::active_line_iterator active_line_iterator
Definition tria.h:1652
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:294
void create_triangulation(Triangulation< dim, dim > &tria, const AdditionalData &additional_data=AdditionalData())
spacedim MeshType< dim - 1, spacedim > const std::set< types::boundary_id > & boundary_ids
void reference_cell(Triangulation< dim, spacedim > &tria, const ReferenceCell &reference_cell)
spacedim const Point< spacedim > & p
Definition grid_tools.h:990
const Triangulation< dim, spacedim > & tria
double diameter(const Triangulation< dim, spacedim > &tria)
if(marked_vertices.size() !=0) for(auto it
for(unsigned int j=best_vertex+1;j< vertices.size();++j) if(vertices_to_use[j])
@ 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
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:14962
const Manifold< dim, spacedim > & get_default_flat_manifold()
Definition tria.cc:12132
unsigned int n_cells(const internal::TriangulationImplementation::NumberCache< 1 > &c)
Definition tria.cc:14955
void reserve_space(TriaFaces &tria_faces, const unsigned int new_quads_in_pairs, const unsigned int new_quads_single)
Definition tria.cc:1995
void monitor_memory(const TriaLevel &tria_level, const unsigned int true_dimension)
Definition tria.cc:2187
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
const InputIterator OutputIterator out
Definition parallel.h:167
const Iterator const std_cxx20::type_identity_t< Iterator > & end
Definition parallel.h:610
const Iterator & begin
Definition parallel.h:609
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:1731
boost::signals2::signal< void(const Triangulation< dim, spacedim > &destination_tria)> copy
Definition tria.h:2355
std::vector< pack_callback_t > pack_callbacks_variable
Definition tria.h:362
std::vector< pack_callback_t > pack_callbacks_fixed
Definition tria.h:361
unsigned int n_attached_data_sets
Definition tria.h:346
static void update_neighbors(Triangulation< 1, spacedim > &)
Definition tria.cc:12009
static Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:12094
static bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &)
Definition tria.cc:12120
static void update_neighbors(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:12013
static 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)
Definition tria.cc:12079
static void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:12112
static void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:12103
static void reserve_space_(TriaObjects &obj, const unsigned int size)
Definition tria.cc:3615
static void reserve_space_(TriaFaces &faces, const unsigned structdim, const unsigned int size)
Definition tria.cc:3555
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:2777
static void prevent_distorted_boundary_cells(Triangulation< 1, spacedim > &)
Definition tria.cc:11616
static void update_neighbors(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:3005
static void prepare_refinement_dim_dependent(const Triangulation< dim, spacedim > &)
Definition tria.cc:11704
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:3910
static void reserve_space_(TriaLevel &level, const unsigned int spacedim, const unsigned int size, const bool orientation_needed)
Definition tria.cc:3577
static void update_neighbors(Triangulation< 1, spacedim > &)
Definition tria.cc:2999
static Triangulation< 3, spacedim >::DistortedCellList execute_refinement(Triangulation< 3, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:7255
static Triangulation< dim, spacedim >::DistortedCellList execute_refinement_isotropic(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:4905
static void compute_number_cache(const Triangulation< dim, spacedim > &triangulation, const unsigned int level_objects, internal::TriangulationImplementation::NumberCache< dim > &number_cache)
Definition tria.cc:2977
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:4538
static void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:11623
static bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell)
Definition tria.cc:11937
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:2884
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:3668
static void prepare_refinement_dim_dependent(Triangulation< 3, spacedim > &triangulation)
Definition tria.cc:11714
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:3772
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:2689
static Triangulation< 1, spacedim >::DistortedCellList execute_refinement(Triangulation< 1, spacedim > &triangulation, const bool)
Definition tria.cc:5364
static Triangulation< 3, spacedim >::DistortedCellList execute_refinement_isotropic(Triangulation< 3, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:5909
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:3184
static Triangulation< 2, spacedim >::DistortedCellList execute_refinement(Triangulation< 2, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:5599
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:3447
std::vector< std::vector< CellData< dim > > > cell_infos