deal.II version GIT relicensing-2165-gc91f007519 2024-11-20 01:40:00+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
tria.cc
Go to the documentation of this file.
1// ------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: LGPL-2.1-or-later
4// Copyright (C) 1999 - 2024 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Part of the source code is dual licensed under Apache-2.0 WITH
9// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
10// governing the source code and code contributions can be found in
11// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
12//
13// ------------------------------------------------------------------------
14
15
18#include <deal.II/base/mpi.templates.h>
23
26
31#include <deal.II/grid/tria.h>
36
37#include <boost/archive/text_iarchive.hpp>
38#include <boost/archive/text_oarchive.hpp>
39
40#include <algorithm>
41#include <array>
42#include <cmath>
43#include <cstdint>
44#include <fstream>
45#include <functional>
46#include <limits>
47#include <list>
48#include <map>
49#include <memory>
50#include <numeric>
51
52
54
55
56namespace internal
57{
58 namespace TriangulationImplementation
59 {
61 : n_levels(0)
62 , n_lines(0)
63 , n_active_lines(0)
64 // all other fields are
65 // default constructed
66 {}
67
68
69
70 std::size_t
72 {
73 std::size_t mem =
78 MemoryConsumption::memory_consumption(n_active_lines_level);
79
80 if (active_cell_index_partitioner)
81 mem += active_cell_index_partitioner->memory_consumption();
82
83 for (const auto &partitioner : level_cell_index_partitioners)
84 if (partitioner)
85 mem += partitioner->memory_consumption();
86
87 return mem;
88 }
89
90
92 : n_quads(0)
93 , n_active_quads(0)
94 // all other fields are
95 // default constructed
96 {}
97
98
99
100 std::size_t
109
110
111
113 : n_hexes(0)
114 , n_active_hexes(0)
115 // all other fields are
116 // default constructed
117 {}
118
119
120
121 std::size_t
130 } // namespace TriangulationImplementation
131
132
133 template <int dim, int spacedim>
136 : variable_size_data_stored(false)
137 {}
138
139
140 template <int dim, int spacedim>
142 void CellAttachedDataSerializer<dim, spacedim>::pack_data(
143 const std::vector<cell_relation_t> &cell_relations,
144 const std::vector<
145 typename internal::CellAttachedData<dim, spacedim>::pack_callback_t>
146 &pack_callbacks_fixed,
147 const std::vector<
148 typename internal::CellAttachedData<dim, spacedim>::pack_callback_t>
149 &pack_callbacks_variable,
150 const MPI_Comm &mpi_communicator)
151 {
152 Assert(src_data_fixed.empty(),
153 ExcMessage("Previously packed data has not been released yet!"));
154 Assert(src_sizes_variable.empty(), ExcInternalError());
155
156 const unsigned int n_callbacks_fixed = pack_callbacks_fixed.size();
157 const unsigned int n_callbacks_variable = pack_callbacks_variable.size();
158
159 // Store information that we packed variable size data in
160 // a member variable for later.
161 variable_size_data_stored = (n_callbacks_variable > 0);
162
163 // If variable transfer is scheduled, we will store the data size that
164 // each variable size callback function writes in this auxiliary
165 // container. The information will be stored by each cell in this vector
166 // temporarily.
167 std::vector<unsigned int> cell_sizes_variable_cumulative(
168 n_callbacks_variable);
169
170 // Prepare the buffer structure, in which each callback function will
171 // store its data for each active cell.
172 // The outmost shell in this container construct corresponds to the
173 // data packed per cell. The next layer resembles the data that
174 // each callback function packs on the corresponding cell. These
175 // buffers are chains of chars stored in an std::vector<char>.
176 // A visualisation of the data structure:
177 /* clang-format off */
178 // | cell_1 | | cell_2 | ...
179 // || callback_1 || callback_2 |...| || callback_1 || callback_2 |...| ...
180 // |||char|char|...|||char|char|...|...| |||char|char|...|||char|char|...|...| ...
181 /* clang-format on */
182 std::vector<std::vector<std::vector<char>>> packed_fixed_size_data(
183 cell_relations.size());
184 std::vector<std::vector<std::vector<char>>> packed_variable_size_data(
185 variable_size_data_stored ? cell_relations.size() : 0);
186
187 //
188 // --------- Pack data for fixed and variable size transfer ---------
189 //
190 // Iterate over all cells, call all callback functions on each cell,
191 // and store their data in the corresponding buffer scope.
192 {
193 auto cell_rel_it = cell_relations.cbegin();
194 auto data_cell_fixed_it = packed_fixed_size_data.begin();
195 auto data_cell_variable_it = packed_variable_size_data.begin();
196 for (; cell_rel_it != cell_relations.cend(); ++cell_rel_it)
197 {
198 const auto &dealii_cell = cell_rel_it->first;
199 const auto &cell_status = cell_rel_it->second;
200
201 // Assertions about the tree structure.
202 switch (cell_status)
203 {
206 // double check the condition that we will only ever attach
207 // data to active cells when we get here
208 Assert(dealii_cell->is_active(), ExcInternalError());
209 break;
210
212 // double check the condition that we will only ever attach
213 // data to cells with children when we get here. however, we
214 // can only tolerate one level of coarsening at a time, so
215 // check that the children are all active
216 Assert(dealii_cell->is_active() == false, ExcInternalError());
217 for (unsigned int c = 0; c < dealii_cell->n_children(); ++c)
218 Assert(dealii_cell->child(c)->is_active(),
220 break;
221
223 // do nothing on invalid cells
224 break;
225
226 default:
228 break;
229 }
230
231 // Reserve memory corresponding to the number of callback
232 // functions that will be called.
233 // If variable size transfer is scheduled, we need to leave
234 // room for an array that holds information about how many
235 // bytes each of the variable size callback functions will
236 // write.
237 // On cells flagged with CellStatus::cell_invalid, only its CellStatus
238 // will be stored.
239 const unsigned int n_fixed_size_data_sets_on_cell =
240 1 + ((cell_status == CellStatus::cell_invalid) ?
241 0 :
242 ((variable_size_data_stored ? 1 : 0) + n_callbacks_fixed));
243 data_cell_fixed_it->resize(n_fixed_size_data_sets_on_cell);
244
245 // We continue with packing all data on this specific cell.
246 auto data_fixed_it = data_cell_fixed_it->begin();
247
248 // First, we pack the CellStatus information.
249 // to get consistent data sizes on each cell for the fixed size
250 // transfer, we won't allow compression
251 *data_fixed_it =
252 Utilities::pack(cell_status, /*allow_compression=*/false);
253 ++data_fixed_it;
254
255 // Proceed with all registered callback functions.
256 // Skip cells with the CellStatus::cell_invalid flag.
257 if (cell_status != CellStatus::cell_invalid)
258 {
259 // Pack fixed size data.
260 for (auto callback_it = pack_callbacks_fixed.cbegin();
261 callback_it != pack_callbacks_fixed.cend();
262 ++callback_it, ++data_fixed_it)
263 {
264 *data_fixed_it = (*callback_it)(dealii_cell, cell_status);
265 }
266
267 // Pack variable size data.
268 // If we store variable size data, we need to transfer
269 // the sizes of each corresponding callback function
270 // via fixed size transfer as well.
271 if (variable_size_data_stored)
272 {
273 const unsigned int n_variable_size_data_sets_on_cell =
274 ((cell_status == CellStatus::cell_invalid) ?
275 0 :
276 n_callbacks_variable);
277 data_cell_variable_it->resize(
278 n_variable_size_data_sets_on_cell);
279
280 auto callback_it = pack_callbacks_variable.cbegin();
281 auto data_variable_it = data_cell_variable_it->begin();
282 auto sizes_variable_it =
283 cell_sizes_variable_cumulative.begin();
284 for (; callback_it != pack_callbacks_variable.cend();
285 ++callback_it, ++data_variable_it, ++sizes_variable_it)
286 {
287 *data_variable_it =
288 (*callback_it)(dealii_cell, cell_status);
289
290 // Store data sizes for each callback function first.
291 // Make it cumulative below.
292 *sizes_variable_it = data_variable_it->size();
293 }
294
295 // Turn size vector into its cumulative representation.
296 std::partial_sum(cell_sizes_variable_cumulative.begin(),
297 cell_sizes_variable_cumulative.end(),
298 cell_sizes_variable_cumulative.begin());
299
300 // Serialize cumulative variable size vector
301 // value-by-value. This way we can circumvent the overhead
302 // of storing the container object as a whole, since we
303 // know its size by the number of registered callback
304 // functions.
305 data_fixed_it->resize(n_callbacks_variable *
306 sizeof(unsigned int));
307 for (unsigned int i = 0; i < n_callbacks_variable; ++i)
308 std::memcpy(&(data_fixed_it->at(i * sizeof(unsigned int))),
309 &(cell_sizes_variable_cumulative.at(i)),
310 sizeof(unsigned int));
311
312 ++data_fixed_it;
313 }
314
315 // Double check that we packed everything we wanted
316 // in the fixed size buffers.
317 Assert(data_fixed_it == data_cell_fixed_it->end(),
319 }
320
321 ++data_cell_fixed_it;
322
323 // Increment the variable size data iterator
324 // only if we actually pack this kind of data
325 // to avoid getting out of bounds.
326 if (variable_size_data_stored)
327 ++data_cell_variable_it;
328 } // loop over cell_relations
329 }
330
331 //
332 // ----------- Gather data sizes for fixed size transfer ------------
333 //
334 // Generate a vector which stores the sizes of each callback function,
335 // including the packed CellStatus transfer.
336 // Find the very first cell that we wrote to with all callback
337 // functions (i.e. a cell that was not flagged with
338 // CellStatus::cell_invalid) and store the sizes of each buffer.
339 //
340 // To deal with the case that at least one of the processors does not
341 // own any cell at all, we will exchange the information about the data
342 // sizes among them later. The code in between is still well-defined,
343 // since the following loops will be skipped.
344 std::vector<unsigned int> local_sizes_fixed(
345 1 + n_callbacks_fixed + (variable_size_data_stored ? 1 : 0));
346 for (const auto &data_cell : packed_fixed_size_data)
347 {
348 if (data_cell.size() == local_sizes_fixed.size())
349 {
350 auto sizes_fixed_it = local_sizes_fixed.begin();
351 auto data_fixed_it = data_cell.cbegin();
352 for (; data_fixed_it != data_cell.cend();
353 ++data_fixed_it, ++sizes_fixed_it)
354 {
355 *sizes_fixed_it = data_fixed_it->size();
356 }
357
358 break;
359 }
360 }
361
362 // Check if all cells have valid sizes.
363 for (auto data_cell_fixed_it = packed_fixed_size_data.cbegin();
364 data_cell_fixed_it != packed_fixed_size_data.cend();
365 ++data_cell_fixed_it)
366 {
367 Assert((data_cell_fixed_it->size() == 1) ||
368 (data_cell_fixed_it->size() == local_sizes_fixed.size()),
370 }
371
372 // Share information about the packed data sizes
373 // of all callback functions across all processors, in case one
374 // of them does not own any cells at all.
375 std::vector<unsigned int> global_sizes_fixed(local_sizes_fixed.size());
376 Utilities::MPI::max(local_sizes_fixed,
377 mpi_communicator,
378 global_sizes_fixed);
379
380 // Construct cumulative sizes, since this is the only information
381 // we need from now on.
382 sizes_fixed_cumulative.resize(global_sizes_fixed.size());
383 std::partial_sum(global_sizes_fixed.begin(),
384 global_sizes_fixed.end(),
385 sizes_fixed_cumulative.begin());
386
387 //
388 // ---------- Gather data sizes for variable size transfer ----------
389 //
390 if (variable_size_data_stored)
391 {
392 src_sizes_variable.reserve(packed_variable_size_data.size());
393 for (const auto &data_cell : packed_variable_size_data)
394 {
395 int variable_data_size_on_cell = 0;
396
397 for (const auto &data : data_cell)
398 variable_data_size_on_cell += data.size();
399
400 src_sizes_variable.push_back(variable_data_size_on_cell);
401 }
402 }
403
404 //
405 // ------------------------ Build buffers ---------------------------
406 //
407 const unsigned int expected_size_fixed =
408 cell_relations.size() * sizes_fixed_cumulative.back();
409 const unsigned int expected_size_variable =
410 std::accumulate(src_sizes_variable.begin(),
411 src_sizes_variable.end(),
412 std::vector<int>::size_type(0));
413
414 // Move every piece of packed fixed size data into the consecutive
415 // buffer.
416 src_data_fixed.reserve(expected_size_fixed);
417 for (const auto &data_cell_fixed : packed_fixed_size_data)
418 {
419 // Move every fraction of packed data into the buffer
420 // reserved for this particular cell.
421 for (const auto &data_fixed : data_cell_fixed)
422 std::move(data_fixed.begin(),
423 data_fixed.end(),
424 std::back_inserter(src_data_fixed));
425
426 // If we only packed the CellStatus information
427 // (i.e. encountered a cell flagged CellStatus::cell_invalid),
428 // fill the remaining space with invalid entries.
429 // We can skip this if there is nothing else to pack.
430 if ((data_cell_fixed.size() == 1) &&
431 (sizes_fixed_cumulative.size() > 1))
432 {
433 const std::size_t bytes_skipped =
434 sizes_fixed_cumulative.back() - sizes_fixed_cumulative.front();
435
436 src_data_fixed.insert(src_data_fixed.end(),
437 bytes_skipped,
438 static_cast<char>(-1)); // invalid_char
440 }
441
442 // Move every piece of packed variable size data into the consecutive
443 // buffer.
444 if (variable_size_data_stored)
445 {
446 src_data_variable.reserve(expected_size_variable);
447 for (const auto &data_cell : packed_variable_size_data)
448 {
449 // Move every fraction of packed data into the buffer
450 // reserved for this particular cell.
451 for (const auto &data : data_cell)
452 std::move(data.begin(),
453 data.end(),
454 std::back_inserter(src_data_variable));
455 }
456 }
457
458 // Double check that we packed everything correctly.
459 Assert(src_data_fixed.size() == expected_size_fixed, ExcInternalError());
460 Assert(src_data_variable.size() == expected_size_variable,
462 }
464
465
466 template <int dim, int spacedim>
468 void CellAttachedDataSerializer<dim, spacedim>::unpack_cell_status(
469 std::vector<
470 typename CellAttachedDataSerializer<dim, spacedim>::cell_relation_t>
471 &cell_relations) const
472 {
473 Assert(sizes_fixed_cumulative.size() > 0,
474 ExcMessage("No data has been packed!"));
475 if (cell_relations.size() > 0)
476 {
477 Assert(dest_data_fixed.size() > 0,
478 ExcMessage("No data has been received!"));
479 }
480
481 // Size of CellStatus object that will be unpacked on each cell.
482 const unsigned int size = sizes_fixed_cumulative.front();
483
484 // Iterate over all cells and overwrite the CellStatus
485 // information from the transferred data.
486 // Proceed buffer iterator position to next cell after
487 // each iteration.
488 auto cell_rel_it = cell_relations.begin();
489 auto dest_fixed_it = dest_data_fixed.cbegin();
490 for (; cell_rel_it != cell_relations.end();
491 ++cell_rel_it, dest_fixed_it += sizes_fixed_cumulative.back())
492 {
493 cell_rel_it->second = // cell_status
494 Utilities::unpack<CellStatus>(dest_fixed_it,
495 dest_fixed_it + size,
496 /*allow_compression=*/false);
497 }
498 }
499
500
501
502 template <int dim, int spacedim>
504 void CellAttachedDataSerializer<dim, spacedim>::unpack_data(
505 const std::vector<
506 typename CellAttachedDataSerializer<dim, spacedim>::cell_relation_t>
507 &cell_relations,
508 const unsigned int handle,
509 const std::function<
510 void(const cell_iterator &,
511 const CellStatus &,
512 const boost::iterator_range<std::vector<char>::const_iterator> &)>
513 &unpack_callback) const
514 {
515 // We decode the handle returned by register_data_attach() back into
516 // a format we can use. All even handles belong to those callback
517 // functions which write/read variable size data, all odd handles
518 // interact with fixed size buffers.
519 const bool callback_variable_transfer = (handle % 2 == 0);
520 const unsigned int callback_index = handle / 2;
521
522 // Cells will always receive fixed size data (i.e., CellStatus
523 // information), but not necessarily variable size data (e.g., with a
524 // ParticleHandler a cell might not contain any particle at all).
525 // Thus it is sufficient to check if fixed size data has been received.
526 Assert(sizes_fixed_cumulative.size() > 0,
527 ExcMessage("No data has been packed!"));
528 if (cell_relations.size() > 0)
529 {
530 Assert(dest_data_fixed.size() > 0,
531 ExcMessage("No data has been received!"));
532 }
533
534 std::vector<char>::const_iterator dest_data_it;
535 std::vector<char>::const_iterator dest_sizes_cell_it;
536
537 // Depending on whether our callback function unpacks fixed or
538 // variable size data, we have to pursue different approaches
539 // to localize the correct fraction of the buffer from which
540 // we are allowed to read.
541 unsigned int offset = numbers::invalid_unsigned_int;
542 unsigned int size = numbers::invalid_unsigned_int;
543 unsigned int data_increment = numbers::invalid_unsigned_int;
544
545 if (callback_variable_transfer)
546 {
547 // For the variable size data, we need to extract the
548 // data size from the fixed size buffer on each cell.
549 //
550 // We packed this information last, so the last packed
551 // object in the fixed size buffer corresponds to the
552 // variable data sizes.
553 //
554 // The last entry of sizes_fixed_cumulative corresponds
555 // to the size of all fixed size data packed on the cell.
556 // To get the offset for the last packed object, we need
557 // to get the next-to-last entry.
558 const unsigned int offset_variable_data_sizes =
559 sizes_fixed_cumulative[sizes_fixed_cumulative.size() - 2];
560
561 // This iterator points to the data size that the
562 // callback_function packed for each specific cell.
563 // Adjust buffer iterator to the offset of the callback
564 // function so that we only have to advance its position
565 // to the next cell after each iteration.
566 dest_sizes_cell_it = dest_data_fixed.cbegin() +
567 offset_variable_data_sizes +
568 callback_index * sizeof(unsigned int);
569
570 // Let the data iterator point to the correct buffer.
571 dest_data_it = dest_data_variable.cbegin();
572 }
573 else
574 {
575 // For the fixed size data, we can get the information about
576 // the buffer location on each cell directly from the
577 // sizes_fixed_cumulative vector.
578 offset = sizes_fixed_cumulative[callback_index];
579 size = sizes_fixed_cumulative[callback_index + 1] - offset;
580 data_increment = sizes_fixed_cumulative.back();
581
582 // Let the data iterator point to the correct buffer.
583 // Adjust buffer iterator to the offset of the callback
584 // function so that we only have to advance its position
585 // to the next cell after each iteration.
586 if (cell_relations.begin() != cell_relations.end())
587 dest_data_it = dest_data_fixed.cbegin() + offset;
588 }
589
590 // Iterate over all cells and unpack the transferred data.
591 auto cell_rel_it = cell_relations.begin();
592 auto dest_sizes_it = dest_sizes_variable.cbegin();
593 for (; cell_rel_it != cell_relations.end(); ++cell_rel_it)
594 {
595 const auto &dealii_cell = cell_rel_it->first;
596 const auto &cell_status = cell_rel_it->second;
597
598 if (callback_variable_transfer)
599 {
600 // Update the increment according to the whole data size
601 // of the current cell.
602 data_increment = *dest_sizes_it;
603
604 if (cell_status != CellStatus::cell_invalid)
605 {
606 // Extract the corresponding values for offset and size from
607 // the cumulative sizes array stored in the fixed size
608 // buffer.
609 if (callback_index == 0)
610 offset = 0;
611 else
612 std::memcpy(&offset,
613 &(*(dest_sizes_cell_it - sizeof(unsigned int))),
614 sizeof(unsigned int));
615
616 std::memcpy(&size,
617 &(*dest_sizes_cell_it),
618 sizeof(unsigned int));
619
620 size -= offset;
621
622 // Move the data iterator to the corresponding position
623 // of the callback function and adjust the increment
624 // accordingly.
625 dest_data_it += offset;
626 data_increment -= offset;
627 }
628
629 // Advance data size iterators to the next cell, avoid iterating
630 // past the end of dest_sizes_cell_it
631 if (cell_rel_it != cell_relations.end() - 1)
632 dest_sizes_cell_it += sizes_fixed_cumulative.back();
633 ++dest_sizes_it;
634 }
635
636 switch (cell_status)
637 {
640 unpack_callback(dealii_cell,
641 cell_status,
642 boost::make_iterator_range(dest_data_it,
643 dest_data_it + size));
644 break;
645
647 unpack_callback(dealii_cell->parent(),
648 cell_status,
649 boost::make_iterator_range(dest_data_it,
650 dest_data_it + size));
651 break;
652
654 // Skip this cell.
655 break;
656
657 default:
659 break;
660 }
661
662 if (cell_rel_it != cell_relations.end() - 1)
663 dest_data_it += data_increment;
664 }
665 }
666
667
668
669 template <int dim, int spacedim>
671 void CellAttachedDataSerializer<dim, spacedim>::save(
672 const unsigned int global_first_cell,
673 const unsigned int global_num_cells,
674 const std::string &file_basename,
675 const MPI_Comm &mpi_communicator) const
676 {
677 Assert(sizes_fixed_cumulative.size() > 0,
678 ExcMessage("No data has been packed!"));
679
680#ifdef DEAL_II_WITH_MPI
681 // Large fractions of this function have been copied from
682 // DataOutInterface::write_vtu_in_parallel.
683 // TODO: Write general MPIIO interface.
684
685 const unsigned int myrank =
686 Utilities::MPI::this_mpi_process(mpi_communicator);
687 const unsigned int mpisize =
688 Utilities::MPI::n_mpi_processes(mpi_communicator);
689
690 if (mpisize > 1)
691 {
692 const unsigned int bytes_per_cell = sizes_fixed_cumulative.back();
693
694 //
695 // ---------- Fixed size data ----------
696 //
697 {
698 const std::string fname_fixed =
699 std::string(file_basename) + "_fixed.data";
700
701 MPI_Info info;
702 int ierr = MPI_Info_create(&info);
703 AssertThrowMPI(ierr);
704
705 MPI_File fh;
706 ierr = MPI_File_open(mpi_communicator,
707 fname_fixed.c_str(),
708 MPI_MODE_CREATE | MPI_MODE_WRONLY,
709 info,
710 &fh);
711 AssertThrowMPI(ierr);
712
713 ierr = MPI_File_set_size(fh, 0); // delete the file contents
714 AssertThrowMPI(ierr);
715 // this barrier is necessary, because otherwise others might already
716 // write while one core is still setting the size to zero.
717 ierr = MPI_Barrier(mpi_communicator);
718 AssertThrowMPI(ierr);
719 ierr = MPI_Info_free(&info);
720 AssertThrowMPI(ierr);
721 // ------------------
722
723 // Write cumulative sizes to file.
724 // Since each processor owns the same information about the data
725 // sizes, it is sufficient to let only the first processor perform
726 // this task.
727 if (myrank == 0)
728 {
730 fh,
731 0,
732 sizes_fixed_cumulative.data(),
733 sizes_fixed_cumulative.size(),
734 MPI_UNSIGNED,
735 MPI_STATUS_IGNORE);
736 AssertThrowMPI(ierr);
737 }
738
739 // Write packed data to file simultaneously.
740 const MPI_Offset size_header =
741 sizes_fixed_cumulative.size() * sizeof(unsigned int);
742
743 // Make sure we do the following computation in 64bit integers to be
744 // able to handle 4GB+ files:
745 const MPI_Offset my_global_file_position =
746 size_header +
747 static_cast<MPI_Offset>(global_first_cell) * bytes_per_cell;
748
749 ierr =
751 my_global_file_position,
752 src_data_fixed.data(),
753 src_data_fixed.size(),
754 MPI_BYTE,
755 MPI_STATUS_IGNORE);
756 AssertThrowMPI(ierr);
757
758 ierr = MPI_File_close(&fh);
759 AssertThrowMPI(ierr);
760 }
761
762
763
764 //
765 // ---------- Variable size data ----------
766 //
767 if (variable_size_data_stored)
768 {
769 const std::string fname_variable =
770 std::string(file_basename) + "_variable.data";
771
772 MPI_Info info;
773 int ierr = MPI_Info_create(&info);
774 AssertThrowMPI(ierr);
775
776 MPI_File fh;
777 ierr = MPI_File_open(mpi_communicator,
778 fname_variable.c_str(),
779 MPI_MODE_CREATE | MPI_MODE_WRONLY,
780 info,
781 &fh);
782 AssertThrowMPI(ierr);
783
784 ierr = MPI_File_set_size(fh, 0); // delete the file contents
785 AssertThrowMPI(ierr);
786 // this barrier is necessary, because otherwise others might already
787 // write while one core is still setting the size to zero.
788 ierr = MPI_Barrier(mpi_communicator);
789 AssertThrowMPI(ierr);
790 ierr = MPI_Info_free(&info);
791 AssertThrowMPI(ierr);
792
793 // Write sizes of each cell into file simultaneously.
794 {
795 const MPI_Offset my_global_file_position =
796 static_cast<MPI_Offset>(global_first_cell) *
797 sizeof(unsigned int);
798
799 // It is very unlikely that a single process has more than
800 // 2 billion cells, but we might as well check.
801 AssertThrow(src_sizes_variable.size() <
802 static_cast<std::size_t>(
803 std::numeric_limits<int>::max()),
805
807 fh,
808 my_global_file_position,
809 src_sizes_variable.data(),
810 src_sizes_variable.size(),
811 MPI_INT,
812 MPI_STATUS_IGNORE);
813 AssertThrowMPI(ierr);
814 }
815
816 // Gather size of data in bytes we want to store from this
817 // processor and compute the prefix sum. We do this in 64 bit
818 // to avoid overflow for files larger than 4GB:
819 const std::uint64_t size_on_proc = src_data_variable.size();
820 std::uint64_t prefix_sum = 0;
821 ierr = MPI_Exscan(&size_on_proc,
822 &prefix_sum,
823 1,
824 MPI_UINT64_T,
825 MPI_SUM,
826 mpi_communicator);
827 AssertThrowMPI(ierr);
828
829 const MPI_Offset my_global_file_position =
830 static_cast<MPI_Offset>(global_num_cells) * sizeof(unsigned int) +
831 prefix_sum;
832
833 // Write data consecutively into file.
835 fh,
836 my_global_file_position,
837 src_data_variable.data(),
838 src_data_variable.size(),
839 MPI_BYTE,
840 MPI_STATUS_IGNORE);
841 AssertThrowMPI(ierr);
842
843
844 ierr = MPI_File_close(&fh);
845 AssertThrowMPI(ierr);
846 }
847 } // if (mpisize > 1)
848 else
849#endif
850 {
851 (void)global_first_cell;
852 (void)global_num_cells;
853 (void)mpi_communicator;
854
855 //
856 // ---------- Fixed size data ----------
857 //
858 {
859 const std::string fname_fixed =
860 std::string(file_basename) + "_fixed.data";
861
862 std::ofstream file(fname_fixed, std::ios::binary | std::ios::out);
863 AssertThrow(file.fail() == false, ExcIO());
864
865 // Write header data.
866 file.write(reinterpret_cast<const char *>(
867 sizes_fixed_cumulative.data()),
868 sizes_fixed_cumulative.size() * sizeof(unsigned int));
869
870 // Write packed data.
871 file.write(reinterpret_cast<const char *>(src_data_fixed.data()),
872 src_data_fixed.size() * sizeof(char));
873 }
874
875 //
876 // ---------- Variable size data ----------
877 //
878 if (variable_size_data_stored)
879 {
880 const std::string fname_variable =
881 std::string(file_basename) + "_variable.data";
882
883 std::ofstream file(fname_variable,
884 std::ios::binary | std::ios::out);
885 AssertThrow(file.fail() == false, ExcIO());
886
887 // Write header data.
888 file.write(reinterpret_cast<const char *>(
889 src_sizes_variable.data()),
890 src_sizes_variable.size() * sizeof(int));
891
892 // Write packed data.
893 file.write(reinterpret_cast<const char *>(src_data_variable.data()),
894 src_data_variable.size() * sizeof(char));
895 }
896 }
897 }
898
899
900 template <int dim, int spacedim>
902 void CellAttachedDataSerializer<dim, spacedim>::load(
903 const unsigned int global_first_cell,
904 const unsigned int global_num_cells,
905 const unsigned int local_num_cells,
906 const std::string &file_basename,
907 const unsigned int n_attached_deserialize_fixed,
908 const unsigned int n_attached_deserialize_variable,
909 const MPI_Comm &mpi_communicator)
910 {
911 Assert(dest_data_fixed.empty(),
912 ExcMessage("Previously loaded data has not been released yet!"));
913
914 variable_size_data_stored = (n_attached_deserialize_variable > 0);
915
916#ifdef DEAL_II_WITH_MPI
917 // Large fractions of this function have been copied from
918 // DataOutInterface::write_vtu_in_parallel.
919 // TODO: Write general MPIIO interface.
920
921 const unsigned int mpisize =
922 Utilities::MPI::n_mpi_processes(mpi_communicator);
923
924 if (mpisize > 1)
925 {
926 //
927 // ---------- Fixed size data ----------
928 //
929 {
930 const std::string fname_fixed =
931 std::string(file_basename) + "_fixed.data";
932
933 MPI_Info info;
934 int ierr = MPI_Info_create(&info);
935 AssertThrowMPI(ierr);
936
937 MPI_File fh;
938 ierr = MPI_File_open(
939 mpi_communicator, fname_fixed.c_str(), MPI_MODE_RDONLY, info, &fh);
940 AssertThrowMPI(ierr);
941
942 ierr = MPI_Info_free(&info);
943 AssertThrowMPI(ierr);
944
945 // Read cumulative sizes from file.
946 // Since all processors need the same information about the data
947 // sizes, let each of them retrieve it by reading from the same
948 // location in the file.
949 sizes_fixed_cumulative.resize(1 + n_attached_deserialize_fixed +
950 (variable_size_data_stored ? 1 : 0));
952 fh,
953 0,
954 sizes_fixed_cumulative.data(),
955 sizes_fixed_cumulative.size(),
956 MPI_UNSIGNED,
957 MPI_STATUS_IGNORE);
958 AssertThrowMPI(ierr);
959
960 // Allocate sufficient memory.
961 const unsigned int bytes_per_cell = sizes_fixed_cumulative.back();
962 dest_data_fixed.resize(static_cast<size_t>(local_num_cells) *
963 bytes_per_cell);
964
965 // Read packed data from file simultaneously.
966 const MPI_Offset size_header =
967 sizes_fixed_cumulative.size() * sizeof(unsigned int);
968
969 // Make sure we do the following computation in 64bit integers to be
970 // able to handle 4GB+ files:
971 const MPI_Offset my_global_file_position =
972 size_header +
973 static_cast<MPI_Offset>(global_first_cell) * bytes_per_cell;
974
975 ierr =
977 my_global_file_position,
978 dest_data_fixed.data(),
979 dest_data_fixed.size(),
980 MPI_BYTE,
981 MPI_STATUS_IGNORE);
982 AssertThrowMPI(ierr);
983
984
985 ierr = MPI_File_close(&fh);
986 AssertThrowMPI(ierr);
987 }
988
989 //
990 // ---------- Variable size data ----------
991 //
992 if (variable_size_data_stored)
993 {
994 const std::string fname_variable =
995 std::string(file_basename) + "_variable.data";
996
997 MPI_Info info;
998 int ierr = MPI_Info_create(&info);
999 AssertThrowMPI(ierr);
1000
1001 MPI_File fh;
1002 ierr = MPI_File_open(mpi_communicator,
1003 fname_variable.c_str(),
1004 MPI_MODE_RDONLY,
1005 info,
1006 &fh);
1007 AssertThrowMPI(ierr);
1008
1009 ierr = MPI_Info_free(&info);
1010 AssertThrowMPI(ierr);
1011
1012 // Read sizes of all locally owned cells.
1013 dest_sizes_variable.resize(local_num_cells);
1014
1015 const MPI_Offset my_global_file_position_sizes =
1016 static_cast<MPI_Offset>(global_first_cell) * sizeof(unsigned int);
1017
1019 fh,
1020 my_global_file_position_sizes,
1021 dest_sizes_variable.data(),
1022 dest_sizes_variable.size(),
1023 MPI_INT,
1024 MPI_STATUS_IGNORE);
1025 AssertThrowMPI(ierr);
1026
1027
1028 // Compute my data size in bytes and compute prefix sum. We do this
1029 // in 64 bit to avoid overflow for files larger than 4 GB:
1030 const std::uint64_t size_on_proc =
1031 std::accumulate(dest_sizes_variable.begin(),
1032 dest_sizes_variable.end(),
1033 0ULL);
1034
1035 std::uint64_t prefix_sum = 0;
1036 ierr = MPI_Exscan(&size_on_proc,
1037 &prefix_sum,
1038 1,
1039 MPI_UINT64_T,
1040 MPI_SUM,
1041 mpi_communicator);
1042 AssertThrowMPI(ierr);
1043
1044 const MPI_Offset my_global_file_position =
1045 static_cast<MPI_Offset>(global_num_cells) * sizeof(unsigned int) +
1046 prefix_sum;
1047
1048 dest_data_variable.resize(size_on_proc);
1049
1051 fh,
1052 my_global_file_position,
1053 dest_data_variable.data(),
1054 dest_data_variable.size(),
1055 MPI_BYTE,
1056 MPI_STATUS_IGNORE);
1057 AssertThrowMPI(ierr);
1058
1059 ierr = MPI_File_close(&fh);
1060 AssertThrowMPI(ierr);
1061 }
1062 }
1063 else // if (mpisize > 1)
1064#endif
1065 {
1066 (void)mpi_communicator;
1067 (void)global_first_cell;
1068 (void)global_num_cells;
1069
1070 //
1071 // ---------- Fixed size data ----------
1072 //
1073 {
1074 const std::string fname_fixed =
1075 std::string(file_basename) + "_fixed.data";
1076
1077 std::ifstream file(fname_fixed, std::ios::binary | std::ios::in);
1078 AssertThrow(file.fail() == false, ExcIO());
1079
1080 sizes_fixed_cumulative.resize(1 + n_attached_deserialize_fixed +
1081 (variable_size_data_stored ? 1 : 0));
1082 // Read header data.
1083 file.read(reinterpret_cast<char *>(sizes_fixed_cumulative.data()),
1084 sizes_fixed_cumulative.size() * sizeof(unsigned int));
1085
1086 const unsigned int bytes_per_cell = sizes_fixed_cumulative.back();
1087 dest_data_fixed.resize(static_cast<size_t>(local_num_cells) *
1088 bytes_per_cell);
1089
1090 // Read packed data.
1091 file.read(reinterpret_cast<char *>(dest_data_fixed.data()),
1092 dest_data_fixed.size() * sizeof(char));
1093 }
1094
1095 //
1096 // ---------- Variable size data ----------
1097 //
1098 if (variable_size_data_stored)
1099 {
1100 const std::string fname_variable =
1101 std::string(file_basename) + "_variable.data";
1102
1103 std::ifstream file(fname_variable, std::ios::binary | std::ios::in);
1104 AssertThrow(file.fail() == false, ExcIO());
1105
1106 // Read header data.
1107 dest_sizes_variable.resize(local_num_cells);
1108 file.read(reinterpret_cast<char *>(dest_sizes_variable.data()),
1109 dest_sizes_variable.size() * sizeof(int));
1110
1111 // Read packed data.
1112 const std::uint64_t size =
1113 std::accumulate(dest_sizes_variable.begin(),
1114 dest_sizes_variable.end(),
1115 0ULL);
1116 dest_data_variable.resize(size);
1117 file.read(reinterpret_cast<char *>(dest_data_variable.data()),
1118 dest_data_variable.size() * sizeof(char));
1119 }
1120 }
1121 }
1122
1123
1124 template <int dim, int spacedim>
1126 void CellAttachedDataSerializer<dim, spacedim>::clear()
1127 {
1128 variable_size_data_stored = false;
1129
1130 // free information about data sizes
1131 sizes_fixed_cumulative.clear();
1132 sizes_fixed_cumulative.shrink_to_fit();
1133
1134 // free fixed size transfer data
1135 src_data_fixed.clear();
1136 src_data_fixed.shrink_to_fit();
1137
1138 dest_data_fixed.clear();
1139 dest_data_fixed.shrink_to_fit();
1140
1141 // free variable size transfer data
1142 src_sizes_variable.clear();
1143 src_sizes_variable.shrink_to_fit();
1144
1145 src_data_variable.clear();
1146 src_data_variable.shrink_to_fit();
1147
1148 dest_sizes_variable.clear();
1149 dest_sizes_variable.shrink_to_fit();
1150
1151 dest_data_variable.clear();
1152 dest_data_variable.shrink_to_fit();
1153 }
1154
1155} // namespace internal
1156
1157// anonymous namespace for internal helper functions
1158namespace
1159{
1160 // return whether the given cell is
1161 // patch_level_1, i.e. determine
1162 // whether either all or none of
1163 // its children are further
1164 // refined. this function can only
1165 // be called for non-active cells.
1166 template <int dim, int spacedim>
1167 bool
1168 cell_is_patch_level_1(
1170 {
1171 Assert(cell->is_active() == false, ExcInternalError());
1172
1173 unsigned int n_active_children = 0;
1174 for (unsigned int i = 0; i < cell->n_children(); ++i)
1175 if (cell->child(i)->is_active())
1176 ++n_active_children;
1177
1178 return (n_active_children == 0) ||
1179 (n_active_children == cell->n_children());
1180 }
1181
1182
1183
1184 // return, whether a given @p cell will be
1185 // coarsened, which is the case if all
1186 // children are active and have their coarsen
1187 // flag set. In case only part of the coarsen
1188 // flags are set, remove them.
1189 template <int dim, int spacedim>
1190 bool
1191 cell_will_be_coarsened(
1193 {
1194 // only cells with children should be
1195 // considered for coarsening
1196
1197 if (cell->has_children())
1198 {
1199 unsigned int children_to_coarsen = 0;
1200 const unsigned int n_children = cell->n_children();
1201
1202 for (unsigned int c = 0; c < n_children; ++c)
1203 if (cell->child(c)->is_active() && cell->child(c)->coarsen_flag_set())
1204 ++children_to_coarsen;
1205 if (children_to_coarsen == n_children)
1206 return true;
1207 else
1208 for (unsigned int c = 0; c < n_children; ++c)
1209 if (cell->child(c)->is_active())
1210 cell->child(c)->clear_coarsen_flag();
1211 }
1212 // no children, so no coarsening
1213 // possible. however, no children also
1214 // means that this cell will be in the same
1215 // state as if it had children and was
1216 // coarsened. So, what should we return -
1217 // false or true?
1218 // make sure we do not have to do this at
1219 // all...
1220 Assert(cell->has_children(), ExcInternalError());
1221 // ... and then simply return false
1222 return false;
1223 }
1224
1225
1226 // return, whether the face @p face_no of the
1227 // given @p cell will be refined after the
1228 // current refinement step, considering
1229 // refine and coarsen flags and considering
1230 // only those refinemnts that will be caused
1231 // by the neighboring cell.
1232
1233 // this function is used on both active cells
1234 // and cells with children. on cells with
1235 // children it also of interest to know 'how'
1236 // the face will be refined. thus there is an
1237 // additional third argument @p
1238 // expected_face_ref_case returning just
1239 // that. be aware, that this variable will
1240 // only contain useful information if this
1241 // function is called for an active cell.
1242 //
1243 // thus, this is an internal function, users
1244 // should call one of the two alternatives
1245 // following below.
1246 template <int dim, int spacedim>
1247 bool
1248 face_will_be_refined_by_neighbor_internal(
1250 const unsigned int face_no,
1251 RefinementCase<dim - 1> &expected_face_ref_case)
1252 {
1253 // first of all: set the default value for
1254 // expected_face_ref_case, which is no
1255 // refinement at all
1256 expected_face_ref_case = RefinementCase<dim - 1>::no_refinement;
1257
1258 const typename Triangulation<dim, spacedim>::cell_iterator neighbor =
1259 cell->neighbor(face_no);
1260
1261 // If we are at the boundary, there is no
1262 // neighbor which could refine the face
1263 if (neighbor.state() != IteratorState::valid)
1264 return false;
1265
1266 if (neighbor->has_children())
1267 {
1268 // if the neighbor is refined, it may be
1269 // coarsened. if so, then it won't refine
1270 // the face, no matter what else happens
1271 if (cell_will_be_coarsened(neighbor))
1272 return false;
1273 else
1274 // if the neighbor is refined, then it
1275 // is also refined at our current
1276 // face. It will stay so without
1277 // coarsening, so return true in that
1278 // case.
1279 {
1280 expected_face_ref_case = cell->face(face_no)->refinement_case();
1281 return true;
1282 }
1283 }
1284
1285 // now, the neighbor is not refined, but
1286 // perhaps it will be
1287 const RefinementCase<dim> nb_ref_flag = neighbor->refine_flag_set();
1288 if (nb_ref_flag != RefinementCase<dim>::no_refinement)
1289 {
1290 // now we need to know, which of the
1291 // neighbors faces points towards us
1292 const unsigned int neighbor_neighbor = cell->neighbor_face_no(face_no);
1293 // check, whether the cell will be
1294 // refined in a way that refines our
1295 // face
1296 const RefinementCase<dim - 1> face_ref_case =
1298 nb_ref_flag,
1299 neighbor_neighbor,
1300 neighbor->face_orientation(neighbor_neighbor),
1301 neighbor->face_flip(neighbor_neighbor),
1302 neighbor->face_rotation(neighbor_neighbor));
1303 if (face_ref_case != RefinementCase<dim - 1>::no_refinement)
1304 {
1306 neighbor_face = neighbor->face(neighbor_neighbor);
1307 const int this_face_index = cell->face_index(face_no);
1308
1309 // there are still two basic
1310 // possibilities here: the neighbor
1311 // might be coarser or as coarse
1312 // as we are
1313 if (neighbor_face->index() == this_face_index)
1314 // the neighbor is as coarse as
1315 // we are and will be refined at
1316 // the face of consideration, so
1317 // return true
1318 {
1319 expected_face_ref_case = face_ref_case;
1320 return true;
1321 }
1322 else
1323 {
1324 // the neighbor is coarser.
1325 // this is the most complicated
1326 // case. It might be, that the
1327 // neighbor's face will be
1328 // refined, but that we will
1329 // not see this, as we are
1330 // refined in a similar way.
1331
1332 // so, the neighbor's face must
1333 // have children. check, if our
1334 // cell's face is one of these
1335 // (it could also be a
1336 // grand_child)
1337 for (unsigned int c = 0; c < neighbor_face->n_children(); ++c)
1338 if (neighbor_face->child_index(c) == this_face_index)
1339 {
1340 // if the flagged refine
1341 // case of the face is a
1342 // subset or the same as
1343 // the current refine case,
1344 // then the face, as seen
1345 // from our cell, won't be
1346 // refined by the neighbor
1347 if ((neighbor_face->refinement_case() | face_ref_case) ==
1348 neighbor_face->refinement_case())
1349 return false;
1350 else
1351 {
1352 // if we are active, we
1353 // must be an
1354 // anisotropic child
1355 // and the coming
1356 // face_ref_case is
1357 // isotropic. Thus,
1358 // from our cell we
1359 // will see exactly the
1360 // opposite refine case
1361 // that the face has
1362 // now...
1363 Assert(
1364 face_ref_case ==
1367 expected_face_ref_case =
1368 ~neighbor_face->refinement_case();
1369 return true;
1370 }
1371 }
1372
1373 // so, obviously we were not
1374 // one of the children, but a
1375 // grandchild. This is only
1376 // possible in 3d.
1377 Assert(dim == 3, ExcInternalError());
1378 // In that case, however, no
1379 // matter what the neighbor
1380 // does, it won't be finer
1381 // after the next refinement
1382 // step.
1383 return false;
1384 }
1385 } // if face will be refined
1386 } // if neighbor is flagged for refinement
1387
1388 // no cases left, so the neighbor will not
1389 // refine the face
1390 return false;
1391 }
1392
1393 // version of above function for both active
1394 // and non-active cells
1395 template <int dim, int spacedim>
1396 bool
1397 face_will_be_refined_by_neighbor(
1399 const unsigned int face_no)
1400 {
1401 RefinementCase<dim - 1> dummy = RefinementCase<dim - 1>::no_refinement;
1402 return face_will_be_refined_by_neighbor_internal(cell, face_no, dummy);
1403 }
1404
1405 // version of above function for active cells
1406 // only. Additionally returning the refine
1407 // case (to come) of the face under
1408 // consideration
1409 template <int dim, int spacedim>
1410 bool
1411 face_will_be_refined_by_neighbor(
1413 const unsigned int face_no,
1414 RefinementCase<dim - 1> &expected_face_ref_case)
1415 {
1416 return face_will_be_refined_by_neighbor_internal(cell,
1417 face_no,
1418 expected_face_ref_case);
1419 }
1420
1421
1422
1423 template <int dim, int spacedim>
1424 bool
1425 satisfies_level1_at_vertex_rule(
1427 {
1428 std::vector<unsigned int> min_adjacent_cell_level(
1429 triangulation.n_vertices(), triangulation.n_levels());
1430 std::vector<unsigned int> max_adjacent_cell_level(
1431 triangulation.n_vertices(), 0);
1432
1433 for (const auto &cell : triangulation.active_cell_iterators())
1434 for (const unsigned int v : cell->vertex_indices())
1435 {
1436 min_adjacent_cell_level[cell->vertex_index(v)] =
1437 std::min<unsigned int>(
1438 min_adjacent_cell_level[cell->vertex_index(v)], cell->level());
1439 max_adjacent_cell_level[cell->vertex_index(v)] =
1440 std::max<unsigned int>(
1441 min_adjacent_cell_level[cell->vertex_index(v)], cell->level());
1442 }
1443
1444 for (unsigned int k = 0; k < triangulation.n_vertices(); ++k)
1445 if (triangulation.vertex_used(k))
1446 if (max_adjacent_cell_level[k] - min_adjacent_cell_level[k] > 1)
1447 return false;
1448 return true;
1449 }
1450
1451
1452
1470 template <int dim, int spacedim>
1471 unsigned int
1472 middle_vertex_index(
1474 {
1475 if (line->has_children())
1476 return line->child(0)->vertex_index(1);
1478 }
1479
1480
1481 template <int dim, int spacedim>
1482 unsigned int
1483 middle_vertex_index(
1485 {
1486 switch (static_cast<unsigned char>(quad->refinement_case()))
1487 {
1489 return middle_vertex_index<dim, spacedim>(quad->child(0)->line(1));
1490 break;
1492 return middle_vertex_index<dim, spacedim>(quad->child(0)->line(3));
1493 break;
1495 return quad->child(0)->vertex_index(3);
1496 break;
1497 default:
1498 break;
1499 }
1501 }
1502
1503
1504 template <int dim, int spacedim>
1505 unsigned int
1506 middle_vertex_index(
1508 {
1509 switch (static_cast<unsigned char>(hex->refinement_case()))
1510 {
1512 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(1));
1513 break;
1515 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(3));
1516 break;
1518 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(5));
1519 break;
1521 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(11));
1522 break;
1524 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(5));
1525 break;
1527 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(7));
1528 break;
1530 return hex->child(0)->vertex_index(7);
1531 break;
1532 default:
1533 break;
1534 }
1536 }
1537
1538
1551 template <class TRIANGULATION>
1552 inline typename TRIANGULATION::DistortedCellList
1553 collect_distorted_coarse_cells(const TRIANGULATION &)
1554 {
1555 return typename TRIANGULATION::DistortedCellList();
1556 }
1557
1558
1559
1568 template <int dim>
1570 collect_distorted_coarse_cells(const Triangulation<dim, dim> &triangulation)
1571 {
1572 typename Triangulation<dim, dim>::DistortedCellList distorted_cells;
1573 for (const auto &cell : triangulation.cell_iterators_on_level(0))
1574 {
1576 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1577 vertices[i] = cell->vertex(i);
1578
1581
1582 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1583 if (determinants[i] <=
1584 1e-9 * Utilities::fixed_power<dim>(cell->diameter()))
1585 {
1586 distorted_cells.distorted_cells.push_back(cell);
1587 break;
1588 }
1589 }
1590
1591 return distorted_cells;
1592 }
1593
1594
1601 template <int dim>
1602 bool
1603 has_distorted_children(
1604 const typename Triangulation<dim, dim>::cell_iterator &cell)
1605 {
1606 Assert(cell->has_children(), ExcInternalError());
1607
1608 for (unsigned int c = 0; c < cell->n_children(); ++c)
1609 {
1611 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1612 vertices[i] = cell->child(c)->vertex(i);
1613
1616
1617 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1618 if (determinants[i] <=
1619 1e-9 * Utilities::fixed_power<dim>(cell->child(c)->diameter()))
1620 return true;
1621 }
1622
1623 return false;
1624 }
1625
1626
1634 template <int dim, int spacedim>
1635 bool
1636 has_distorted_children(
1638 {
1639 return false;
1640 }
1641
1642
1643 template <int dim, int spacedim>
1644 void
1645 update_periodic_face_map_recursively(
1646 const typename Triangulation<dim, spacedim>::cell_iterator &cell_1,
1647 const typename Triangulation<dim, spacedim>::cell_iterator &cell_2,
1648 unsigned int n_face_1,
1649 unsigned int n_face_2,
1650 const unsigned char orientation,
1651 typename std::map<
1653 unsigned int>,
1654 std::pair<std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
1655 unsigned int>,
1656 unsigned char>> &periodic_face_map)
1657 {
1658 using FaceIterator = typename Triangulation<dim, spacedim>::face_iterator;
1659 const FaceIterator face_1 = cell_1->face(n_face_1);
1660 const FaceIterator face_2 = cell_2->face(n_face_2);
1661
1662 const unsigned char inverse_orientation =
1663 face_1->reference_cell().get_inverse_combined_orientation(orientation);
1664
1665#ifdef DEBUG
1666 const auto [face_orientation, face_rotation, face_flip] =
1668
1669 Assert((dim != 1) || (face_orientation == true && face_flip == false &&
1670 face_rotation == false),
1671 ExcMessage("The supplied orientation "
1672 "(face_orientation, face_flip, face_rotation) "
1673 "is invalid for 1d"));
1674
1675 Assert((dim != 2) || (face_flip == false && face_rotation == false),
1676 ExcMessage("The supplied orientation "
1677 "(face_orientation, face_flip, face_rotation) "
1678 "is invalid for 2d"));
1679#endif
1680
1681 Assert(face_1 != face_2, ExcMessage("face_1 and face_2 are equal!"));
1682
1683 Assert(face_1->at_boundary() && face_2->at_boundary(),
1684 ExcMessage("Periodic faces must be on the boundary"));
1685
1686 // Check if the requirement that each edge can only have at most one hanging
1687 // node, and as a consequence neighboring cells can differ by at most
1688 // one refinement level is enforced. In 1d, there are no hanging nodes and
1689 // so neighboring cells can differ by more than one refinement level.
1690 Assert(dim == 1 || std::abs(cell_1->level() - cell_2->level()) < 2,
1692
1693 // insert periodic face pair for both cells
1694 using CellFace =
1695 std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
1696 unsigned int>;
1697 const CellFace cell_face_1(cell_1, n_face_1);
1698 const CellFace cell_face_2(cell_2, n_face_2);
1699 const std::pair<CellFace, unsigned char> cell_face_orientation_2(
1700 cell_face_2, orientation);
1701
1702 const std::pair<CellFace, std::pair<CellFace, unsigned char>>
1703 periodic_faces(cell_face_1, cell_face_orientation_2);
1704
1705 // Only one periodic neighbor is allowed
1706 Assert(periodic_face_map.count(cell_face_1) == 0, ExcInternalError());
1707 periodic_face_map.insert(periodic_faces);
1708
1709 if (dim == 1)
1710 {
1711 if (cell_1->has_children())
1712 {
1713 if (cell_2->has_children())
1714 {
1715 update_periodic_face_map_recursively<dim, spacedim>(
1716 cell_1->child(n_face_1),
1717 cell_2->child(n_face_2),
1718 n_face_1,
1719 n_face_2,
1720 orientation,
1721 periodic_face_map);
1722 }
1723 else // only face_1 has children
1724 {
1725 update_periodic_face_map_recursively<dim, spacedim>(
1726 cell_1->child(n_face_1),
1727 cell_2,
1728 n_face_1,
1729 n_face_2,
1730 orientation,
1731 periodic_face_map);
1732 }
1733 }
1734 }
1735 else // dim == 2 || dim == 3
1736 {
1737 if (cell_1->has_children())
1738 {
1739 if (cell_2->has_children())
1740 {
1741 // In the case that both faces have children, we loop over all
1742 // children and apply update_periodic_face_map_recursively
1743 // recursively:
1744
1745 Assert(face_1->n_children() ==
1747 face_2->n_children() ==
1750
1751 const auto reference_cell = cell_1->reference_cell();
1752
1753 for (unsigned int i = 0;
1754 i < GeometryInfo<dim>::max_children_per_face;
1755 ++i)
1756 {
1757 // Lookup the index for the second face
1758 const unsigned int j =
1759 reference_cell.standard_to_real_face_vertex(
1760 i, n_face_1, inverse_orientation);
1761
1762 // find subcell ids that belong to the subface indices
1763 unsigned int child_cell_1 =
1765 cell_1->refinement_case(),
1766 n_face_1,
1767 i,
1768 cell_1->face_orientation(n_face_1),
1769 cell_1->face_flip(n_face_1),
1770 cell_1->face_rotation(n_face_1),
1771 face_1->refinement_case());
1772 unsigned int child_cell_2 =
1774 cell_2->refinement_case(),
1775 n_face_2,
1776 j,
1777 cell_2->face_orientation(n_face_2),
1778 cell_2->face_flip(n_face_2),
1779 cell_2->face_rotation(n_face_2),
1780 face_2->refinement_case());
1781
1782 Assert(cell_1->child(child_cell_1)->face(n_face_1) ==
1783 face_1->child(i),
1785 Assert(cell_2->child(child_cell_2)->face(n_face_2) ==
1786 face_2->child(j),
1788
1789 // precondition: subcell has the same orientation as cell
1790 // (so that the face numbers coincide) recursive call
1791 update_periodic_face_map_recursively<dim, spacedim>(
1792 cell_1->child(child_cell_1),
1793 cell_2->child(child_cell_2),
1794 n_face_1,
1795 n_face_2,
1796 orientation,
1797 periodic_face_map);
1798 }
1799 }
1800 else // only face_1 has children
1801 {
1802 for (unsigned int i = 0;
1803 i < GeometryInfo<dim>::max_children_per_face;
1804 ++i)
1805 {
1806 // find subcell ids that belong to the subface indices
1807 unsigned int child_cell_1 =
1809 cell_1->refinement_case(),
1810 n_face_1,
1811 i,
1812 cell_1->face_orientation(n_face_1),
1813 cell_1->face_flip(n_face_1),
1814 cell_1->face_rotation(n_face_1),
1815 face_1->refinement_case());
1816
1817 // recursive call
1818 update_periodic_face_map_recursively<dim, spacedim>(
1819 cell_1->child(child_cell_1),
1820 cell_2,
1821 n_face_1,
1822 n_face_2,
1823 orientation,
1824 periodic_face_map);
1825 }
1826 }
1827 }
1828 }
1829 }
1830
1831
1832} // end of anonymous namespace
1833
1834
1835namespace internal
1836{
1837 namespace TriangulationImplementation
1838 {
1839 // make sure that if in the following we
1840 // write Triangulation<dim,spacedim>
1841 // we mean the *class*
1842 // ::Triangulation, not the
1843 // enclosing namespace
1844 // internal::TriangulationImplementation
1845 using ::Triangulation;
1846
1852 int,
1853 << "Something went wrong upon construction of cell "
1854 << arg1);
1865 int,
1866 << "Cell " << arg1
1867 << " has negative measure. This typically "
1868 << "indicates some distortion in the cell, or a mistakenly "
1869 << "swapped pair of vertices in the input to "
1870 << "Triangulation::create_triangulation().");
1879 int,
1880 int,
1881 int,
1882 << "Error while creating cell " << arg1
1883 << ": the vertex index " << arg2 << " must be between 0 and "
1884 << arg3 << '.');
1891 int,
1892 int,
1894 << "The input data for creating a triangulation contained "
1895 << "information about a line with indices " << arg1 << " and " << arg2
1896 << " that is described to have boundary indicator "
1897 << static_cast<int>(arg3)
1898 << ". However, this is an internal line not located on the "
1899 << "boundary. You cannot assign a boundary indicator to it." << std::endl
1900 << std::endl
1901 << "If this happened at a place where you call "
1902 << "Triangulation::create_triangulation() yourself, you need "
1903 << "to check the SubCellData object you pass to this function."
1904 << std::endl
1905 << std::endl
1906 << "If this happened in a place where you are reading a mesh "
1907 << "from a file, then you need to investigate why such a line "
1908 << "ended up in the input file. A typical case is a geometry "
1909 << "that consisted of multiple parts and for which the mesh "
1910 << "generator program assumes that the interface between "
1911 << "two parts is a boundary when that isn't supposed to be "
1912 << "the case, or where the mesh generator simply assigns "
1913 << "'geometry indicators' to lines at the perimeter of "
1914 << "a part that are not supposed to be interpreted as "
1915 << "'boundary indicators'.");
1922 int,
1923 int,
1924 int,
1925 int,
1927 << "The input data for creating a triangulation contained "
1928 << "information about a quad with indices " << arg1 << ", " << arg2
1929 << ", " << arg3 << ", and " << arg4
1930 << " that is described to have boundary indicator "
1931 << static_cast<int>(arg5)
1932 << ". However, this is an internal quad not located on the "
1933 << "boundary. You cannot assign a boundary indicator to it." << std::endl
1934 << std::endl
1935 << "If this happened at a place where you call "
1936 << "Triangulation::create_triangulation() yourself, you need "
1937 << "to check the SubCellData object you pass to this function."
1938 << std::endl
1939 << std::endl
1940 << "If this happened in a place where you are reading a mesh "
1941 << "from a file, then you need to investigate why such a quad "
1942 << "ended up in the input file. A typical case is a geometry "
1943 << "that consisted of multiple parts and for which the mesh "
1944 << "generator program assumes that the interface between "
1945 << "two parts is a boundary when that isn't supposed to be "
1946 << "the case, or where the mesh generator simply assigns "
1947 << "'geometry indicators' to quads at the surface of "
1948 << "a part that are not supposed to be interpreted as "
1949 << "'boundary indicators'.");
1956 int,
1957 int,
1958 << "In SubCellData the line info of the line with vertex indices " << arg1
1959 << " and " << arg2 << " appears more than once. "
1960 << "This is not allowed.");
1967 int,
1968 int,
1969 std::string,
1970 << "In SubCellData the line info of the line with vertex indices " << arg1
1971 << " and " << arg2 << " appears multiple times with different (valid) "
1972 << arg3 << ". This is not allowed.");
1979 int,
1980 int,
1981 int,
1982 int,
1983 std::string,
1984 << "In SubCellData the quad info of the quad with line indices " << arg1
1985 << ", " << arg2 << ", " << arg3 << " and " << arg4
1986 << " appears multiple times with different (valid) " << arg5
1987 << ". This is not allowed.");
1988
1989 /*
1990 * Reserve space for TriaFaces. Details:
1991 *
1992 * Reserve space for line_orientations.
1993 *
1994 * @note Used only for dim=3.
1995 */
1996 void
1998 const unsigned int new_quads_in_pairs,
1999 const unsigned int new_quads_single)
2000 {
2001 AssertDimension(tria_faces.dim, 3);
2002
2003 Assert(new_quads_in_pairs % 2 == 0, ExcInternalError());
2004
2005 unsigned int next_free_single = 0;
2006 unsigned int next_free_pair = 0;
2007
2008 // count the number of objects, of unused single objects and of
2009 // unused pairs of objects
2010 [[maybe_unused]] unsigned int n_quads = 0;
2011 unsigned int n_unused_pairs = 0;
2012 unsigned int n_unused_singles = 0;
2013 for (unsigned int i = 0; i < tria_faces.quads.used.size(); ++i)
2014 {
2015 if (tria_faces.quads.used[i])
2016 ++n_quads;
2017 else if (i + 1 < tria_faces.quads.used.size())
2018 {
2019 if (tria_faces.quads.used[i + 1])
2020 {
2021 ++n_unused_singles;
2022 if (next_free_single == 0)
2023 next_free_single = i;
2024 }
2025 else
2026 {
2027 ++n_unused_pairs;
2028 if (next_free_pair == 0)
2029 next_free_pair = i;
2030 ++i;
2031 }
2032 }
2033 else
2034 ++n_unused_singles;
2035 }
2036 Assert(n_quads + 2 * n_unused_pairs + n_unused_singles ==
2037 tria_faces.quads.used.size(),
2039
2040 // how many single quads are needed in addition to n_unused_quads?
2041 const int additional_single_quads = new_quads_single - n_unused_singles;
2042
2043 unsigned int new_size =
2044 tria_faces.quads.used.size() + new_quads_in_pairs - 2 * n_unused_pairs;
2045 if (additional_single_quads > 0)
2046 new_size += additional_single_quads;
2047
2048 // see above...
2049 if (new_size > tria_faces.quads.n_objects())
2050 {
2051 // reserve the field of the derived class
2052 tria_faces.quads_line_orientations.resize(
2053 new_size * GeometryInfo<3>::lines_per_face, true);
2054
2055 auto &q_is_q = tria_faces.quad_is_quadrilateral;
2056 q_is_q.reserve(new_size);
2057 q_is_q.insert(q_is_q.end(), new_size - q_is_q.size(), true);
2058 }
2059 }
2060
2061
2062
2076 void
2078 const unsigned int total_cells,
2079 const unsigned int dimension,
2080 const unsigned int space_dimension,
2081 const bool tetraheder_in_mesh = false)
2082 {
2083 // we need space for total_cells cells. Maybe we have more already
2084 // with those cells which are unused, so only allocate new space if
2085 // needed.
2086 //
2087 // note that all arrays should have equal sizes (checked by
2088 // @p{monitor_memory}
2089 if (total_cells > tria_level.refine_flags.size())
2090 {
2091 tria_level.refine_flags.reserve(total_cells);
2092 tria_level.refine_flags.insert(tria_level.refine_flags.end(),
2093 total_cells -
2094 tria_level.refine_flags.size(),
2095 /*RefinementCase::no_refinement=*/0);
2096
2097 if (tetraheder_in_mesh)
2098 {
2099 tria_level.refine_choice.reserve(total_cells);
2100 tria_level.refine_choice.insert(
2101 tria_level.refine_choice.end(),
2102 total_cells - tria_level.refine_choice.size(),
2103 static_cast<char>(
2105 }
2106
2107 tria_level.coarsen_flags.reserve(total_cells);
2108 tria_level.coarsen_flags.insert(tria_level.coarsen_flags.end(),
2109 total_cells -
2110 tria_level.coarsen_flags.size(),
2111 false);
2112
2113 tria_level.active_cell_indices.reserve(total_cells);
2114 tria_level.active_cell_indices.insert(
2115 tria_level.active_cell_indices.end(),
2116 total_cells - tria_level.active_cell_indices.size(),
2118
2119 tria_level.subdomain_ids.reserve(total_cells);
2120 tria_level.subdomain_ids.insert(tria_level.subdomain_ids.end(),
2121 total_cells -
2122 tria_level.subdomain_ids.size(),
2123 0);
2124
2125 tria_level.level_subdomain_ids.reserve(total_cells);
2126 tria_level.level_subdomain_ids.insert(
2127 tria_level.level_subdomain_ids.end(),
2128 total_cells - tria_level.level_subdomain_ids.size(),
2129 0);
2130
2131 tria_level.global_active_cell_indices.reserve(total_cells);
2132 tria_level.global_active_cell_indices.insert(
2133 tria_level.global_active_cell_indices.end(),
2134 total_cells - tria_level.global_active_cell_indices.size(),
2136
2137 tria_level.global_level_cell_indices.reserve(total_cells);
2138 tria_level.global_level_cell_indices.insert(
2139 tria_level.global_level_cell_indices.end(),
2140 total_cells - tria_level.global_level_cell_indices.size(),
2142
2143 if (dimension == space_dimension - 1)
2144 {
2145 tria_level.direction_flags.reserve(total_cells);
2146 tria_level.direction_flags.insert(
2147 tria_level.direction_flags.end(),
2148 total_cells - tria_level.direction_flags.size(),
2149 true);
2150 }
2151 else
2152 tria_level.direction_flags.clear();
2153
2154 tria_level.parents.reserve((total_cells + 1) / 2);
2155 tria_level.parents.insert(tria_level.parents.end(),
2156 (total_cells + 1) / 2 -
2157 tria_level.parents.size(),
2158 -1);
2159
2160 tria_level.neighbors.reserve(total_cells * (2 * dimension));
2161 tria_level.neighbors.insert(tria_level.neighbors.end(),
2162 total_cells * (2 * dimension) -
2163 tria_level.neighbors.size(),
2164 std::make_pair(-1, -1));
2165
2166 if (tria_level.dim == 2 || tria_level.dim == 3)
2167 {
2168 const unsigned int max_faces_per_cell = 2 * dimension;
2169 tria_level.face_orientations.resize(total_cells *
2170 max_faces_per_cell);
2171
2172 tria_level.reference_cell.reserve(total_cells);
2173 tria_level.reference_cell.insert(
2174 tria_level.reference_cell.end(),
2175 total_cells - tria_level.reference_cell.size(),
2176 tria_level.dim == 2 ? ReferenceCells::Quadrilateral :
2178 }
2179 }
2180 }
2181
2182
2183
2188 int,
2189 int,
2190 << "The containers have sizes " << arg1 << " and " << arg2
2191 << ", which is not as expected.");
2192
2198 void
2199 monitor_memory(const TriaLevel &tria_level,
2200 const unsigned int true_dimension)
2201 {
2202 Assert(2 * true_dimension * tria_level.refine_flags.size() ==
2203 tria_level.neighbors.size(),
2204 ExcMemoryInexact(tria_level.refine_flags.size(),
2205 tria_level.neighbors.size()));
2206 Assert(2 * true_dimension * tria_level.coarsen_flags.size() ==
2207 tria_level.neighbors.size(),
2208 ExcMemoryInexact(tria_level.coarsen_flags.size(),
2209 tria_level.neighbors.size()));
2210 }
2211
2212
2213
2226 void
2228 const unsigned int new_objects_in_pairs,
2229 const unsigned int new_objects_single = 0)
2230 {
2231 if (tria_objects.structdim <= 2)
2232 {
2233 Assert(new_objects_in_pairs % 2 == 0, ExcInternalError());
2234
2235 tria_objects.next_free_single = 0;
2236 tria_objects.next_free_pair = 0;
2237 tria_objects.reverse_order_next_free_single = false;
2238
2239 // count the number of objects, of unused single objects and of
2240 // unused pairs of objects
2241 [[maybe_unused]] unsigned int n_objects = 0;
2242 unsigned int n_unused_pairs = 0;
2243 unsigned int n_unused_singles = 0;
2244 for (unsigned int i = 0; i < tria_objects.used.size(); ++i)
2245 {
2246 if (tria_objects.used[i])
2247 ++n_objects;
2248 else if (i + 1 < tria_objects.used.size())
2249 {
2250 if (tria_objects.used[i + 1])
2251 {
2252 ++n_unused_singles;
2253 if (tria_objects.next_free_single == 0)
2254 tria_objects.next_free_single = i;
2255 }
2256 else
2257 {
2258 ++n_unused_pairs;
2259 if (tria_objects.next_free_pair == 0)
2260 tria_objects.next_free_pair = i;
2261 ++i;
2262 }
2263 }
2264 else
2265 ++n_unused_singles;
2266 }
2267 Assert(n_objects + 2 * n_unused_pairs + n_unused_singles ==
2268 tria_objects.used.size(),
2270
2271 // how many single objects are needed in addition to
2272 // n_unused_objects?
2273 const int additional_single_objects =
2274 new_objects_single - n_unused_singles;
2275
2276 unsigned int new_size = tria_objects.used.size() +
2277 new_objects_in_pairs - 2 * n_unused_pairs;
2278 if (additional_single_objects > 0)
2279 new_size += additional_single_objects;
2280
2281 // only allocate space if necessary
2282 if (new_size > tria_objects.n_objects())
2283 {
2284 const unsigned int max_faces_per_cell =
2285 2 * tria_objects.structdim;
2286 const unsigned int max_children_per_cell =
2287 1 << tria_objects.structdim;
2288
2289 tria_objects.cells.reserve(new_size * max_faces_per_cell);
2290 tria_objects.cells.insert(tria_objects.cells.end(),
2291 (new_size - tria_objects.n_objects()) *
2292 max_faces_per_cell,
2293 -1);
2294
2295 tria_objects.used.reserve(new_size);
2296 tria_objects.used.insert(tria_objects.used.end(),
2297 new_size - tria_objects.used.size(),
2298 false);
2299
2300 tria_objects.user_flags.reserve(new_size);
2301 tria_objects.user_flags.insert(tria_objects.user_flags.end(),
2302 new_size -
2303 tria_objects.user_flags.size(),
2304 false);
2305
2306 const unsigned int factor = max_children_per_cell / 2;
2307 tria_objects.children.reserve(factor * new_size);
2308 tria_objects.children.insert(tria_objects.children.end(),
2309 factor * new_size -
2310 tria_objects.children.size(),
2311 -1);
2312
2313 if (tria_objects.structdim > 1)
2314 {
2315 tria_objects.refinement_cases.reserve(new_size);
2316 tria_objects.refinement_cases.insert(
2317 tria_objects.refinement_cases.end(),
2318 new_size - tria_objects.refinement_cases.size(),
2319 /*RefinementCase::no_refinement=*/0);
2320 }
2321
2322 // first reserve, then resize. Otherwise the std library can
2323 // decide to allocate more entries.
2324 tria_objects.boundary_or_material_id.reserve(new_size);
2325 tria_objects.boundary_or_material_id.resize(new_size);
2326
2327 tria_objects.user_data.reserve(new_size);
2328 tria_objects.user_data.resize(new_size);
2329
2330 tria_objects.manifold_id.reserve(new_size);
2331 tria_objects.manifold_id.insert(tria_objects.manifold_id.end(),
2332 new_size -
2333 tria_objects.manifold_id.size(),
2335 }
2336
2337 if (n_unused_singles == 0)
2338 {
2339 tria_objects.next_free_single = new_size - 1;
2340 tria_objects.reverse_order_next_free_single = true;
2341 }
2342 }
2343 else
2344 {
2345 const unsigned int new_hexes = new_objects_in_pairs;
2346
2347 const unsigned int new_size =
2348 new_hexes + std::count(tria_objects.used.begin(),
2349 tria_objects.used.end(),
2350 true);
2351
2352 // see above...
2353 if (new_size > tria_objects.n_objects())
2354 {
2355 const unsigned int max_faces_per_cell =
2356 2 * tria_objects.structdim;
2357
2358 tria_objects.cells.reserve(new_size * max_faces_per_cell);
2359 tria_objects.cells.insert(tria_objects.cells.end(),
2360 (new_size - tria_objects.n_objects()) *
2361 max_faces_per_cell,
2362 -1);
2363
2364 tria_objects.used.reserve(new_size);
2365 tria_objects.used.insert(tria_objects.used.end(),
2366 new_size - tria_objects.used.size(),
2367 false);
2368
2369 tria_objects.user_flags.reserve(new_size);
2370 tria_objects.user_flags.insert(tria_objects.user_flags.end(),
2371 new_size -
2372 tria_objects.user_flags.size(),
2373 false);
2374
2375 tria_objects.children.reserve(4 * new_size);
2376 tria_objects.children.insert(tria_objects.children.end(),
2377 4 * new_size -
2378 tria_objects.children.size(),
2379 -1);
2380
2381 // for the following fields, we know exactly how many elements
2382 // we need, so first reserve then resize (resize itself, at least
2383 // with some compiler libraries, appears to round up the size it
2384 // actually reserves)
2385 tria_objects.boundary_or_material_id.reserve(new_size);
2386 tria_objects.boundary_or_material_id.resize(new_size);
2387
2388 tria_objects.manifold_id.reserve(new_size);
2389 tria_objects.manifold_id.insert(tria_objects.manifold_id.end(),
2390 new_size -
2391 tria_objects.manifold_id.size(),
2393
2394 tria_objects.user_data.reserve(new_size);
2395 tria_objects.user_data.resize(new_size);
2396
2397 tria_objects.refinement_cases.reserve(new_size);
2398 tria_objects.refinement_cases.insert(
2399 tria_objects.refinement_cases.end(),
2400 new_size - tria_objects.refinement_cases.size(),
2401 /*RefinementCase::no_refinement=*/0);
2402 }
2403 tria_objects.next_free_single = tria_objects.next_free_pair = 0;
2404 }
2405 }
2406
2407
2408
2414 void
2415 monitor_memory(const TriaObjects &tria_object, const unsigned int)
2416 {
2417 Assert(tria_object.n_objects() == tria_object.used.size(),
2418 ExcMemoryInexact(tria_object.n_objects(),
2419 tria_object.used.size()));
2420 Assert(tria_object.n_objects() == tria_object.user_flags.size(),
2421 ExcMemoryInexact(tria_object.n_objects(),
2422 tria_object.user_flags.size()));
2423 Assert(tria_object.n_objects() ==
2424 tria_object.boundary_or_material_id.size(),
2425 ExcMemoryInexact(tria_object.n_objects(),
2426 tria_object.boundary_or_material_id.size()));
2427 Assert(tria_object.n_objects() == tria_object.manifold_id.size(),
2428 ExcMemoryInexact(tria_object.n_objects(),
2429 tria_object.manifold_id.size()));
2430 Assert(tria_object.n_objects() == tria_object.user_data.size(),
2431 ExcMemoryInexact(tria_object.n_objects(),
2432 tria_object.user_data.size()));
2433
2434 if (tria_object.structdim == 1)
2435 {
2436 Assert(1 * tria_object.n_objects() == tria_object.children.size(),
2437 ExcMemoryInexact(tria_object.n_objects(),
2438 tria_object.children.size()));
2439 }
2440 else if (tria_object.structdim == 2)
2441 {
2442 Assert(2 * tria_object.n_objects() == tria_object.children.size(),
2443 ExcMemoryInexact(tria_object.n_objects(),
2444 tria_object.children.size()));
2445 }
2446 else if (tria_object.structdim == 3)
2447 {
2448 Assert(4 * tria_object.n_objects() == tria_object.children.size(),
2449 ExcMemoryInexact(tria_object.n_objects(),
2450 tria_object.children.size()));
2451 }
2452 }
2453
2454
2455
2460 template <int dim, int spacedim>
2462 {
2463 public:
2467 virtual ~Policy() = default;
2468
2472 virtual void
2474
2478 virtual void
2482 std::vector<unsigned int> &line_cell_count,
2483 std::vector<unsigned int> &quad_cell_count) = 0;
2484
2490 const bool check_for_distorted_cells) = 0;
2491
2495 virtual void
2498
2502 virtual void
2505
2509 virtual bool
2511 const typename Triangulation<dim, spacedim>::cell_iterator &cell) = 0;
2512
2519 virtual std::unique_ptr<Policy<dim, spacedim>>
2520 clone() = 0;
2521 };
2522
2523
2524
2530 template <int dim, int spacedim, typename T>
2531 class PolicyWrapper : public Policy<dim, spacedim>
2532 {
2533 public:
2534 void
2536 {
2537 T::update_neighbors(tria);
2538 }
2539
2540 void
2544 std::vector<unsigned int> &line_cell_count,
2545 std::vector<unsigned int> &quad_cell_count) override
2546 {
2547 T::delete_children(tria, cell, line_cell_count, quad_cell_count);
2548 }
2549
2552 const bool check_for_distorted_cells) override
2553 {
2554 return T::execute_refinement(triangulation, check_for_distorted_cells);
2555 }
2556
2557 void
2560 {
2561 T::prevent_distorted_boundary_cells(triangulation);
2562 }
2563
2564 void
2567 {
2568 T::prepare_refinement_dim_dependent(triangulation);
2569 }
2570
2571 bool
2574 override
2575 {
2576 return T::template coarsening_allowed<dim, spacedim>(cell);
2577 }
2578
2579 std::unique_ptr<Policy<dim, spacedim>>
2580 clone() override
2581 {
2582 return std::make_unique<PolicyWrapper<dim, spacedim, T>>();
2583 }
2584 };
2585
2586
2587
2684 {
2696 template <int dim, int spacedim>
2697 static void
2700 const unsigned int level_objects,
2702 {
2703 using line_iterator =
2705
2706 number_cache.n_levels = 0;
2707 if (level_objects > 0)
2708 // find the last level on which there are used cells
2709 for (unsigned int level = 0; level < level_objects; ++level)
2710 if (triangulation.begin(level) != triangulation.end(level))
2711 number_cache.n_levels = level + 1;
2712
2713 // no cells at all?
2714 Assert(number_cache.n_levels > 0, ExcInternalError());
2715
2716 //---------------------------------
2717 // update the number of lines on the different levels in the
2718 // cache
2719 number_cache.n_lines = 0;
2720 number_cache.n_active_lines = 0;
2721
2722 // for 1d, lines have levels so take count the objects per
2723 // level and globally
2724 if (dim == 1)
2725 {
2726 number_cache.n_lines_level.resize(number_cache.n_levels);
2727 number_cache.n_active_lines_level.resize(number_cache.n_levels);
2728
2729 for (unsigned int level = 0; level < number_cache.n_levels; ++level)
2730 {
2731 // count lines on this level
2732 number_cache.n_lines_level[level] = 0;
2733 number_cache.n_active_lines_level[level] = 0;
2734
2735 line_iterator line = triangulation.begin_line(level),
2736 endc =
2737 (level == number_cache.n_levels - 1 ?
2738 line_iterator(triangulation.end_line()) :
2739 triangulation.begin_line(level + 1));
2740 for (; line != endc; ++line)
2741 {
2742 ++number_cache.n_lines_level[level];
2743 if (line->has_children() == false)
2744 ++number_cache.n_active_lines_level[level];
2745 }
2746
2747 // update total number of lines
2748 number_cache.n_lines += number_cache.n_lines_level[level];
2749 number_cache.n_active_lines +=
2750 number_cache.n_active_lines_level[level];
2751 }
2752 }
2753 else
2754 {
2755 // for dim>1, there are no levels for lines
2756 number_cache.n_lines_level.clear();
2757 number_cache.n_active_lines_level.clear();
2758
2759 line_iterator line = triangulation.begin_line(),
2760 endc = triangulation.end_line();
2761 for (; line != endc; ++line)
2762 {
2763 ++number_cache.n_lines;
2764 if (line->has_children() == false)
2765 ++number_cache.n_active_lines;
2766 }
2767 }
2768 }
2769
2784 template <int dim, int spacedim>
2785 static void
2788 const unsigned int level_objects,
2790 {
2791 // update lines and n_levels in number_cache. since we don't
2792 // access any of these numbers, we can do this in the
2793 // background
2795 static_cast<
2796 void (*)(const Triangulation<dim, spacedim> &,
2797 const unsigned int,
2799 &compute_number_cache_dim<dim, spacedim>),
2801 level_objects,
2803 number_cache));
2804
2805 using quad_iterator =
2807
2808 //---------------------------------
2809 // update the number of quads on the different levels in the
2810 // cache
2811 number_cache.n_quads = 0;
2812 number_cache.n_active_quads = 0;
2813
2814 // for 2d, quads have levels so take count the objects per
2815 // level and globally
2816 if (dim == 2)
2817 {
2818 // count the number of levels; the function we called above
2819 // on a separate Task for lines also does this and puts it into
2820 // number_cache.n_levels, but this datum may not yet be
2821 // available as we call the function on a separate task
2822 unsigned int n_levels = 0;
2823 if (level_objects > 0)
2824 // find the last level on which there are used cells
2825 for (unsigned int level = 0; level < level_objects; ++level)
2826 if (triangulation.begin(level) != triangulation.end(level))
2827 n_levels = level + 1;
2828
2829 number_cache.n_quads_level.resize(n_levels);
2830 number_cache.n_active_quads_level.resize(n_levels);
2831
2832 for (unsigned int level = 0; level < n_levels; ++level)
2833 {
2834 // count quads on this level
2835 number_cache.n_quads_level[level] = 0;
2836 number_cache.n_active_quads_level[level] = 0;
2837
2838 quad_iterator quad = triangulation.begin_quad(level),
2839 endc =
2840 (level == n_levels - 1 ?
2841 quad_iterator(triangulation.end_quad()) :
2842 triangulation.begin_quad(level + 1));
2843 for (; quad != endc; ++quad)
2844 {
2845 ++number_cache.n_quads_level[level];
2846 if (quad->has_children() == false)
2847 ++number_cache.n_active_quads_level[level];
2848 }
2849
2850 // update total number of quads
2851 number_cache.n_quads += number_cache.n_quads_level[level];
2852 number_cache.n_active_quads +=
2853 number_cache.n_active_quads_level[level];
2854 }
2855 }
2856 else
2857 {
2858 // for dim>2, there are no levels for quads
2859 number_cache.n_quads_level.clear();
2860 number_cache.n_active_quads_level.clear();
2861
2862 quad_iterator quad = triangulation.begin_quad(),
2863 endc = triangulation.end_quad();
2864 for (; quad != endc; ++quad)
2865 {
2866 ++number_cache.n_quads;
2867 if (quad->has_children() == false)
2868 ++number_cache.n_active_quads;
2869 }
2870 }
2871
2872 // wait for the background computation for lines
2873 update_lines.join();
2874 }
2875
2891 template <int dim, int spacedim>
2892 static void
2895 const unsigned int level_objects,
2897 {
2898 // update quads, lines and n_levels in number_cache. since we
2899 // don't access any of these numbers, we can do this in the
2900 // background
2901 Threads::Task<void> update_quads_and_lines = Threads::new_task(
2902 static_cast<
2903 void (*)(const Triangulation<dim, spacedim> &,
2904 const unsigned int,
2906 &compute_number_cache_dim<dim, spacedim>),
2908 level_objects,
2910 number_cache));
2911
2912 using hex_iterator =
2914
2915 //---------------------------------
2916 // update the number of hexes on the different levels in the
2917 // cache
2918 number_cache.n_hexes = 0;
2919 number_cache.n_active_hexes = 0;
2920
2921 // for 3d, hexes have levels so take count the objects per
2922 // level and globally
2923 if (dim == 3)
2924 {
2925 // count the number of levels; the function we called
2926 // above on a separate Task for quads (recursively, via
2927 // the lines function) also does this and puts it into
2928 // number_cache.n_levels, but this datum may not yet be
2929 // available as we call the function on a separate task
2930 unsigned int n_levels = 0;
2931 if (level_objects > 0)
2932 // find the last level on which there are used cells
2933 for (unsigned int level = 0; level < level_objects; ++level)
2934 if (triangulation.begin(level) != triangulation.end(level))
2935 n_levels = level + 1;
2936
2937 number_cache.n_hexes_level.resize(n_levels);
2938 number_cache.n_active_hexes_level.resize(n_levels);
2939
2940 for (unsigned int level = 0; level < n_levels; ++level)
2941 {
2942 // count hexes on this level
2943 number_cache.n_hexes_level[level] = 0;
2944 number_cache.n_active_hexes_level[level] = 0;
2945
2946 hex_iterator hex = triangulation.begin_hex(level),
2947 endc = (level == n_levels - 1 ?
2948 hex_iterator(triangulation.end_hex()) :
2949 triangulation.begin_hex(level + 1));
2950 for (; hex != endc; ++hex)
2951 {
2952 ++number_cache.n_hexes_level[level];
2953 if (hex->has_children() == false)
2954 ++number_cache.n_active_hexes_level[level];
2955 }
2956
2957 // update total number of hexes
2958 number_cache.n_hexes += number_cache.n_hexes_level[level];
2959 number_cache.n_active_hexes +=
2960 number_cache.n_active_hexes_level[level];
2961 }
2962 }
2963 else
2964 {
2965 // for dim>3, there are no levels for hexes
2966 number_cache.n_hexes_level.clear();
2967 number_cache.n_active_hexes_level.clear();
2968
2969 hex_iterator hex = triangulation.begin_hex(),
2970 endc = triangulation.end_hex();
2971 for (; hex != endc; ++hex)
2972 {
2973 ++number_cache.n_hexes;
2974 if (hex->has_children() == false)
2975 ++number_cache.n_active_hexes;
2976 }
2977 }
2978
2979 // wait for the background computation for quads
2980 update_quads_and_lines.join();
2981 }
2982
2983
2984 template <int dim, int spacedim>
2985 static void
2988 const unsigned int level_objects,
2990 {
2991 compute_number_cache_dim(triangulation, level_objects, number_cache);
2992
2993 number_cache.active_cell_index_partitioner =
2994 std::make_shared<const Utilities::MPI::Partitioner>(
2995 triangulation.n_active_cells());
2996
2997 number_cache.level_cell_index_partitioners.resize(
2998 triangulation.n_levels());
2999 for (unsigned int level = 0; level < triangulation.n_levels(); ++level)
3000 number_cache.level_cell_index_partitioners[level] =
3001 std::make_shared<const Utilities::MPI::Partitioner>(
3002 triangulation.n_cells(level));
3003 }
3004
3005
3006 template <int spacedim>
3007 static void
3010
3011
3012 template <int dim, int spacedim>
3013 static void
3015 {
3016 // each face can be neighbored on two sides
3017 // by cells. according to the face's
3018 // intrinsic normal we define the left
3019 // neighbor as the one for which the face
3020 // normal points outward, and store that
3021 // one first; the second one is then
3022 // the right neighbor for which the
3023 // face normal points inward. This
3024 // information depends on the type of cell
3025 // and local number of face for the
3026 // 'standard ordering and orientation' of
3027 // faces and then on the face_orientation
3028 // information for the real mesh. Set up a
3029 // table to have fast access to those
3030 // offsets (0 for left and 1 for
3031 // right). Some of the values are invalid
3032 // as they reference too large face
3033 // numbers, but we just leave them at a
3034 // zero value.
3035 //
3036 // Note, that in 2d for lines as faces the
3037 // normal direction given in the
3038 // GeometryInfo class is not consistent. We
3039 // thus define here that the normal for a
3040 // line points to the right if the line
3041 // points upwards.
3042 //
3043 // There is one more point to
3044 // consider, however: if we have
3045 // dim<spacedim, then we may have
3046 // cases where cells are
3047 // inverted. In effect, both
3048 // cells think they are the left
3049 // neighbor of an edge, for
3050 // example, which leads us to
3051 // forget neighborship
3052 // information (a case that shows
3053 // this is
3054 // codim_one/hanging_nodes_02). We
3055 // store whether a cell is
3056 // inverted using the
3057 // direction_flag, so if a cell
3058 // has a false direction_flag,
3059 // then we need to invert our
3060 // selection whether we are a
3061 // left or right neighbor in all
3062 // following computations.
3063 //
3064 // first index: dimension (minus 2)
3065 // second index: local face index
3066 // third index: face_orientation (false and true)
3067 static const unsigned int left_right_offset[2][6][2] = {
3068 // quadrilateral
3069 {{0, 1}, // face 0, face_orientation = false and true
3070 {1, 0}, // face 1, face_orientation = false and true
3071 {1, 0}, // face 2, face_orientation = false and true
3072 {0, 1}, // face 3, face_orientation = false and true
3073 {0, 0}, // face 4, invalid face
3074 {0, 0}}, // face 5, invalid face
3075 // hexahedron
3076 {{0, 1}, {1, 0}, {0, 1}, {1, 0}, {0, 1}, {1, 0}}};
3077
3078 // now create a vector of the two active
3079 // neighbors (left and right) for each face
3080 // and fill it by looping over all cells. For
3081 // cases with anisotropic refinement and more
3082 // then one cell neighboring at a given side
3083 // of the face we will automatically get the
3084 // active one on the highest level as we loop
3085 // over cells from lower levels first.
3087 std::vector<typename Triangulation<dim, spacedim>::cell_iterator>
3088 adjacent_cells(2 * triangulation.n_raw_faces(), dummy);
3089
3090 for (const auto &cell : triangulation.cell_iterators())
3091 for (auto f : cell->face_indices())
3092 {
3094 cell->face(f);
3095
3096 const unsigned int offset =
3097 (cell->direction_flag() ?
3098 left_right_offset[dim - 2][f][cell->face_orientation(f)] :
3099 1 -
3100 left_right_offset[dim - 2][f][cell->face_orientation(f)]);
3101
3102 adjacent_cells[2 * face->index() + offset] = cell;
3103
3104 // if this cell is not refined, but the
3105 // face is, then we'll have to set our
3106 // cell as neighbor for the child faces
3107 // as well. Fortunately the normal
3108 // orientation of children will be just
3109 // the same.
3110 if (dim == 2)
3111 {
3112 if (cell->is_active() && face->has_children())
3113 {
3114 adjacent_cells[2 * face->child(0)->index() + offset] =
3115 cell;
3116 adjacent_cells[2 * face->child(1)->index() + offset] =
3117 cell;
3118 }
3119 }
3120 else // -> dim == 3
3121 {
3122 // We need the same as in 2d
3123 // here. Furthermore, if the face is
3124 // refined with cut_x or cut_y then
3125 // those children again in the other
3126 // direction, and if this cell is
3127 // refined isotropically (along the
3128 // face) then the neighbor will
3129 // (probably) be refined as cut_x or
3130 // cut_y along the face. For those
3131 // neighboring children cells, their
3132 // neighbor will be the current,
3133 // inactive cell, as our children are
3134 // too fine to be neighbors. Catch that
3135 // case by also acting on inactive
3136 // cells with isotropic refinement
3137 // along the face. If the situation
3138 // described is not present, the data
3139 // will be overwritten later on when we
3140 // visit cells on finer levels, so no
3141 // harm will be done.
3142 if (face->has_children() &&
3143 (cell->is_active() ||
3145 cell->refinement_case(), f) ==
3147 {
3148 for (unsigned int c = 0; c < face->n_children(); ++c)
3149 adjacent_cells[2 * face->child(c)->index() + offset] =
3150 cell;
3151 if (face->child(0)->has_children())
3152 {
3153 adjacent_cells[2 * face->child(0)->child(0)->index() +
3154 offset] = cell;
3155 adjacent_cells[2 * face->child(0)->child(1)->index() +
3156 offset] = cell;
3157 }
3158 if (face->child(1)->has_children())
3159 {
3160 adjacent_cells[2 * face->child(1)->child(0)->index() +
3161 offset] = cell;
3162 adjacent_cells[2 * face->child(1)->child(1)->index() +
3163 offset] = cell;
3164 }
3165 } // if cell active and face refined
3166 } // else -> dim==3
3167 } // for all faces of all cells
3168
3169 // now loop again over all cells and set the
3170 // corresponding neighbor cell. Note, that we
3171 // have to use the opposite of the
3172 // left_right_offset in this case as we want
3173 // the offset of the neighbor, not our own.
3174 for (const auto &cell : triangulation.cell_iterators())
3175 for (auto f : cell->face_indices())
3176 {
3177 const unsigned int offset =
3178 (cell->direction_flag() ?
3179 left_right_offset[dim - 2][f][cell->face_orientation(f)] :
3180 1 -
3181 left_right_offset[dim - 2][f][cell->face_orientation(f)]);
3182 cell->set_neighbor(
3183 f, adjacent_cells[2 * cell->face(f)->index() + 1 - offset]);
3184 }
3185 }
3186
3187
3191 template <int dim, int spacedim>
3192 static void
3193 create_triangulation(const std::vector<Point<spacedim>> &vertices,
3194 const std::vector<CellData<dim>> &cells,
3195 const SubCellData &subcelldata,
3197 {
3198 AssertThrow(vertices.size() > 0, ExcMessage("No vertices given"));
3199 AssertThrow(cells.size() > 0, ExcMessage("No cells given"));
3200
3201 // Check that all cells have positive volume.
3202#ifndef _MSC_VER
3203 // TODO: The following code does not compile with MSVC. Find a way
3204 // around it
3205 if (dim == spacedim)
3206 for (unsigned int cell_no = 0; cell_no < cells.size(); ++cell_no)
3207 {
3208 // If we should check for distorted cells, then we permit them
3209 // to exist. If a cell has negative measure, then it must be
3210 // distorted (the converse is not necessarily true); hence
3211 // throw an exception if no such cells should exist.
3213 {
3214 const double cell_measure = GridTools::cell_measure<spacedim>(
3215 vertices,
3216 ArrayView<const unsigned int>(cells[cell_no].vertices));
3217 AssertThrow(cell_measure > 0, ExcGridHasInvalidCell(cell_no));
3218 }
3219 }
3220#endif
3221
3222 // clear old content
3223 tria.levels.clear();
3224 tria.levels.push_back(
3225 std::make_unique<
3227
3228 if (dim > 1)
3229 tria.faces = std::make_unique<
3231
3232 // copy vertices
3233 tria.vertices = vertices;
3234 tria.vertices_used.assign(vertices.size(), true);
3235
3236 // compute connectivity
3237 const auto connectivity = build_connectivity<unsigned int>(cells);
3238 const unsigned int n_cell = cells.size();
3239
3240 // TriaObjects: lines
3241 if (dim >= 2)
3242 {
3243 auto &lines_0 = tria.faces->lines; // data structure to be filled
3244
3245 // get connectivity between quads and lines
3246 const auto &crs = connectivity.entity_to_entities(1, 0);
3247 const unsigned int n_lines = crs.ptr.size() - 1;
3248
3249 // allocate memory
3250 reserve_space_(lines_0, n_lines);
3251
3252 // loop over lines
3253 for (unsigned int line = 0; line < n_lines; ++line)
3254 for (unsigned int i = crs.ptr[line], j = 0; i < crs.ptr[line + 1];
3255 ++i, ++j)
3256 lines_0.cells[line * GeometryInfo<1>::faces_per_cell + j] =
3257 crs.col[i]; // set vertex indices
3258 }
3259
3260 // TriaObjects: quads
3261 if (dim == 3)
3262 {
3263 auto &quads_0 = tria.faces->quads; // data structures to be filled
3264 auto &faces = *tria.faces;
3265
3266 // get connectivity between quads and lines
3267 const auto &crs = connectivity.entity_to_entities(2, 1);
3268 const unsigned int n_quads = crs.ptr.size() - 1;
3269
3270 // allocate memory
3271 reserve_space_(quads_0, n_quads);
3272 reserve_space_(faces, 2 /*structdim*/, n_quads);
3273
3274 // loop over all quads -> entity type, line indices/orientations
3275 for (unsigned int q = 0, k = 0; q < n_quads; ++q)
3276 {
3277 // set entity type of quads
3278 faces.set_quad_type(q, connectivity.entity_types(2)[q]);
3279
3280 // loop over all its lines
3281 for (unsigned int i = crs.ptr[q], j = 0; i < crs.ptr[q + 1];
3282 ++i, ++j, ++k)
3283 {
3284 // set line index
3285 quads_0.cells[q * GeometryInfo<3>::lines_per_face + j] =
3286 crs.col[i];
3287
3288 // set line orientations
3289 const unsigned char combined_orientation =
3290 connectivity.entity_orientations(1)
3291 .get_combined_orientation(k);
3292 // it doesn't make sense to set any flags except
3293 // orientation for a line
3294 Assert(
3295 combined_orientation ==
3297 combined_orientation ==
3300 faces.quads_line_orientations
3302 combined_orientation ==
3304 }
3305 }
3306 }
3307
3308 // TriaObjects/TriaLevel: cell
3309 {
3310 auto &cells_0 = tria.levels[0]->cells; // data structure to be filled
3311 auto &level = *tria.levels[0];
3312
3313 // get connectivity between cells/faces and cells/cells
3314 const auto &crs = connectivity.entity_to_entities(dim, dim - 1);
3315 const auto &nei = connectivity.entity_to_entities(dim, dim);
3316
3317 // in 2d optional: since in in pure QUAD meshes same line
3318 // orientations can be guaranteed
3319 bool orientation_needed = false;
3320 if (dim == 3)
3321 orientation_needed = true;
3322 else if (dim == 2)
3323 {
3324 const auto &orientations = connectivity.entity_orientations(1);
3325 for (unsigned int i = 0; i < orientations.n_objects(); ++i)
3326 if (orientations.get_combined_orientation(i) !=
3328 {
3329 orientation_needed = true;
3330 break;
3331 }
3332 }
3333
3334 // allocate memory
3335 reserve_space_(cells_0, n_cell);
3336 reserve_space_(level, spacedim, n_cell, orientation_needed);
3337
3338 // loop over all cells
3339 for (unsigned int cell = 0; cell < n_cell; ++cell)
3340 {
3341 // set material ids
3342 cells_0.boundary_or_material_id[cell].material_id =
3343 cells[cell].material_id;
3344
3345 // set manifold ids
3346 cells_0.manifold_id[cell] = cells[cell].manifold_id;
3347
3348 // set entity types
3349 level.reference_cell[cell] = connectivity.entity_types(dim)[cell];
3350
3351 // loop over faces
3352 for (unsigned int i = crs.ptr[cell], j = 0; i < crs.ptr[cell + 1];
3353 ++i, ++j)
3354 {
3355 // set neighbor if not at boundary
3356 if (nei.col[i] != static_cast<unsigned int>(-1))
3357 level.neighbors[cell * GeometryInfo<dim>::faces_per_cell +
3358 j] = {0, nei.col[i]};
3359
3360 // set face indices
3361 cells_0.cells[cell * GeometryInfo<dim>::faces_per_cell + j] =
3362 crs.col[i];
3363
3364 // set face orientation if needed
3365 if (orientation_needed)
3366 {
3367 level.face_orientations.set_combined_orientation(
3369 connectivity.entity_orientations(dim - 1)
3370 .get_combined_orientation(i));
3371 }
3372 }
3373 }
3374 }
3375
3376 // TriaFaces: boundary id of boundary faces
3377 if (dim > 1)
3378 {
3379 auto &bids_face = dim == 3 ?
3380 tria.faces->quads.boundary_or_material_id :
3381 tria.faces->lines.boundary_or_material_id;
3382
3383 // count number of cells a face is belonging to
3384 std::vector<unsigned int> count(bids_face.size(), 0);
3385
3386 // get connectivity between cells/faces
3387 const auto &crs = connectivity.entity_to_entities(dim, dim - 1);
3388
3389 // count how many cells are adjacent to the same face
3390 for (unsigned int cell = 0; cell < cells.size(); ++cell)
3391 for (unsigned int i = crs.ptr[cell]; i < crs.ptr[cell + 1]; ++i)
3392 count[crs.col[i]]++;
3393
3394 // loop over all faces
3395 for (unsigned int face = 0; face < count.size(); ++face)
3396 {
3397 if (count[face] != 1) // inner face
3398 continue;
3399
3400 // boundary faces ...
3401 bids_face[face].boundary_id = 0;
3402
3403 if (dim != 3)
3404 continue;
3405
3406 // ... and the lines of quads in 3d
3407 const auto &crs = connectivity.entity_to_entities(2, 1);
3408 for (unsigned int i = crs.ptr[face]; i < crs.ptr[face + 1]; ++i)
3409 tria.faces->lines.boundary_or_material_id[crs.col[i]]
3410 .boundary_id = 0;
3411 }
3412 }
3413 else // 1d
3414 {
3415 static const unsigned int t_tba = static_cast<unsigned int>(-1);
3416 static const unsigned int t_inner = static_cast<unsigned int>(-2);
3417
3418 std::vector<unsigned int> type(vertices.size(), t_tba);
3419
3420 const auto &crs = connectivity.entity_to_entities(1, 0);
3421
3422 for (unsigned int cell = 0; cell < cells.size(); ++cell)
3423 for (unsigned int i = crs.ptr[cell], j = 0; i < crs.ptr[cell + 1];
3424 ++i, ++j)
3425 if (type[crs.col[i]] != t_inner)
3426 type[crs.col[i]] = type[crs.col[i]] == t_tba ? j : t_inner;
3427
3428 for (unsigned int face = 0; face < type.size(); ++face)
3429 {
3430 // note: we also treat manifolds here!?
3431 (*tria.vertex_to_manifold_id_map_1d)[face] =
3433 if (type[face] != t_inner && type[face] != t_tba)
3434 (*tria.vertex_to_boundary_id_map_1d)[face] = type[face];
3435 }
3436 }
3437
3438 // SubCellData: line
3439 if (dim >= 2)
3440 process_subcelldata(connectivity.entity_to_entities(1, 0),
3441 tria.faces->lines,
3442 subcelldata.boundary_lines,
3443 vertices);
3444
3445 // SubCellData: quad
3446 if (dim == 3)
3447 process_subcelldata(connectivity.entity_to_entities(2, 0),
3448 tria.faces->quads,
3449 subcelldata.boundary_quads,
3450 vertices);
3451 }
3452
3453
3454 template <int structdim, int spacedim, typename T>
3455 static void
3457 const CRS<T> &crs,
3458 TriaObjects &obj,
3459 const std::vector<CellData<structdim>> &boundary_objects_in,
3460 const std::vector<Point<spacedim>> &vertex_locations)
3461 {
3462 AssertDimension(obj.structdim, structdim);
3463
3464 if (boundary_objects_in.empty())
3465 return; // empty subcelldata -> nothing to do
3466
3467 // pre-sort subcelldata
3468 auto boundary_objects = boundary_objects_in;
3469
3470 // ... sort vertices
3471 for (auto &boundary_object : boundary_objects)
3472 std::sort(boundary_object.vertices.begin(),
3473 boundary_object.vertices.end());
3474
3475 // ... sort cells
3476 std::sort(boundary_objects.begin(),
3477 boundary_objects.end(),
3478 [](const auto &a, const auto &b) {
3479 return a.vertices < b.vertices;
3480 });
3481
3482 [[maybe_unused]] unsigned int counter = 0;
3483
3484 std::vector<unsigned int> key;
3486
3487 for (unsigned int o = 0; o < obj.n_objects(); ++o)
3488 {
3489 auto &boundary_id = obj.boundary_or_material_id[o].boundary_id;
3490 auto &manifold_id = obj.manifold_id[o];
3491
3492 // assert that object has not been visited yet and its value
3493 // has not been modified yet
3494 AssertThrow(boundary_id == 0 ||
3499
3500 // create key
3501 key.assign(crs.col.data() + crs.ptr[o],
3502 crs.col.data() + crs.ptr[o + 1]);
3503 std::sort(key.begin(), key.end());
3504
3505 // is subcelldata provided? -> binary search
3506 const auto subcell_object =
3507 std::lower_bound(boundary_objects.begin(),
3508 boundary_objects.end(),
3509 key,
3510 [&](const auto &cell, const auto &key) {
3511 return cell.vertices < key;
3512 });
3513
3514 // no subcelldata provided for this object
3515 if (subcell_object == boundary_objects.end() ||
3516 subcell_object->vertices != key)
3517 continue;
3518
3519 ++counter;
3520
3521 // set manifold id
3522 manifold_id = subcell_object->manifold_id;
3523
3524 // set boundary id
3525 if (subcell_object->boundary_id !=
3527 {
3530 ExcMessage(
3531 "The input arguments for creating a triangulation "
3532 "specified a boundary id for an internal face. This "
3533 "is not allowed."
3534 "\n\n"
3535 "The object in question has vertex indices " +
3536 [subcell_object]() {
3537 std::string s;
3538 for (const auto v : subcell_object->vertices)
3539 s += std::to_string(v) + ',';
3540 return s;
3541 }() +
3542 " which are located at coordinates " +
3543 [vertex_locations, subcell_object]() {
3544 std::ostringstream s;
3545 for (unsigned int i = 0;
3546 i < subcell_object->vertices.size();
3547 ++i)
3548 s << '('
3549 << vertex_locations[subcell_object->vertices[i]]
3550 << (i != subcell_object->vertices.size() - 1 ? "), " :
3551 ")");
3552 return s.str();
3553 }() +
3554 "."));
3555 boundary_id = subcell_object->boundary_id;
3556 }
3557 }
3558
3559 // make sure that all subcelldata entries have been processed
3560 // TODO: this is not guaranteed, why?
3561 // AssertDimension(counter, boundary_objects_in.size());
3562 }
3563
3564
3565
3566 static void
3568 const unsigned structdim,
3569 const unsigned int size)
3570 {
3571 const unsigned int dim = faces.dim;
3572
3573 const unsigned int max_lines_per_face = 2 * structdim;
3574
3575 if (dim == 3 && structdim == 2)
3576 {
3577 // quad entity types
3578 faces.quad_is_quadrilateral.assign(size, true);
3579
3580 // quad line orientations
3581 faces.quads_line_orientations.assign(size * max_lines_per_face,
3582 true);
3583 }
3584 }
3585
3586
3587
3588 static void
3590 const unsigned int spacedim,
3591 const unsigned int size,
3592 const bool orientation_needed)
3593 {
3594 const unsigned int dim = level.dim;
3595
3596 const unsigned int max_faces_per_cell = 2 * dim;
3597
3598 level.active_cell_indices.assign(size, numbers::invalid_unsigned_int);
3599 level.subdomain_ids.assign(size, 0);
3600 level.level_subdomain_ids.assign(size, 0);
3601
3602 level.refine_flags.assign(size, 0u);
3603 level.refine_choice.assign(size, 0u);
3604 level.coarsen_flags.assign(size, false);
3605
3606 level.parents.assign((size + 1) / 2, -1);
3607
3608 if (dim == spacedim - 1)
3609 level.direction_flags.assign(size, true);
3610
3611 level.neighbors.assign(size * max_faces_per_cell, {-1, -1});
3612
3613 level.reference_cell.assign(size, ReferenceCells::Invalid);
3614
3615 if (orientation_needed)
3616 level.face_orientations.reinit(size * max_faces_per_cell);
3617
3618
3619 level.global_active_cell_indices.assign(size,
3621 level.global_level_cell_indices.assign(size,
3623 }
3624
3625
3626
3627 static void
3628 reserve_space_(TriaObjects &obj, const unsigned int size)
3629 {
3630 const unsigned int structdim = obj.structdim;
3631
3632 const unsigned int max_children_per_cell = 1 << structdim;
3633 const unsigned int max_faces_per_cell = 2 * structdim;
3634
3635 obj.used.assign(size, true);
3636 obj.boundary_or_material_id.assign(
3637 size,
3639 BoundaryOrMaterialId());
3640 obj.manifold_id.assign(size, -1);
3641 obj.user_flags.assign(size, false);
3642 obj.user_data.resize(size);
3643
3644 if (structdim > 1) // TODO: why?
3645 obj.refinement_cases.assign(size, 0);
3646
3647 obj.children.assign(max_children_per_cell / 2 * size, -1);
3648
3649 obj.cells.assign(max_faces_per_cell * size, -1);
3650
3651 if (structdim <= 2)
3652 {
3653 obj.next_free_single = size - 1;
3654 obj.next_free_pair = 0;
3656 }
3657 else
3658 {
3659 obj.next_free_single = obj.next_free_pair = 0;
3660 }
3661 }
3662
3663
3679 template <int spacedim>
3680 static void
3683 std::vector<unsigned int> &,
3684 std::vector<unsigned int> &)
3685 {
3686 const unsigned int dim = 1;
3687
3688 // first we need to reset the
3689 // neighbor pointers of the
3690 // neighbors of this cell's
3691 // children to this cell. This is
3692 // different for one dimension,
3693 // since there neighbors can have a
3694 // refinement level differing from
3695 // that of this cell's children by
3696 // more than one level.
3697
3698 Assert(!cell->child(0)->has_children() &&
3699 !cell->child(1)->has_children(),
3701
3702 // first do it for the cells to the
3703 // left
3704 if (cell->neighbor(0).state() == IteratorState::valid)
3705 if (cell->neighbor(0)->has_children())
3706 {
3708 cell->neighbor(0);
3709 Assert(neighbor->level() == cell->level(), ExcInternalError());
3710
3711 // right child
3712 neighbor = neighbor->child(1);
3713 while (true)
3714 {
3715 Assert(neighbor->neighbor(1) == cell->child(0),
3717 neighbor->set_neighbor(1, cell);
3718
3719 // move on to further
3720 // children on the
3721 // boundary between this
3722 // cell and its neighbor
3723 if (neighbor->has_children())
3724 neighbor = neighbor->child(1);
3725 else
3726 break;
3727 }
3728 }
3729
3730 // now do it for the cells to the
3731 // left
3732 if (cell->neighbor(1).state() == IteratorState::valid)
3733 if (cell->neighbor(1)->has_children())
3734 {
3736 cell->neighbor(1);
3737 Assert(neighbor->level() == cell->level(), ExcInternalError());
3738
3739 // left child
3740 neighbor = neighbor->child(0);
3741 while (true)
3742 {
3743 Assert(neighbor->neighbor(0) == cell->child(1),
3745 neighbor->set_neighbor(0, cell);
3746
3747 // move on to further
3748 // children on the
3749 // boundary between this
3750 // cell and its neighbor
3751 if (neighbor->has_children())
3752 neighbor = neighbor->child(0);
3753 else
3754 break;
3755 }
3756 }
3757
3758
3759 // delete the vertex which will not
3760 // be needed anymore. This vertex
3761 // is the second of the first child
3762 triangulation.vertices_used[cell->child(0)->vertex_index(1)] = false;
3763
3764 // invalidate children. clear user
3765 // pointers, to avoid that they may
3766 // appear at unwanted places later
3767 // on...
3768 for (unsigned int child = 0; child < cell->n_children(); ++child)
3769 {
3770 cell->child(child)->clear_user_data();
3771 cell->child(child)->clear_user_flag();
3772 cell->child(child)->clear_used_flag();
3773 }
3774
3775
3776 // delete pointer to children
3777 cell->clear_children();
3778 cell->clear_user_flag();
3779 }
3780
3781
3782
3783 template <int spacedim>
3784 static void
3787 std::vector<unsigned int> &line_cell_count,
3788 std::vector<unsigned int> &)
3789 {
3790 const unsigned int dim = 2;
3791 const RefinementCase<dim> ref_case = cell->refinement_case();
3792
3793 Assert(line_cell_count.size() == triangulation.n_raw_lines(),
3795
3796 // vectors to hold all lines which
3797 // may be deleted
3798 std::vector<typename Triangulation<dim, spacedim>::line_iterator>
3799 lines_to_delete(0);
3800
3801 lines_to_delete.reserve(4 * 2 + 4);
3802
3803 // now we decrease the counters for
3804 // lines contained in the child
3805 // cells
3806 for (unsigned int c = 0; c < cell->n_children(); ++c)
3807 {
3809 cell->child(c);
3810 for (unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++l)
3811 --line_cell_count[child->line_index(l)];
3812 }
3813
3814
3815 // delete the vertex which will not
3816 // be needed anymore. This vertex
3817 // is the second of the second line
3818 // of the first child, if the cell
3819 // is refined with cut_xy, else there
3820 // is no inner vertex.
3821 // additionally delete unneeded inner
3822 // lines
3823 if (ref_case == RefinementCase<dim>::cut_xy)
3824 {
3826 .vertices_used[cell->child(0)->line(1)->vertex_index(1)] = false;
3827
3828 lines_to_delete.push_back(cell->child(0)->line(1));
3829 lines_to_delete.push_back(cell->child(0)->line(3));
3830 lines_to_delete.push_back(cell->child(3)->line(0));
3831 lines_to_delete.push_back(cell->child(3)->line(2));
3832 }
3833 else
3834 {
3835 unsigned int inner_face_no =
3836 ref_case == RefinementCase<dim>::cut_x ? 1 : 3;
3837
3838 // the inner line will not be
3839 // used any more
3840 lines_to_delete.push_back(cell->child(0)->line(inner_face_no));
3841 }
3842
3843 // invalidate children
3844 for (unsigned int child = 0; child < cell->n_children(); ++child)
3845 {
3846 cell->child(child)->clear_user_data();
3847 cell->child(child)->clear_user_flag();
3848 cell->child(child)->clear_used_flag();
3849 }
3850
3851
3852 // delete pointer to children
3853 cell->clear_children();
3854 cell->clear_refinement_case();
3855 cell->clear_user_flag();
3856
3857 // look at the refinement of outer
3858 // lines. if nobody needs those
3859 // anymore we can add them to the
3860 // list of lines to be deleted.
3861 for (unsigned int line_no = 0;
3862 line_no < GeometryInfo<dim>::lines_per_cell;
3863 ++line_no)
3864 {
3866 cell->line(line_no);
3867
3868 if (line->has_children())
3869 {
3870 // if one of the cell counters is
3871 // zero, the other has to be as well
3872
3873 Assert((line_cell_count[line->child_index(0)] == 0 &&
3874 line_cell_count[line->child_index(1)] == 0) ||
3875 (line_cell_count[line->child_index(0)] > 0 &&
3876 line_cell_count[line->child_index(1)] > 0),
3878
3879 if (line_cell_count[line->child_index(0)] == 0)
3880 {
3881 for (unsigned int c = 0; c < 2; ++c)
3882 Assert(!line->child(c)->has_children(),
3884
3885 // we may delete the line's
3886 // children and the middle vertex
3887 // as no cell references them
3888 // anymore
3890 .vertices_used[line->child(0)->vertex_index(1)] = false;
3891
3892 lines_to_delete.push_back(line->child(0));
3893 lines_to_delete.push_back(line->child(1));
3894
3895 line->clear_children();
3896 }
3897 }
3898 }
3899
3900 // finally, delete unneeded lines
3901
3902 // clear user pointers, to avoid that
3903 // they may appear at unwanted places
3904 // later on...
3905 // same for user flags, then finally
3906 // delete the lines
3907 typename std::vector<
3909 line = lines_to_delete.begin(),
3910 endline = lines_to_delete.end();
3911 for (; line != endline; ++line)
3912 {
3913 (*line)->clear_user_data();
3914 (*line)->clear_user_flag();
3915 (*line)->clear_used_flag();
3916 }
3917 }
3918
3919
3920
3921 template <int spacedim>
3922 static void
3925 std::vector<unsigned int> &line_cell_count,
3926 std::vector<unsigned int> &quad_cell_count)
3927 {
3928 const unsigned int dim = 3;
3929
3930 Assert(line_cell_count.size() == triangulation.n_raw_lines(),
3932 Assert(quad_cell_count.size() == triangulation.n_raw_quads(),
3934
3935 // first of all, we store the RefineCase of
3936 // this cell
3937 const RefinementCase<dim> ref_case = cell->refinement_case();
3938 // vectors to hold all lines and quads which
3939 // may be deleted
3940 std::vector<typename Triangulation<dim, spacedim>::line_iterator>
3941 lines_to_delete(0);
3942 std::vector<typename Triangulation<dim, spacedim>::quad_iterator>
3943 quads_to_delete(0);
3944
3945 lines_to_delete.reserve(12 * 2 + 6 * 4 + 6);
3946 quads_to_delete.reserve(6 * 4 + 12);
3947
3948 // now we decrease the counters for lines and
3949 // quads contained in the child cells
3950 for (unsigned int c = 0; c < cell->n_children(); ++c)
3951 {
3953 cell->child(c);
3954 const auto line_indices = TriaAccessorImplementation::
3955 Implementation::get_line_indices_of_cell(*child);
3956 for (const unsigned int l : cell->line_indices())
3957 --line_cell_count[line_indices[l]];
3958 for (auto f : GeometryInfo<dim>::face_indices())
3959 --quad_cell_count[child->quad_index(f)];
3960 }
3961
3962 //-------------------------------------
3963 // delete interior quads and lines and the
3964 // interior vertex, depending on the
3965 // refinement case of the cell
3966 //
3967 // for append quads and lines: only append
3968 // them to the list of objects to be deleted
3969
3970 switch (ref_case)
3971 {
3973 quads_to_delete.push_back(cell->child(0)->face(1));
3974 break;
3976 quads_to_delete.push_back(cell->child(0)->face(3));
3977 break;
3979 quads_to_delete.push_back(cell->child(0)->face(5));
3980 break;
3982 quads_to_delete.push_back(cell->child(0)->face(1));
3983 quads_to_delete.push_back(cell->child(0)->face(3));
3984 quads_to_delete.push_back(cell->child(3)->face(0));
3985 quads_to_delete.push_back(cell->child(3)->face(2));
3986
3987 lines_to_delete.push_back(cell->child(0)->line(11));
3988 break;
3990 quads_to_delete.push_back(cell->child(0)->face(1));
3991 quads_to_delete.push_back(cell->child(0)->face(5));
3992 quads_to_delete.push_back(cell->child(3)->face(0));
3993 quads_to_delete.push_back(cell->child(3)->face(4));
3994
3995 lines_to_delete.push_back(cell->child(0)->line(5));
3996 break;
3998 quads_to_delete.push_back(cell->child(0)->face(3));
3999 quads_to_delete.push_back(cell->child(0)->face(5));
4000 quads_to_delete.push_back(cell->child(3)->face(2));
4001 quads_to_delete.push_back(cell->child(3)->face(4));
4002
4003 lines_to_delete.push_back(cell->child(0)->line(7));
4004 break;
4006 quads_to_delete.push_back(cell->child(0)->face(1));
4007 quads_to_delete.push_back(cell->child(2)->face(1));
4008 quads_to_delete.push_back(cell->child(4)->face(1));
4009 quads_to_delete.push_back(cell->child(6)->face(1));
4010
4011 quads_to_delete.push_back(cell->child(0)->face(3));
4012 quads_to_delete.push_back(cell->child(1)->face(3));
4013 quads_to_delete.push_back(cell->child(4)->face(3));
4014 quads_to_delete.push_back(cell->child(5)->face(3));
4015
4016 quads_to_delete.push_back(cell->child(0)->face(5));
4017 quads_to_delete.push_back(cell->child(1)->face(5));
4018 quads_to_delete.push_back(cell->child(2)->face(5));
4019 quads_to_delete.push_back(cell->child(3)->face(5));
4020
4021 lines_to_delete.push_back(cell->child(0)->line(5));
4022 lines_to_delete.push_back(cell->child(0)->line(7));
4023 lines_to_delete.push_back(cell->child(0)->line(11));
4024 lines_to_delete.push_back(cell->child(7)->line(0));
4025 lines_to_delete.push_back(cell->child(7)->line(2));
4026 lines_to_delete.push_back(cell->child(7)->line(8));
4027 // delete the vertex which will not
4028 // be needed anymore. This vertex
4029 // is the vertex at the heart of
4030 // this cell, which is the sixth of
4031 // the first child
4032 triangulation.vertices_used[cell->child(0)->vertex_index(7)] =
4033 false;
4034 break;
4035 default:
4036 // only remaining case is
4037 // no_refinement, thus an error
4039 break;
4040 }
4041
4042
4043 // invalidate children
4044 for (unsigned int child = 0; child < cell->n_children(); ++child)
4045 {
4046 cell->child(child)->clear_user_data();
4047 cell->child(child)->clear_user_flag();
4048
4049 for (auto f : GeometryInfo<dim>::face_indices())
4050 // set flags denoting deviations from standard orientation of
4051 // faces back to initialization values
4052 cell->child(child)->set_combined_face_orientation(
4054
4055 cell->child(child)->clear_used_flag();
4056 }
4057
4058
4059 // delete pointer to children
4060 cell->clear_children();
4061 cell->clear_refinement_case();
4062 cell->clear_user_flag();
4063
4064 // so far we only looked at inner quads,
4065 // lines and vertices. Now we have to
4066 // consider outer ones as well. here, we have
4067 // to check, whether there are other cells
4068 // still needing these objects. otherwise we
4069 // can delete them. first for quads (and
4070 // their inner lines).
4071
4072 for (const unsigned int quad_no : GeometryInfo<dim>::face_indices())
4073 {
4075 cell->face(quad_no);
4076
4077 Assert(
4078 (GeometryInfo<dim>::face_refinement_case(ref_case, quad_no) &&
4079 quad->has_children()) ||
4080 GeometryInfo<dim>::face_refinement_case(ref_case, quad_no) ==
4083
4084 switch (quad->refinement_case())
4085 {
4086 case RefinementCase<dim - 1>::no_refinement:
4087 // nothing to do as the quad
4088 // is not refined
4089 break;
4090 case RefinementCase<dim - 1>::cut_x:
4091 case RefinementCase<dim - 1>::cut_y:
4092 {
4093 // if one of the cell counters is
4094 // zero, the other has to be as
4095 // well
4096 Assert((quad_cell_count[quad->child_index(0)] == 0 &&
4097 quad_cell_count[quad->child_index(1)] == 0) ||
4098 (quad_cell_count[quad->child_index(0)] > 0 &&
4099 quad_cell_count[quad->child_index(1)] > 0),
4101 // it might be, that the quad is
4102 // refined twice anisotropically,
4103 // first check, whether we may
4104 // delete possible grand_children
4105 unsigned int deleted_grandchildren = 0;
4106 unsigned int number_of_child_refinements = 0;
4107
4108 for (unsigned int c = 0; c < 2; ++c)
4109 if (quad->child(c)->has_children())
4110 {
4111 ++number_of_child_refinements;
4112 // if one of the cell counters is
4113 // zero, the other has to be as
4114 // well
4115 Assert(
4116 (quad_cell_count[quad->child(c)->child_index(0)] ==
4117 0 &&
4118 quad_cell_count[quad->child(c)->child_index(1)] ==
4119 0) ||
4120 (quad_cell_count[quad->child(c)->child_index(0)] >
4121 0 &&
4122 quad_cell_count[quad->child(c)->child_index(1)] >
4123 0),
4125 if (quad_cell_count[quad->child(c)->child_index(0)] ==
4126 0)
4127 {
4128 // Assert, that the two
4129 // anisotropic
4130 // refinements add up to
4131 // isotropic refinement
4132 Assert(quad->refinement_case() +
4133 quad->child(c)->refinement_case() ==
4136 // we may delete the
4137 // quad's children and
4138 // the inner line as no
4139 // cell references them
4140 // anymore
4141 quads_to_delete.push_back(
4142 quad->child(c)->child(0));
4143 quads_to_delete.push_back(
4144 quad->child(c)->child(1));
4145 if (quad->child(c)->refinement_case() ==
4147 lines_to_delete.push_back(
4148 quad->child(c)->child(0)->line(1));
4149 else
4150 lines_to_delete.push_back(
4151 quad->child(c)->child(0)->line(3));
4152 quad->child(c)->clear_children();
4153 quad->child(c)->clear_refinement_case();
4154 ++deleted_grandchildren;
4155 }
4156 }
4157 // if no grandchildren are left, we
4158 // may as well delete the
4159 // refinement of the inner line
4160 // between our children and the
4161 // corresponding vertex
4162 if (number_of_child_refinements > 0 &&
4163 deleted_grandchildren == number_of_child_refinements)
4164 {
4166 middle_line;
4167 if (quad->refinement_case() == RefinementCase<2>::cut_x)
4168 middle_line = quad->child(0)->line(1);
4169 else
4170 middle_line = quad->child(0)->line(3);
4171
4172 lines_to_delete.push_back(middle_line->child(0));
4173 lines_to_delete.push_back(middle_line->child(1));
4175 .vertices_used[middle_vertex_index<dim, spacedim>(
4176 middle_line)] = false;
4177 middle_line->clear_children();
4178 }
4179
4180 // now consider the direct children
4181 // of the given quad
4182 if (quad_cell_count[quad->child_index(0)] == 0)
4183 {
4184 // we may delete the quad's
4185 // children and the inner line
4186 // as no cell references them
4187 // anymore
4188 quads_to_delete.push_back(quad->child(0));
4189 quads_to_delete.push_back(quad->child(1));
4190 if (quad->refinement_case() == RefinementCase<2>::cut_x)
4191 lines_to_delete.push_back(quad->child(0)->line(1));
4192 else
4193 lines_to_delete.push_back(quad->child(0)->line(3));
4194
4195 // if the counters just dropped
4196 // to zero, otherwise the
4197 // children would have been
4198 // deleted earlier, then this
4199 // cell's children must have
4200 // contained the anisotropic
4201 // quad children. thus, if
4202 // those have again anisotropic
4203 // children, which are in
4204 // effect isotropic children of
4205 // the original quad, those are
4206 // still needed by a
4207 // neighboring cell and we
4208 // cannot delete them. instead,
4209 // we have to reset this quad's
4210 // refine case to isotropic and
4211 // set the children
4212 // accordingly.
4213 if (quad->child(0)->has_children())
4214 if (quad->refinement_case() ==
4216 {
4217 // now evereything is
4218 // quite complicated. we
4219 // have the children
4220 // numbered according to
4221 //
4222 // *---*---*
4223 // |n+1|m+1|
4224 // *---*---*
4225 // | n | m |
4226 // *---*---*
4227 //
4228 // from the original
4229 // anisotropic
4230 // refinement. we have to
4231 // reorder them as
4232 //
4233 // *---*---*
4234 // | m |m+1|
4235 // *---*---*
4236 // | n |n+1|
4237 // *---*---*
4238 //
4239 // for isotropic refinement.
4240 //
4241 // this is a bit ugly, of
4242 // course: loop over all
4243 // cells on all levels
4244 // and look for faces n+1
4245 // (switch_1) and m
4246 // (switch_2).
4247 const typename Triangulation<dim, spacedim>::
4248 quad_iterator switch_1 =
4249 quad->child(0)->child(1),
4250 switch_2 =
4251 quad->child(1)->child(0);
4252
4253 Assert(!switch_1->has_children(),
4255 Assert(!switch_2->has_children(),
4257
4258 const int switch_1_index = switch_1->index();
4259 const int switch_2_index = switch_2->index();
4260 for (unsigned int l = 0;
4261 l < triangulation.levels.size();
4262 ++l)
4263 for (unsigned int h = 0;
4264 h <
4265 triangulation.levels[l]->cells.n_objects();
4266 ++h)
4267 for (const unsigned int q :
4269 {
4270 const int index =
4272 ->cells.get_bounding_object_indices(
4273 h)[q];
4274 if (index == switch_1_index)
4275 triangulation.levels[l]
4276 ->cells.get_bounding_object_indices(
4277 h)[q] = switch_2_index;
4278 else if (index == switch_2_index)
4279 triangulation.levels[l]
4280 ->cells.get_bounding_object_indices(
4281 h)[q] = switch_1_index;
4282 }
4283 // now we have to copy
4284 // all information of the
4285 // two quads
4286 const int switch_1_lines[4] = {
4287 static_cast<signed int>(
4288 switch_1->line_index(0)),
4289 static_cast<signed int>(
4290 switch_1->line_index(1)),
4291 static_cast<signed int>(
4292 switch_1->line_index(2)),
4293 static_cast<signed int>(
4294 switch_1->line_index(3))};
4295 const bool switch_1_line_orientations[4] = {
4296 switch_1->line_orientation(0),
4297 switch_1->line_orientation(1),
4298 switch_1->line_orientation(2),
4299 switch_1->line_orientation(3)};
4300 const types::boundary_id switch_1_boundary_id =
4301 switch_1->boundary_id();
4302 const unsigned int switch_1_user_index =
4303 switch_1->user_index();
4304 const bool switch_1_user_flag =
4305 switch_1->user_flag_set();
4306
4307 switch_1->set_bounding_object_indices(
4308 {switch_2->line_index(0),
4309 switch_2->line_index(1),
4310 switch_2->line_index(2),
4311 switch_2->line_index(3)});
4312 switch_1->set_line_orientation(
4313 0, switch_2->line_orientation(0));
4314 switch_1->set_line_orientation(
4315 1, switch_2->line_orientation(1));
4316 switch_1->set_line_orientation(
4317 2, switch_2->line_orientation(2));
4318 switch_1->set_line_orientation(
4319 3, switch_2->line_orientation(3));
4320 switch_1->set_boundary_id_internal(
4321 switch_2->boundary_id());
4322 switch_1->set_manifold_id(
4323 switch_2->manifold_id());
4324 switch_1->set_user_index(switch_2->user_index());
4325 if (switch_2->user_flag_set())
4326 switch_1->set_user_flag();
4327 else
4328 switch_1->clear_user_flag();
4329
4330 switch_2->set_bounding_object_indices(
4331 {switch_1_lines[0],
4332 switch_1_lines[1],
4333 switch_1_lines[2],
4334 switch_1_lines[3]});
4335 switch_2->set_line_orientation(
4336 0, switch_1_line_orientations[0]);
4337 switch_2->set_line_orientation(
4338 1, switch_1_line_orientations[1]);
4339 switch_2->set_line_orientation(
4340 2, switch_1_line_orientations[2]);
4341 switch_2->set_line_orientation(
4342 3, switch_1_line_orientations[3]);
4343 switch_2->set_boundary_id_internal(
4344 switch_1_boundary_id);
4345 switch_2->set_manifold_id(
4346 switch_1->manifold_id());
4347 switch_2->set_user_index(switch_1_user_index);
4348 if (switch_1_user_flag)
4349 switch_2->set_user_flag();
4350 else
4351 switch_2->clear_user_flag();
4352
4353 const unsigned int child_0 =
4354 quad->child(0)->child_index(0);
4355 const unsigned int child_2 =
4356 quad->child(1)->child_index(0);
4357 quad->clear_children();
4358 quad->clear_refinement_case();
4359 quad->set_refinement_case(
4361 quad->set_children(0, child_0);
4362 quad->set_children(2, child_2);
4363 std::swap(quad_cell_count[child_0 + 1],
4364 quad_cell_count[child_2]);
4365 }
4366 else
4367 {
4368 // the face was refined
4369 // with cut_y, thus the
4370 // children are already
4371 // in correct order. we
4372 // only have to set them
4373 // correctly, deleting
4374 // the indirection of two
4375 // anisotropic refinement
4376 // and going directly
4377 // from the quad to
4378 // isotropic children
4379 const unsigned int child_0 =
4380 quad->child(0)->child_index(0);
4381 const unsigned int child_2 =
4382 quad->child(1)->child_index(0);
4383 quad->clear_children();
4384 quad->clear_refinement_case();
4385 quad->set_refinement_case(
4387 quad->set_children(0, child_0);
4388 quad->set_children(2, child_2);
4389 }
4390 else
4391 {
4392 quad->clear_children();
4393 quad->clear_refinement_case();
4394 }
4395 }
4396 break;
4397 }
4398 case RefinementCase<dim - 1>::cut_xy:
4399 {
4400 // if one of the cell counters is
4401 // zero, the others have to be as
4402 // well
4403
4404 Assert((quad_cell_count[quad->child_index(0)] == 0 &&
4405 quad_cell_count[quad->child_index(1)] == 0 &&
4406 quad_cell_count[quad->child_index(2)] == 0 &&
4407 quad_cell_count[quad->child_index(3)] == 0) ||
4408 (quad_cell_count[quad->child_index(0)] > 0 &&
4409 quad_cell_count[quad->child_index(1)] > 0 &&
4410 quad_cell_count[quad->child_index(2)] > 0 &&
4411 quad_cell_count[quad->child_index(3)] > 0),
4413
4414 if (quad_cell_count[quad->child_index(0)] == 0)
4415 {
4416 // we may delete the quad's
4417 // children, the inner lines
4418 // and the middle vertex as no
4419 // cell references them anymore
4420 lines_to_delete.push_back(quad->child(0)->line(1));
4421 lines_to_delete.push_back(quad->child(3)->line(0));
4422 lines_to_delete.push_back(quad->child(0)->line(3));
4423 lines_to_delete.push_back(quad->child(3)->line(2));
4424
4425 for (unsigned int child = 0; child < quad->n_children();
4426 ++child)
4427 quads_to_delete.push_back(quad->child(child));
4428
4430 .vertices_used[quad->child(0)->vertex_index(3)] =
4431 false;
4432
4433 quad->clear_children();
4434 quad->clear_refinement_case();
4435 }
4436 }
4437 break;
4438
4439 default:
4441 break;
4442 }
4443 }
4444
4445 // now we repeat a similar procedure
4446 // for the outer lines of this cell.
4447
4448 // if in debug mode: check that each
4449 // of the lines for which we consider
4450 // deleting the children in fact has
4451 // children (the bits/coarsening_3d
4452 // test tripped over this initially)
4453 for (unsigned int line_no = 0;
4454 line_no < GeometryInfo<dim>::lines_per_cell;
4455 ++line_no)
4456 {
4458 cell->line(line_no);
4459
4460 Assert(
4461 (GeometryInfo<dim>::line_refinement_case(ref_case, line_no) &&
4462 line->has_children()) ||
4463 GeometryInfo<dim>::line_refinement_case(ref_case, line_no) ==
4466
4467 if (line->has_children())
4468 {
4469 // if one of the cell counters is
4470 // zero, the other has to be as well
4471
4472 Assert((line_cell_count[line->child_index(0)] == 0 &&
4473 line_cell_count[line->child_index(1)] == 0) ||
4474 (line_cell_count[line->child_index(0)] > 0 &&
4475 line_cell_count[line->child_index(1)] > 0),
4477
4478 if (line_cell_count[line->child_index(0)] == 0)
4479 {
4480 for (unsigned int c = 0; c < 2; ++c)
4481 Assert(!line->child(c)->has_children(),
4483
4484 // we may delete the line's
4485 // children and the middle vertex
4486 // as no cell references them
4487 // anymore
4489 .vertices_used[line->child(0)->vertex_index(1)] = false;
4490
4491 lines_to_delete.push_back(line->child(0));
4492 lines_to_delete.push_back(line->child(1));
4493
4494 line->clear_children();
4495 }
4496 }
4497 }
4498
4499 // finally, delete unneeded quads and lines
4500
4501 // clear user pointers, to avoid that
4502 // they may appear at unwanted places
4503 // later on...
4504 // same for user flags, then finally
4505 // delete the quads and lines
4506 typename std::vector<
4508 line = lines_to_delete.begin(),
4509 endline = lines_to_delete.end();
4510 for (; line != endline; ++line)
4511 {
4512 (*line)->clear_user_data();
4513 (*line)->clear_user_flag();
4514 (*line)->clear_used_flag();
4515 }
4516
4517 typename std::vector<
4519 quad = quads_to_delete.begin(),
4520 endquad = quads_to_delete.end();
4521 for (; quad != endquad; ++quad)
4522 {
4523 (*quad)->clear_user_data();
4524 (*quad)->clear_children();
4525 (*quad)->clear_refinement_case();
4526 (*quad)->clear_user_flag();
4527 (*quad)->clear_used_flag();
4528 }
4529 }
4530
4531
4549 template <int spacedim>
4550 static void
4553 unsigned int &next_unused_vertex,
4555 &next_unused_line,
4557 &next_unused_cell,
4558 const typename Triangulation<2, spacedim>::cell_iterator &cell)
4559 {
4560 const unsigned int dim = 2;
4561 // clear refinement flag
4562 const RefinementCase<dim> ref_case = cell->refine_flag_set();
4563 cell->clear_refine_flag();
4564
4565 /* For the refinement process: since we go the levels up from the
4566 lowest, there are (unlike above) only two possibilities: a neighbor
4567 cell is on the same level or one level up (in both cases, it may or
4568 may not be refined later on, but we don't care here).
4569
4570 First:
4571 Set up an array of the 3x3 vertices, which are distributed on the
4572 cell (the array consists of indices into the @p{vertices} std::vector
4573
4574 2--7--3
4575 | | |
4576 4--8--5
4577 | | |
4578 0--6--1
4579
4580 note: in case of cut_x or cut_y not all these vertices are needed for
4581 the new cells
4582
4583 Second:
4584 Set up an array of the new lines (the array consists of iterator
4585 pointers into the lines arrays)
4586
4587 .-6-.-7-. The directions are: .->-.->-.
4588 1 9 3 ^ ^ ^
4589 .-10.11-. .->-.->-.
4590 0 8 2 ^ ^ ^
4591 .-4-.-5-. .->-.->-.
4592
4593 cut_x:
4594 .-4-.-5-.
4595 | | |
4596 0 6 1
4597 | | |
4598 .-2-.-3-.
4599
4600 cut_y:
4601 .---5---.
4602 1 3
4603 .---6---.
4604 0 2
4605 .---4---.
4606
4607
4608 Third:
4609 Set up an array of neighbors:
4610
4611 6 7
4612 .--.--.
4613 1| | |3
4614 .--.--.
4615 0| | |2
4616 .--.--.
4617 4 5
4618
4619 We need this array for two reasons: first to get the lines which will
4620 bound the four subcells (if the neighboring cell is refined, these
4621 lines already exist), and second to update neighborship information.
4622 Since if a neighbor is not refined, its neighborship record only
4623 points to the present, unrefined, cell rather than the children we
4624 are presently creating, we only need the neighborship information
4625 if the neighbor cells are refined. In all other cases, we store
4626 the unrefined neighbor address
4627
4628 We also need for every neighbor (if refined) which number among its
4629 neighbors the present (unrefined) cell has, since that number is to
4630 be replaced and because that also is the number of the subline which
4631 will be the interface between that neighbor and the to be created
4632 cell. We will store this number (between 0 and 3) in the field
4633 @p{neighbors_neighbor}.
4634
4635 It would be sufficient to use the children of the common line to the
4636 neighbor, if we only wanted to get the new sublines and the new
4637 vertex, but because we need to update the neighborship information of
4638 the two refined subcells of the neighbor, we need to search these
4639 anyway.
4640
4641 Convention:
4642 The created children are numbered like this:
4643
4644 .--.--.
4645 |2 . 3|
4646 .--.--.
4647 |0 | 1|
4648 .--.--.
4649 */
4650 // collect the indices of the eight surrounding vertices
4651 // 2--7--3
4652 // | | |
4653 // 4--8--5
4654 // | | |
4655 // 0--6--1
4656 int new_vertices[9];
4657 for (unsigned int vertex_no = 0; vertex_no < 4; ++vertex_no)
4658 new_vertices[vertex_no] = cell->vertex_index(vertex_no);
4659 for (unsigned int line_no = 0; line_no < 4; ++line_no)
4660 if (cell->line(line_no)->has_children())
4661 new_vertices[4 + line_no] =
4662 cell->line(line_no)->child(0)->vertex_index(1);
4663
4664 if (ref_case == RefinementCase<dim>::cut_xy)
4665 {
4666 // find the next
4667 // unused vertex and
4668 // allocate it for
4669 // the new vertex we
4670 // need here
4671 while (triangulation.vertices_used[next_unused_vertex] == true)
4672 ++next_unused_vertex;
4673 Assert(next_unused_vertex < triangulation.vertices.size(),
4674 ExcMessage(
4675 "Internal error: During refinement, the triangulation "
4676 "wants to access an element of the 'vertices' array "
4677 "but it turns out that the array is not large enough."));
4678 triangulation.vertices_used[next_unused_vertex] = true;
4679
4680 new_vertices[8] = next_unused_vertex;
4681
4682 // determine middle vertex by transfinite interpolation to be
4683 // consistent with what happens to quads in a
4684 // Triangulation<3,3> when they are refined
4685 triangulation.vertices[next_unused_vertex] =
4686 cell->center(true, true);
4687 }
4688
4689
4690 // Now the lines:
4692 unsigned int lmin = 8;
4693 unsigned int lmax = 12;
4694 if (ref_case != RefinementCase<dim>::cut_xy)
4695 {
4696 lmin = 6;
4697 lmax = 7;
4698 }
4699
4700 for (unsigned int l = lmin; l < lmax; ++l)
4701 {
4702 while (next_unused_line->used() == true)
4703 ++next_unused_line;
4704 new_lines[l] = next_unused_line;
4705 ++next_unused_line;
4706
4707 AssertIsNotUsed(new_lines[l]);
4708 }
4709
4710 if (ref_case == RefinementCase<dim>::cut_xy)
4711 {
4712 // .-6-.-7-.
4713 // 1 9 3
4714 // .-10.11-.
4715 // 0 8 2
4716 // .-4-.-5-.
4717
4718 // lines 0-7 already exist, create only the four interior
4719 // lines 8-11
4720 unsigned int l = 0;
4721 for (const unsigned int face_no : GeometryInfo<dim>::face_indices())
4722 for (unsigned int c = 0; c < 2; ++c, ++l)
4723 new_lines[l] = cell->line(face_no)->child(c);
4724 Assert(l == 8, ExcInternalError());
4725
4726 new_lines[8]->set_bounding_object_indices(
4727 {new_vertices[6], new_vertices[8]});
4728 new_lines[9]->set_bounding_object_indices(
4729 {new_vertices[8], new_vertices[7]});
4730 new_lines[10]->set_bounding_object_indices(
4731 {new_vertices[4], new_vertices[8]});
4732 new_lines[11]->set_bounding_object_indices(
4733 {new_vertices[8], new_vertices[5]});
4734 }
4735 else if (ref_case == RefinementCase<dim>::cut_x)
4736 {
4737 // .-4-.-5-.
4738 // | | |
4739 // 0 6 1
4740 // | | |
4741 // .-2-.-3-.
4742 new_lines[0] = cell->line(0);
4743 new_lines[1] = cell->line(1);
4744 new_lines[2] = cell->line(2)->child(0);
4745 new_lines[3] = cell->line(2)->child(1);
4746 new_lines[4] = cell->line(3)->child(0);
4747 new_lines[5] = cell->line(3)->child(1);
4748 new_lines[6]->set_bounding_object_indices(
4749 {new_vertices[6], new_vertices[7]});
4750 }
4751 else
4752 {
4754 // .---5---.
4755 // 1 3
4756 // .---6---.
4757 // 0 2
4758 // .---4---.
4759 new_lines[0] = cell->line(0)->child(0);
4760 new_lines[1] = cell->line(0)->child(1);
4761 new_lines[2] = cell->line(1)->child(0);
4762 new_lines[3] = cell->line(1)->child(1);
4763 new_lines[4] = cell->line(2);
4764 new_lines[5] = cell->line(3);
4765 new_lines[6]->set_bounding_object_indices(
4766 {new_vertices[4], new_vertices[5]});
4767 }
4768
4769 for (unsigned int l = lmin; l < lmax; ++l)
4770 {
4771 new_lines[l]->set_used_flag();
4772 new_lines[l]->clear_user_flag();
4773 new_lines[l]->clear_user_data();
4774 new_lines[l]->clear_children();
4775 // interior line
4776 new_lines[l]->set_boundary_id_internal(
4778 new_lines[l]->set_manifold_id(cell->manifold_id());
4779 }
4780
4781 // Now add the four (two)
4782 // new cells!
4785 while (next_unused_cell->used() == true)
4786 ++next_unused_cell;
4787
4788 const unsigned int n_children = GeometryInfo<dim>::n_children(ref_case);
4789 for (unsigned int i = 0; i < n_children; ++i)
4790 {
4791 AssertIsNotUsed(next_unused_cell);
4792 subcells[i] = next_unused_cell;
4793 ++next_unused_cell;
4794 if (i % 2 == 1 && i < n_children - 1)
4795 while (next_unused_cell->used() == true)
4796 ++next_unused_cell;
4797 }
4798
4799 if (ref_case == RefinementCase<dim>::cut_xy)
4800 {
4801 // children:
4802 // .--.--.
4803 // |2 . 3|
4804 // .--.--.
4805 // |0 | 1|
4806 // .--.--.
4807 // lines:
4808 // .-6-.-7-.
4809 // 1 9 3
4810 // .-10.11-.
4811 // 0 8 2
4812 // .-4-.-5-.
4813 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
4814 new_lines[8]->index(),
4815 new_lines[4]->index(),
4816 new_lines[10]->index()});
4817 subcells[1]->set_bounding_object_indices({new_lines[8]->index(),
4818 new_lines[2]->index(),
4819 new_lines[5]->index(),
4820 new_lines[11]->index()});
4821 subcells[2]->set_bounding_object_indices({new_lines[1]->index(),
4822 new_lines[9]->index(),
4823 new_lines[10]->index(),
4824 new_lines[6]->index()});
4825 subcells[3]->set_bounding_object_indices({new_lines[9]->index(),
4826 new_lines[3]->index(),
4827 new_lines[11]->index(),
4828 new_lines[7]->index()});
4829 }
4830 else if (ref_case == RefinementCase<dim>::cut_x)
4831 {
4832 // children:
4833 // .--.--.
4834 // | . |
4835 // .0 . 1.
4836 // | | |
4837 // .--.--.
4838 // lines:
4839 // .-4-.-5-.
4840 // | | |
4841 // 0 6 1
4842 // | | |
4843 // .-2-.-3-.
4844 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
4845 new_lines[6]->index(),
4846 new_lines[2]->index(),
4847 new_lines[4]->index()});
4848 subcells[1]->set_bounding_object_indices({new_lines[6]->index(),
4849 new_lines[1]->index(),
4850 new_lines[3]->index(),
4851 new_lines[5]->index()});
4852 }
4853 else
4854 {
4856 // children:
4857 // .-----.
4858 // | 1 |
4859 // .-----.
4860 // | 0 |
4861 // .-----.
4862 // lines:
4863 // .---5---.
4864 // 1 3
4865 // .---6---.
4866 // 0 2
4867 // .---4---.
4868 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
4869 new_lines[2]->index(),
4870 new_lines[4]->index(),
4871 new_lines[6]->index()});
4872 subcells[1]->set_bounding_object_indices({new_lines[1]->index(),
4873 new_lines[3]->index(),
4874 new_lines[6]->index(),
4875 new_lines[5]->index()});
4876 }
4877
4878 types::subdomain_id subdomainid = cell->subdomain_id();
4879
4880 for (unsigned int i = 0; i < n_children; ++i)
4881 {
4882 subcells[i]->set_used_flag();
4883 subcells[i]->clear_refine_flag();
4884 subcells[i]->clear_user_flag();
4885 subcells[i]->clear_user_data();
4886 subcells[i]->clear_children();
4887 // inherit material properties
4888 subcells[i]->set_material_id(cell->material_id());
4889 subcells[i]->set_manifold_id(cell->manifold_id());
4890 subcells[i]->set_subdomain_id(subdomainid);
4891
4892 if (i % 2 == 0)
4893 subcells[i]->set_parent(cell->index());
4894 }
4895
4896
4897
4898 // set child index for even children i=0,2 (0)
4899 for (unsigned int i = 0; i < n_children / 2; ++i)
4900 cell->set_children(2 * i, subcells[2 * i]->index());
4901 // set the refine case
4902 cell->set_refinement_case(ref_case);
4903
4904 // note that the
4905 // refinement flag was
4906 // already cleared at the
4907 // beginning of this function
4908
4909 if (dim == spacedim - 1)
4910 for (unsigned int c = 0; c < n_children; ++c)
4911 cell->child(c)->set_direction_flag(cell->direction_flag());
4912 }
4913
4914
4915
4916 template <int dim, int spacedim>
4919 const bool check_for_distorted_cells)
4920 {
4921 AssertDimension(dim, 2);
4922
4923 // Check whether a new level is needed. We have to check for
4924 // this on the highest level only
4925 for (const auto &cell : triangulation.active_cell_iterators_on_level(
4926 triangulation.levels.size() - 1))
4927 if (cell->refine_flag_set())
4928 {
4929 triangulation.levels.push_back(
4930 std::make_unique<
4932 break;
4933 }
4934
4937 line != triangulation.end_line();
4938 ++line)
4939 {
4940 line->clear_user_flag();
4941 line->clear_user_data();
4942 }
4943
4944 unsigned int n_single_lines = 0;
4945 unsigned int n_lines_in_pairs = 0;
4946 unsigned int needed_vertices = 0;
4947
4948 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
4949 {
4950 // count number of flagged cells on this level and compute
4951 // how many new vertices and new lines will be needed
4952 unsigned int needed_cells = 0;
4953
4954 for (const auto &cell :
4955 triangulation.active_cell_iterators_on_level(level))
4956 if (cell->refine_flag_set())
4957 {
4958 if (cell->reference_cell() == ReferenceCells::Triangle)
4959 {
4960 needed_cells += 4;
4961 needed_vertices += 0;
4962 n_single_lines += 3;
4963 }
4964 else if (cell->reference_cell() ==
4966 {
4967 needed_cells += 4;
4968 needed_vertices += 1;
4969 n_single_lines += 4;
4970 }
4971 else
4972 {
4974 }
4975
4976 for (const auto line_no : cell->face_indices())
4977 {
4978 auto line = cell->line(line_no);
4979 if (line->has_children() == false)
4980 line->set_user_flag();
4981 }
4982 }
4983
4984
4985 const unsigned int used_cells =
4986 std::count(triangulation.levels[level + 1]->cells.used.begin(),
4987 triangulation.levels[level + 1]->cells.used.end(),
4988 true);
4989
4990
4991 reserve_space(*triangulation.levels[level + 1],
4992 used_cells + needed_cells,
4993 2,
4994 spacedim);
4995
4996 reserve_space(triangulation.levels[level + 1]->cells,
4997 needed_cells,
4998 0);
4999 }
5000
5001 for (auto line = triangulation.begin_line();
5002 line != triangulation.end_line();
5003 ++line)
5004 if (line->user_flag_set())
5005 {
5006 Assert(line->has_children() == false, ExcInternalError());
5007 n_lines_in_pairs += 2;
5008 needed_vertices += 1;
5009 }
5010
5011 reserve_space(triangulation.faces->lines, n_lines_in_pairs, 0);
5012
5013 needed_vertices += std::count(triangulation.vertices_used.begin(),
5014 triangulation.vertices_used.end(),
5015 true);
5016
5017 if (needed_vertices > triangulation.vertices.size())
5018 {
5019 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
5020 triangulation.vertices_used.resize(needed_vertices, false);
5021 }
5022
5023 unsigned int next_unused_vertex = 0;
5024
5025 {
5028 endl = triangulation.end_line();
5030 next_unused_line = triangulation.begin_raw_line();
5031
5032 for (; line != endl; ++line)
5033 if (line->user_flag_set())
5034 {
5035 // This line needs to be refined. Find the next unused vertex
5036 // and set it appropriately
5037 while (triangulation.vertices_used[next_unused_vertex] == true)
5038 ++next_unused_vertex;
5039 Assert(next_unused_vertex < triangulation.vertices.size(),
5040 ExcMessage(
5041 "Internal error: During refinement, the triangulation "
5042 "wants to access an element of the 'vertices' array "
5043 "but it turns out that the array is not large "
5044 "enough."));
5045 triangulation.vertices_used[next_unused_vertex] = true;
5046
5047 triangulation.vertices[next_unused_vertex] = line->center(true);
5048
5049 [[maybe_unused]] bool pair_found = false;
5050 for (; next_unused_line != endl; ++next_unused_line)
5051 if (!next_unused_line->used() &&
5052 !(++next_unused_line)->used())
5053 {
5054 --next_unused_line;
5055 pair_found = true;
5056 break;
5057 }
5058 Assert(pair_found, ExcInternalError());
5059
5060 line->set_children(0, next_unused_line->index());
5061
5063 children[2] = {next_unused_line, ++next_unused_line};
5064
5065 AssertIsNotUsed(children[0]);
5066 AssertIsNotUsed(children[1]);
5067
5068 children[0]->set_bounding_object_indices(
5069 {line->vertex_index(0), next_unused_vertex});
5070 children[1]->set_bounding_object_indices(
5071 {next_unused_vertex, line->vertex_index(1)});
5072
5073 for (auto &child : children)
5074 {
5075 child->set_used_flag();
5076 child->clear_children();
5077 child->clear_user_data();
5078 child->clear_user_flag();
5079 child->set_boundary_id_internal(line->boundary_id());
5080 child->set_manifold_id(line->manifold_id());
5081 // Line orientation is relative to the cell it is on so
5082 // those cannot be set at this point.
5083 }
5084
5085 line->clear_user_flag();
5086 }
5087 }
5088
5089 reserve_space(triangulation.faces->lines, 0, n_single_lines);
5090
5092 cells_with_distorted_children;
5093
5095 next_unused_line = triangulation.begin_raw_line();
5096
5097 const auto create_children = [](auto &triangulation,
5098 unsigned int &next_unused_vertex,
5099 auto &next_unused_line,
5100 auto &next_unused_cell,
5101 const auto &cell) {
5102 const auto ref_case = cell->refine_flag_set();
5103 cell->clear_refine_flag();
5104
5105 unsigned int n_new_vertices = 0;
5106
5107 if (cell->reference_cell() == ReferenceCells::Triangle)
5108 n_new_vertices = 6;
5109 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5110 n_new_vertices = 9;
5111 else
5113
5114 std::vector<unsigned int> new_vertices(n_new_vertices,
5116 for (unsigned int vertex_no = 0; vertex_no < cell->n_vertices();
5117 ++vertex_no)
5118 new_vertices[vertex_no] = cell->vertex_index(vertex_no);
5119 for (unsigned int line_no = 0; line_no < cell->n_lines(); ++line_no)
5120 if (cell->line(line_no)->has_children())
5121 new_vertices[cell->n_vertices() + line_no] =
5122 cell->line(line_no)->child(0)->vertex_index(1);
5123
5124 if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5125 {
5126 while (triangulation.vertices_used[next_unused_vertex] == true)
5127 ++next_unused_vertex;
5128 Assert(
5129 next_unused_vertex < triangulation.vertices.size(),
5130 ExcMessage(
5131 "Internal error: During refinement, the triangulation wants "
5132 "to access an element of the 'vertices' array but it turns "
5133 "out that the array is not large enough."));
5134 triangulation.vertices_used[next_unused_vertex] = true;
5135
5136 new_vertices[8] = next_unused_vertex;
5137
5138 triangulation.vertices[next_unused_vertex] =
5139 cell->center(true, true);
5140 }
5141
5142 std::array<typename Triangulation<dim, spacedim>::raw_line_iterator,
5143 12>
5144 new_lines;
5145 std::array<unsigned char, 12> inherited_orientations;
5146 inherited_orientations.fill(
5148 unsigned int lmin = 0;
5149 unsigned int lmax = 0;
5150
5151 if (cell->reference_cell() == ReferenceCells::Triangle)
5152 {
5153 lmin = 6;
5154 lmax = 9;
5155 // For triangles, the innermost faces are always reversed for the
5156 // first three children and are in the standard orientation for
5157 // the last one.
5158 std::fill(inherited_orientations.begin() + lmin,
5159 inherited_orientations.begin() + lmax,
5161 }
5162 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5163 {
5164 lmin = 8;
5165 lmax = 12;
5166 }
5167 else
5168 {
5170 }
5171
5172 for (unsigned int l = lmin; l < lmax; ++l)
5173 {
5174 while (next_unused_line->used() == true)
5175 ++next_unused_line;
5176 new_lines[l] = next_unused_line;
5177 ++next_unused_line;
5178
5179 AssertIsNotUsed(new_lines[l]);
5180 }
5181
5182 // set up lines which have parents:
5183 for (const unsigned int face_no : cell->face_indices())
5184 {
5185 // Check the face (line) orientation to ensure that the (six or
5186 // eight) outer lines in new_lines are indexed in the default
5187 // orientation. This way we can index into this array in the
5188 // without special casing orientations (e.g., quadrilateral child
5189 // 3 will always have lines 9, 3, 11, 7) when setting child lines.
5190 const unsigned char combined_orientation =
5191 cell->combined_face_orientation(face_no);
5192 Assert(combined_orientation ==
5194 combined_orientation ==
5197 for (unsigned int c = 0; c < 2; ++c)
5198 {
5199 new_lines[2 * face_no + c] = cell->line(face_no)->child(c);
5200 inherited_orientations[2 * face_no + c] =
5201 cell->combined_face_orientation(face_no);
5202 }
5203 if (combined_orientation ==
5205 std::swap(new_lines[2 * face_no], new_lines[2 * face_no + 1]);
5206 }
5207
5208 // set up lines which do not have parents:
5209 if (cell->reference_cell() == ReferenceCells::Triangle)
5210 {
5211 new_lines[6]->set_bounding_object_indices(
5212 {new_vertices[3], new_vertices[4]});
5213 new_lines[7]->set_bounding_object_indices(
5214 {new_vertices[4], new_vertices[5]});
5215 new_lines[8]->set_bounding_object_indices(
5216 {new_vertices[5], new_vertices[3]});
5217 }
5218 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5219 {
5220 new_lines[8]->set_bounding_object_indices(
5221 {new_vertices[6], new_vertices[8]});
5222 new_lines[9]->set_bounding_object_indices(
5223 {new_vertices[8], new_vertices[7]});
5224 new_lines[10]->set_bounding_object_indices(
5225 {new_vertices[4], new_vertices[8]});
5226 new_lines[11]->set_bounding_object_indices(
5227 {new_vertices[8], new_vertices[5]});
5228 }
5229 else
5230 {
5232 }
5233
5234 for (unsigned int l = lmin; l < lmax; ++l)
5235 {
5236 new_lines[l]->set_used_flag();
5237 new_lines[l]->clear_user_flag();
5238 new_lines[l]->clear_user_data();
5239 new_lines[l]->clear_children();
5240 // new lines are always internal.
5241 new_lines[l]->set_boundary_id_internal(
5243 new_lines[l]->set_manifold_id(cell->manifold_id());
5244 }
5245
5248 while (next_unused_cell->used() == true)
5249 ++next_unused_cell;
5250
5251 unsigned int n_children = 0;
5252 if (cell->reference_cell() == ReferenceCells::Triangle)
5253 n_children = 4;
5254 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5255 n_children = 4;
5256 else
5258
5259 for (unsigned int i = 0; i < n_children; ++i)
5260 {
5261 AssertIsNotUsed(next_unused_cell);
5262 subcells[i] = next_unused_cell;
5263 ++next_unused_cell;
5264 if (i % 2 == 1 && i < n_children - 1)
5265 while (next_unused_cell->used() == true)
5266 ++next_unused_cell;
5267 }
5268
5269 // Assign lines to child cells:
5270 constexpr unsigned int X = numbers::invalid_unsigned_int;
5271 static constexpr ::ndarray<unsigned int, 4, 4> tri_child_lines =
5272 {{{{0, 8, 5, X}}, {{1, 2, 6, X}}, {{7, 3, 4, X}}, {{6, 7, 8, X}}}};
5273 static constexpr ::ndarray<unsigned int, 4, 4>
5274 quad_child_lines = {{{{0, 8, 4, 10}},
5275 {{8, 2, 5, 11}},
5276 {{1, 9, 10, 6}},
5277 {{9, 3, 11, 7}}}};
5278 // Here and below we assume that child cells have the same reference
5279 // cell type as the parent.
5280 const auto &child_lines =
5281 cell->reference_cell() == ReferenceCells::Triangle ?
5282 tri_child_lines :
5283 quad_child_lines;
5284 for (unsigned int i = 0; i < n_children; ++i)
5285 {
5286 if (cell->reference_cell() == ReferenceCells::Triangle)
5287 subcells[i]->set_bounding_object_indices(
5288 {new_lines[child_lines[i][0]]->index(),
5289 new_lines[child_lines[i][1]]->index(),
5290 new_lines[child_lines[i][2]]->index()});
5291 else
5292 subcells[i]->set_bounding_object_indices(
5293 {new_lines[child_lines[i][0]]->index(),
5294 new_lines[child_lines[i][1]]->index(),
5295 new_lines[child_lines[i][2]]->index(),
5296 new_lines[child_lines[i][3]]->index()});
5297
5298 subcells[i]->set_used_flag();
5299 subcells[i]->clear_refine_flag();
5300 subcells[i]->clear_user_flag();
5301 subcells[i]->clear_user_data();
5302 subcells[i]->clear_children();
5303 // inherit material properties
5304 subcells[i]->set_material_id(cell->material_id());
5305 subcells[i]->set_manifold_id(cell->manifold_id());
5306 subcells[i]->set_subdomain_id(cell->subdomain_id());
5307
5308 triangulation.levels[subcells[i]->level()]
5309 ->reference_cell[subcells[i]->index()] = cell->reference_cell();
5310
5311 // Finally, now that children are marked as used, we can set
5312 // orientation flags:
5313 for (unsigned int face_no : cell->face_indices())
5314 subcells[i]->set_combined_face_orientation(
5315 face_no, inherited_orientations[child_lines[i][face_no]]);
5316
5317 if (i % 2 == 0)
5318 subcells[i]->set_parent(cell->index());
5319 }
5320
5321 // Unlike the same lines on other children, the innermost triangle's
5322 // faces are all in the default orientation:
5323 if (cell->reference_cell() == ReferenceCells::Triangle)
5324 for (unsigned int face_no : cell->face_indices())
5325 subcells[3]->set_combined_face_orientation(
5327
5328 for (unsigned int i = 0; i < n_children / 2; ++i)
5329 cell->set_children(2 * i, subcells[2 * i]->index());
5330
5331 cell->set_refinement_case(ref_case);
5332
5333 if (dim == spacedim - 1)
5334 for (unsigned int c = 0; c < n_children; ++c)
5335 cell->child(c)->set_direction_flag(cell->direction_flag());
5336 };
5337
5338 for (int level = 0;
5339 level < static_cast<int>(triangulation.levels.size()) - 1;
5340 ++level)
5341 {
5343 next_unused_cell = triangulation.begin_raw(level + 1);
5344
5345 for (const auto &cell :
5346 triangulation.active_cell_iterators_on_level(level))
5347 if (cell->refine_flag_set())
5348 {
5349 create_children(triangulation,
5350 next_unused_vertex,
5351 next_unused_line,
5352 next_unused_cell,
5353 cell);
5354
5355 if (cell->reference_cell() == ReferenceCells::Quadrilateral &&
5356 check_for_distorted_cells &&
5357 has_distorted_children<dim, spacedim>(cell))
5358 cells_with_distorted_children.distorted_cells.push_back(
5359 cell);
5360
5361 triangulation.signals.post_refinement_on_cell(cell);
5362 }
5363 }
5364
5365 return cells_with_distorted_children;
5366 }
5367
5368
5369
5374 template <int spacedim>
5377 const bool /*check_for_distorted_cells*/)
5378 {
5379 const unsigned int dim = 1;
5380
5381 // Check whether a new level is needed. We have to check for
5382 // this on the highest level only
5383 for (const auto &cell : triangulation.active_cell_iterators_on_level(
5384 triangulation.levels.size() - 1))
5385 if (cell->refine_flag_set())
5386 {
5387 triangulation.levels.push_back(
5388 std::make_unique<
5390 break;
5391 }
5392
5393
5394 // check how much space is needed on every level. We need not
5395 // check the highest level since either - on the highest level
5396 // no cells are flagged for refinement - there are, but
5397 // prepare_refinement added another empty level
5398 unsigned int needed_vertices = 0;
5399 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5400 {
5401 // count number of flagged
5402 // cells on this level
5403 unsigned int flagged_cells = 0;
5404
5405 for (const auto &acell :
5406 triangulation.active_cell_iterators_on_level(level))
5407 if (acell->refine_flag_set())
5408 ++flagged_cells;
5409
5410 // count number of used cells
5411 // on the next higher level
5412 const unsigned int used_cells =
5413 std::count(triangulation.levels[level + 1]->cells.used.begin(),
5414 triangulation.levels[level + 1]->cells.used.end(),
5415 true);
5416
5417 // reserve space for the used_cells cells already existing
5418 // on the next higher level as well as for the
5419 // 2*flagged_cells that will be created on that level
5420 reserve_space(*triangulation.levels[level + 1],
5422 flagged_cells,
5423 1,
5424 spacedim);
5425 // reserve space for 2*flagged_cells new lines on the next
5426 // higher level
5427 reserve_space(triangulation.levels[level + 1]->cells,
5429 flagged_cells,
5430 0);
5431
5432 needed_vertices += flagged_cells;
5433 }
5434
5435 // add to needed vertices how many
5436 // vertices are already in use
5437 needed_vertices += std::count(triangulation.vertices_used.begin(),
5438 triangulation.vertices_used.end(),
5439 true);
5440 // if we need more vertices: create them, if not: leave the
5441 // array as is, since shrinking is not really possible because
5442 // some of the vertices at the end may be in use
5443 if (needed_vertices > triangulation.vertices.size())
5444 {
5445 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
5446 triangulation.vertices_used.resize(needed_vertices, false);
5447 }
5448
5449
5450 // Do REFINEMENT on every level; exclude highest level as
5451 // above
5452
5453 // index of next unused vertex
5454 unsigned int next_unused_vertex = 0;
5455
5456 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5457 {
5459 next_unused_cell = triangulation.begin_raw(level + 1);
5460
5461 for (const auto &cell :
5462 triangulation.active_cell_iterators_on_level(level))
5463 if (cell->refine_flag_set())
5464 {
5465 // clear refinement flag
5466 cell->clear_refine_flag();
5467
5468 // search for next unused
5469 // vertex
5470 while (triangulation.vertices_used[next_unused_vertex] ==
5471 true)
5472 ++next_unused_vertex;
5473 Assert(
5474 next_unused_vertex < triangulation.vertices.size(),
5475 ExcMessage(
5476 "Internal error: During refinement, the triangulation "
5477 "wants to access an element of the 'vertices' array "
5478 "but it turns out that the array is not large enough."));
5479
5480 // Now we always ask the cell itself where to put
5481 // the new point. The cell in turn will query the
5482 // manifold object internally.
5483 triangulation.vertices[next_unused_vertex] =
5484 cell->center(true);
5485
5486 triangulation.vertices_used[next_unused_vertex] = true;
5487
5488 // search for next two unused cell (++ takes care of
5489 // the end of the vector)
5491 first_child,
5492 second_child;
5493 while (next_unused_cell->used() == true)
5494 ++next_unused_cell;
5495 first_child = next_unused_cell;
5496 first_child->set_used_flag();
5497 first_child->clear_user_data();
5498 ++next_unused_cell;
5499 AssertIsNotUsed(next_unused_cell);
5500 second_child = next_unused_cell;
5501 second_child->set_used_flag();
5502 second_child->clear_user_data();
5503
5504 types::subdomain_id subdomainid = cell->subdomain_id();
5505
5506 // insert first child
5507 cell->set_children(0, first_child->index());
5508 first_child->clear_children();
5509 first_child->set_bounding_object_indices(
5510 {cell->vertex_index(0), next_unused_vertex});
5511 first_child->set_material_id(cell->material_id());
5512 first_child->set_manifold_id(cell->manifold_id());
5513 first_child->set_subdomain_id(subdomainid);
5514 if (dim == spacedim - 1)
5515 first_child->set_direction_flag(cell->direction_flag());
5516
5517 first_child->set_parent(cell->index());
5518
5519 // Set manifold id of the right face. Only do this
5520 // on the first child.
5521 first_child->face(1)->set_manifold_id(cell->manifold_id());
5522
5523 // reset neighborship info (refer to
5524 // internal::TriangulationImplementation::TriaLevel<0> for
5525 // details)
5526 first_child->set_neighbor(1, second_child);
5527 if (cell->neighbor(0).state() != IteratorState::valid)
5528 first_child->set_neighbor(0, cell->neighbor(0));
5529 else if (cell->neighbor(0)->is_active())
5530 {
5531 // since the neighbors level is always <=level,
5532 // if the cell is active, then there are no
5533 // cells to the left which may want to know
5534 // about this new child cell.
5535 Assert(cell->neighbor(0)->level() <= cell->level(),
5537 first_child->set_neighbor(0, cell->neighbor(0));
5538 }
5539 else
5540 // left neighbor is refined
5541 {
5542 // set neighbor to cell on same level
5543 const unsigned int nbnb = cell->neighbor_of_neighbor(0);
5544 first_child->set_neighbor(0,
5545 cell->neighbor(0)->child(nbnb));
5546
5547 // reset neighbor info of all right descendant
5548 // of the left neighbor of cell
5550 left_neighbor = cell->neighbor(0);
5551 while (left_neighbor->has_children())
5552 {
5553 left_neighbor = left_neighbor->child(nbnb);
5554 left_neighbor->set_neighbor(nbnb, first_child);
5555 }
5556 }
5557
5558 // insert second child
5559 second_child->clear_children();
5560 second_child->set_bounding_object_indices(
5561 {next_unused_vertex, cell->vertex_index(1)});
5562 second_child->set_neighbor(0, first_child);
5563 second_child->set_material_id(cell->material_id());
5564 second_child->set_manifold_id(cell->manifold_id());
5565 second_child->set_subdomain_id(subdomainid);
5566 if (dim == spacedim - 1)
5567 second_child->set_direction_flag(cell->direction_flag());
5568
5569 if (cell->neighbor(1).state() != IteratorState::valid)
5570 second_child->set_neighbor(1, cell->neighbor(1));
5571 else if (cell->neighbor(1)->is_active())
5572 {
5573 Assert(cell->neighbor(1)->level() <= cell->level(),
5575 second_child->set_neighbor(1, cell->neighbor(1));
5576 }
5577 else
5578 // right neighbor is refined same as above
5579 {
5580 const unsigned int nbnb = cell->neighbor_of_neighbor(1);
5581 second_child->set_neighbor(
5582 1, cell->neighbor(1)->child(nbnb));
5583
5585 right_neighbor = cell->neighbor(1);
5586 while (right_neighbor->has_children())
5587 {
5588 right_neighbor = right_neighbor->child(nbnb);
5589 right_neighbor->set_neighbor(nbnb, second_child);
5590 }
5591 }
5592 // inform all listeners that cell refinement is done
5593 triangulation.signals.post_refinement_on_cell(cell);
5594 }
5595 }
5596
5597 // in 1d, we can not have distorted children unless the parent
5598 // was already distorted (that is because we don't use
5599 // boundary information for 1d triangulations). so return an
5600 // empty list
5602 }
5603
5604
5609 template <int spacedim>
5612 const bool check_for_distorted_cells)
5613 {
5614 const unsigned int dim = 2;
5615
5616 // First check whether we can get away with isotropic refinement, or
5617 // whether we need to run through the full anisotropic algorithm
5618 {
5619 bool do_isotropic_refinement = true;
5620 for (const auto &cell : triangulation.active_cell_iterators())
5621 if (cell->refine_flag_set() == RefinementCase<dim>::cut_x ||
5622 cell->refine_flag_set() == RefinementCase<dim>::cut_y)
5623 {
5624 do_isotropic_refinement = false;
5625 break;
5626 }
5627
5628 if (do_isotropic_refinement)
5629 return execute_refinement_isotropic(triangulation,
5630 check_for_distorted_cells);
5631 }
5632
5633 // If we get here, we are doing anisotropic refinement.
5634
5635 // Check whether a new level is needed. We have to check for
5636 // this on the highest level only
5637 for (const auto &cell : triangulation.active_cell_iterators_on_level(
5638 triangulation.levels.size() - 1))
5639 if (cell->refine_flag_set())
5640 {
5641 triangulation.levels.push_back(
5642 std::make_unique<
5644 break;
5645 }
5646
5647 // TODO[WB]: we clear user flags and pointers of lines; we're going
5648 // to use them to flag which lines need refinement
5651 line != triangulation.end_line();
5652 ++line)
5653 {
5654 line->clear_user_flag();
5655 line->clear_user_data();
5656 }
5657 // running over all cells and lines count the number
5658 // n_single_lines of lines which can be stored as single
5659 // lines, e.g. inner lines
5660 unsigned int n_single_lines = 0;
5661
5662 // New lines to be created: number lines which are stored in
5663 // pairs (the children of lines must be stored in pairs)
5664 unsigned int n_lines_in_pairs = 0;
5665
5666 // check how much space is needed on every level. We need not
5667 // check the highest level since either - on the highest level
5668 // no cells are flagged for refinement - there are, but
5669 // prepare_refinement added another empty level
5670 unsigned int needed_vertices = 0;
5671 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5672 {
5673 // count number of flagged cells on this level and compute
5674 // how many new vertices and new lines will be needed
5675 unsigned int needed_cells = 0;
5676
5677 for (const auto &cell :
5678 triangulation.active_cell_iterators_on_level(level))
5679 if (cell->refine_flag_set())
5680 {
5681 if (cell->refine_flag_set() == RefinementCase<dim>::cut_xy)
5682 {
5683 needed_cells += 4;
5684
5685 // new vertex at center of cell is needed in any
5686 // case
5687 ++needed_vertices;
5688
5689 // the four inner lines can be stored as singles
5690 n_single_lines += 4;
5691 }
5692 else // cut_x || cut_y
5693 {
5694 // set the flag showing that anisotropic
5695 // refinement is used for at least one cell
5696 triangulation.anisotropic_refinement = true;
5697
5698 needed_cells += 2;
5699 // no vertex at center
5700
5701 // the inner line can be stored as single
5702 n_single_lines += 1;
5703 }
5704
5705 // mark all faces (lines) for refinement; checking
5706 // locally whether the neighbor would also like to
5707 // refine them is rather difficult for lines so we
5708 // only flag them and after visiting all cells, we
5709 // decide which lines need refinement;
5710 for (const unsigned int line_no :
5712 {
5714 cell->refine_flag_set(), line_no) ==
5716 {
5718 line = cell->line(line_no);
5719 if (line->has_children() == false)
5720 line->set_user_flag();
5721 }
5722 }
5723 }
5724
5725
5726 // count number of used cells on the next higher level
5727 const unsigned int used_cells =
5728 std::count(triangulation.levels[level + 1]->cells.used.begin(),
5729 triangulation.levels[level + 1]->cells.used.end(),
5730 true);
5731
5732
5733 // reserve space for the used_cells cells already existing
5734 // on the next higher level as well as for the
5735 // needed_cells that will be created on that level
5736 reserve_space(*triangulation.levels[level + 1],
5737 used_cells + needed_cells,
5738 2,
5739 spacedim);
5740
5741 // reserve space for needed_cells new quads on the next
5742 // higher level
5743 reserve_space(triangulation.levels[level + 1]->cells,
5744 needed_cells,
5745 0);
5746 }
5747
5748 // now count the lines which were flagged for refinement
5751 line != triangulation.end_line();
5752 ++line)
5753 if (line->user_flag_set())
5754 {
5755 Assert(line->has_children() == false, ExcInternalError());
5756 n_lines_in_pairs += 2;
5757 needed_vertices += 1;
5758 }
5759 // reserve space for n_lines_in_pairs new lines. note, that
5760 // we can't reserve space for the single lines here as well,
5761 // as all the space reserved for lines in pairs would be
5762 // counted as unused and we would end up with too little space
5763 // to store all lines. memory reservation for n_single_lines
5764 // can only be done AFTER we refined the lines of the current
5765 // cells
5766 reserve_space(triangulation.faces->lines, n_lines_in_pairs, 0);
5767
5768 // add to needed vertices how many vertices are already in use
5769 needed_vertices += std::count(triangulation.vertices_used.begin(),
5770 triangulation.vertices_used.end(),
5771 true);
5772 // if we need more vertices: create them, if not: leave the
5773 // array as is, since shrinking is not really possible because
5774 // some of the vertices at the end may be in use
5775 if (needed_vertices > triangulation.vertices.size())
5776 {
5777 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
5778 triangulation.vertices_used.resize(needed_vertices, false);
5779 }
5780
5781
5782 // Do REFINEMENT on every level; exclude highest level as
5783 // above
5784
5785 // index of next unused vertex
5786 unsigned int next_unused_vertex = 0;
5787
5788 // first the refinement of lines. children are stored
5789 // pairwise
5790 {
5791 // only active objects can be refined further
5794 endl = triangulation.end_line();
5796 next_unused_line = triangulation.begin_raw_line();
5797
5798 for (; line != endl; ++line)
5799 if (line->user_flag_set())
5800 {
5801 // this line needs to be refined
5802
5803 // find the next unused vertex and set it
5804 // appropriately
5805 while (triangulation.vertices_used[next_unused_vertex] == true)
5806 ++next_unused_vertex;
5807 Assert(
5808 next_unused_vertex < triangulation.vertices.size(),
5809 ExcMessage(
5810 "Internal error: During refinement, the triangulation wants to access an element of the 'vertices' array but it turns out that the array is not large enough."));
5811 triangulation.vertices_used[next_unused_vertex] = true;
5812
5813 triangulation.vertices[next_unused_vertex] = line->center(true);
5814
5815 // now that we created the right point, make up the
5816 // two child lines. To this end, find a pair of
5817 // unused lines
5818 [[maybe_unused]] bool pair_found = false;
5819 for (; next_unused_line != endl; ++next_unused_line)
5820 if (!next_unused_line->used() &&
5821 !(++next_unused_line)->used())
5822 {
5823 // go back to the first of the two unused
5824 // lines
5825 --next_unused_line;
5826 pair_found = true;
5827 break;
5828 }
5829 Assert(pair_found, ExcInternalError());
5830
5831 // there are now two consecutive unused lines, such
5832 // that the children of a line will be consecutive.
5833 // then set the child pointer of the present line
5834 line->set_children(0, next_unused_line->index());
5835
5836 // set the two new lines
5838 children[2] = {next_unused_line, ++next_unused_line};
5839 // some tests; if any of the iterators should be
5840 // invalid, then already dereferencing will fail
5841 AssertIsNotUsed(children[0]);
5842 AssertIsNotUsed(children[1]);
5843
5844 children[0]->set_bounding_object_indices(
5845 {line->vertex_index(0), next_unused_vertex});
5846 children[1]->set_bounding_object_indices(
5847 {next_unused_vertex, line->vertex_index(1)});
5848
5849 children[0]->set_used_flag();
5850 children[1]->set_used_flag();
5851 children[0]->clear_children();
5852 children[1]->clear_children();
5853 children[0]->clear_user_data();
5854 children[1]->clear_user_data();
5855 children[0]->clear_user_flag();
5856 children[1]->clear_user_flag();
5857
5858
5859 children[0]->set_boundary_id_internal(line->boundary_id());
5860 children[1]->set_boundary_id_internal(line->boundary_id());
5861
5862 children[0]->set_manifold_id(line->manifold_id());
5863 children[1]->set_manifold_id(line->manifold_id());
5864
5865 // finally clear flag indicating the need for
5866 // refinement
5867 line->clear_user_flag();
5868 }
5869 }
5870
5871
5872 // Now set up the new cells
5873
5874 // reserve space for inner lines (can be stored as single
5875 // lines)
5876 reserve_space(triangulation.faces->lines, 0, n_single_lines);
5877
5879 cells_with_distorted_children;
5880
5881 // reset next_unused_line, as now also single empty places in
5882 // the vector can be used
5884 next_unused_line = triangulation.begin_raw_line();
5885
5886 for (int level = 0;
5887 level < static_cast<int>(triangulation.levels.size()) - 1;
5888 ++level)
5889 {
5891 next_unused_cell = triangulation.begin_raw(level + 1);
5892
5893 for (const auto &cell :
5894 triangulation.active_cell_iterators_on_level(level))
5895 if (cell->refine_flag_set())
5896 {
5897 // actually set up the children and update neighbor
5898 // information
5899 create_children(triangulation,
5900 next_unused_vertex,
5901 next_unused_line,
5902 next_unused_cell,
5903 cell);
5904
5905 if (check_for_distorted_cells &&
5906 has_distorted_children<dim, spacedim>(cell))
5907 cells_with_distorted_children.distorted_cells.push_back(
5908 cell);
5909 // inform all listeners that cell refinement is done
5910 triangulation.signals.post_refinement_on_cell(cell);
5911 }
5912 }
5913
5914 return cells_with_distorted_children;
5915 }
5916
5917
5918 template <int spacedim>
5921 const bool check_for_distorted_cells)
5922 {
5923 static const int dim = 3;
5924 static const unsigned int X = numbers::invalid_unsigned_int;
5925 using raw_line_iterator =
5927 using raw_quad_iterator =
5929
5930 Assert(spacedim == 3, ExcNotImplemented());
5931
5932 Assert(triangulation.vertices.size() ==
5933 triangulation.vertices_used.size(),
5935
5936 // Check whether a new level is needed. We have to check for
5937 // this on the highest level only
5938 for (const auto &cell : triangulation.active_cell_iterators_on_level(
5939 triangulation.levels.size() - 1))
5940 if (cell->refine_flag_set())
5941 {
5942 triangulation.levels.push_back(
5943 std::make_unique<
5945 break;
5946 }
5947
5948 // first clear user flags for quads and lines; we're going to
5949 // use them to flag which lines and quads need refinement
5950 triangulation.faces->quads.clear_user_data();
5951 triangulation.faces->lines.clear_user_flags();
5952 triangulation.faces->quads.clear_user_flags();
5953
5954 // check how much space is needed on every level. We need not
5955 // check the highest level since either
5956 // - on the highest level no cells are flagged for refinement
5957 // - there are, but prepare_refinement added another empty
5958 // level which then is the highest level
5959
5960 // variables to hold the number of newly to be created
5961 // vertices, lines and quads. as these are stored globally,
5962 // declare them outside the loop over al levels. we need lines
5963 // and quads in pairs for refinement of old ones and lines and
5964 // quads, that can be stored as single ones, as they are newly
5965 // created in the inside of an existing cell
5966 unsigned int needed_vertices = 0;
5967 unsigned int needed_lines_single = 0;
5968 unsigned int needed_quads_single = 0;
5969 unsigned int needed_lines_pair = 0;
5970 unsigned int needed_quads_pair = 0;
5971 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5972 {
5973 unsigned int new_cells = 0;
5974
5975 for (const auto &cell :
5976 triangulation.active_cell_iterators_on_level(level))
5977 if (cell->refine_flag_set())
5978 {
5979 // Only support isotropic refinement
5980 Assert(cell->refine_flag_set() ==
5983
5984 // Now count up how many new cells, faces, edges, and vertices
5985 // we will need to allocate to do this refinement.
5986 new_cells += cell->reference_cell().n_isotropic_children();
5987
5988 if (cell->reference_cell() == ReferenceCells::Hexahedron)
5989 {
5990 ++needed_vertices;
5991 needed_lines_single += 6;
5992 needed_quads_single += 12;
5993 }
5994 else if (cell->reference_cell() ==
5996 {
5997 needed_lines_single += 1;
5998 needed_quads_single += 8;
5999 }
6000 else
6001 {
6003 }
6004
6005 // Also check whether we have to refine any of the faces and
6006 // edges that bound this cell. They may of course already be
6007 // refined, so we only *mark* them for refinement by setting
6008 // the user flags
6009 for (const auto face : cell->face_indices())
6010 if (cell->face(face)->n_children() == 0)
6011 cell->face(face)->set_user_flag();
6012 else
6013 Assert(cell->face(face)->n_children() ==
6014 cell->reference_cell()
6015 .face_reference_cell(face)
6016 .n_isotropic_children(),
6018
6019 for (const auto line : cell->line_indices())
6020 if (cell->line(line)->has_children() == false)
6021 cell->line(line)->set_user_flag();
6022 else
6023 Assert(cell->line(line)->n_children() == 2,
6025 }
6026
6027 const unsigned int used_cells =
6028 std::count(triangulation.levels[level + 1]->cells.used.begin(),
6029 triangulation.levels[level + 1]->cells.used.end(),
6030 true);
6031
6032 if (triangulation.all_reference_cells_are_hyper_cube())
6033 reserve_space(*triangulation.levels[level + 1],
6034 used_cells + new_cells,
6035 3,
6036 spacedim,
6037 false);
6038 else
6039 reserve_space(*triangulation.levels[level + 1],
6040 used_cells + new_cells,
6041 3,
6042 spacedim,
6043 true);
6044
6045 reserve_space(triangulation.levels[level + 1]->cells, new_cells);
6046 }
6047
6048 // now count the quads and lines which were flagged for
6049 // refinement
6052 quad != triangulation.end_quad();
6053 ++quad)
6054 {
6055 if (quad->user_flag_set() == false)
6056 continue;
6057
6058 if (quad->reference_cell() == ReferenceCells::Quadrilateral)
6059 {
6060 needed_quads_pair += 4;
6061 needed_lines_pair += 4;
6062 needed_vertices += 1;
6063 }
6064 else if (quad->reference_cell() == ReferenceCells::Triangle)
6065 {
6066 needed_quads_pair += 4;
6067 needed_lines_single += 3;
6068 }
6069 else
6070 {
6072 }
6073 }
6074
6077 line != triangulation.end_line();
6078 ++line)
6079 {
6080 if (line->user_flag_set() == false)
6081 continue;
6082
6083 needed_lines_pair += 2;
6084 needed_vertices += 1;
6085 }
6086
6087 reserve_space(triangulation.faces->lines,
6088 needed_lines_pair,
6089 needed_lines_single);
6091 needed_quads_pair,
6092 needed_quads_single);
6093 reserve_space(triangulation.faces->quads,
6094 needed_quads_pair,
6095 needed_quads_single);
6096
6097
6098 // add to needed vertices how many vertices are already in use
6099 needed_vertices += std::count(triangulation.vertices_used.begin(),
6100 triangulation.vertices_used.end(),
6101 true);
6102
6103 if (needed_vertices > triangulation.vertices.size())
6104 {
6105 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
6106 triangulation.vertices_used.resize(needed_vertices, false);
6107 }
6108
6109 //-----------------------------------------
6110 // Before we start with the actual refinement, we do some
6111 // sanity checks if in debug mode. especially, we try to catch
6112 // the notorious problem with lines being twice refined,
6113 // i.e. there are cells adjacent at one line ("around the
6114 // edge", but not at a face), with two cells differing by more
6115 // than one refinement level
6116 //
6117 // this check is very simple to implement here, since we have
6118 // all lines flagged if they shall be refined
6119#ifdef DEBUG
6120 for (const auto &cell : triangulation.active_cell_iterators())
6121 if (!cell->refine_flag_set())
6122 for (unsigned int line_n = 0; line_n < cell->n_lines(); ++line_n)
6123 if (cell->line(line_n)->has_children())
6124 for (unsigned int c = 0; c < 2; ++c)
6125 Assert(cell->line(line_n)->child(c)->user_flag_set() == false,
6127#endif
6128
6129 unsigned int current_vertex = 0;
6130
6131 // helper function - find the next available vertex number and mark it
6132 // as used.
6133 auto get_next_unused_vertex = [](const unsigned int current_vertex,
6134 std::vector<bool> &vertices_used) {
6135 unsigned int next_vertex = current_vertex;
6136 while (next_vertex < vertices_used.size() &&
6137 vertices_used[next_vertex] == true)
6138 ++next_vertex;
6139 Assert(next_vertex < vertices_used.size(), ExcInternalError());
6140 vertices_used[next_vertex] = true;
6141
6142 return next_vertex;
6143 };
6144
6145 // LINES
6146 {
6149 endl = triangulation.end_line();
6150 raw_line_iterator next_unused_line = triangulation.begin_raw_line();
6151
6152 for (; line != endl; ++line)
6153 {
6154 if (line->user_flag_set() == false)
6155 continue;
6156
6157 next_unused_line =
6158 triangulation.faces->lines.template next_free_pair_object<1>(
6160 Assert(next_unused_line.state() == IteratorState::valid,
6162
6163 // now we found two consecutive unused lines, such
6164 // that the children of a line will be consecutive.
6165 // then set the child pointer of the present line
6166 line->set_children(0, next_unused_line->index());
6167
6168 const std::array<raw_line_iterator, 2> children{
6169 {next_unused_line, ++next_unused_line}};
6170
6171 AssertIsNotUsed(children[0]);
6172 AssertIsNotUsed(children[1]);
6173
6174 current_vertex =
6175 get_next_unused_vertex(current_vertex,
6176 triangulation.vertices_used);
6177 triangulation.vertices[current_vertex] = line->center(true);
6178
6179 children[0]->set_bounding_object_indices(
6180 {line->vertex_index(0), current_vertex});
6181 children[1]->set_bounding_object_indices(
6182 {current_vertex, line->vertex_index(1)});
6183
6184 const auto manifold_id = line->manifold_id();
6185 const auto boundary_id = line->boundary_id();
6186 for (const auto &child : children)
6187 {
6188 child->set_used_flag();
6189 child->clear_children();
6190 child->clear_user_data();
6191 child->clear_user_flag();
6192 child->set_boundary_id_internal(boundary_id);
6193 child->set_manifold_id(manifold_id);
6194 }
6195
6196 line->clear_user_flag();
6197 }
6198 }
6199
6200 // QUADS
6201 {
6203 quad = triangulation.begin_quad(),
6204 endq = triangulation.end_quad();
6205
6206 for (; quad != endq; ++quad)
6207 {
6208 if (quad->user_flag_set() == false)
6209 continue;
6210
6211 const auto reference_face_type = quad->reference_cell();
6212
6213 // 1) create new lines (property is set later)
6214 // maximum of 4 new lines (4 quadrilateral, 3 triangle)
6215 std::array<raw_line_iterator, 4> new_lines;
6216 if (reference_face_type == ReferenceCells::Quadrilateral)
6217 {
6218 for (unsigned int l = 0; l < 2; ++l)
6219 {
6220 auto next_unused_line =
6221 triangulation.faces->lines
6222 .template next_free_pair_object<1>(triangulation);
6223 new_lines[2 * l] = next_unused_line;
6224 new_lines[2 * l + 1] = ++next_unused_line;
6225 }
6226 }
6227 else if (reference_face_type == ReferenceCells::Triangle)
6228 {
6229 for (unsigned int l = 0; l < 3; ++l)
6230 new_lines[l] =
6231 triangulation.faces->lines
6232 .template next_free_single_object<1>(triangulation);
6233 }
6234 else
6235 {
6237 }
6238
6239#ifdef DEBUG
6240 for (const unsigned int line : quad->line_indices())
6241 AssertIsNotUsed(new_lines[line]);
6242#endif
6243
6244 // 2) create new quads (properties are set below). Both triangles
6245 // and quads are divided in four.
6246 std::array<raw_quad_iterator, 4> new_quads;
6247 for (unsigned int q = 0; q < 2; ++q)
6248 {
6249 auto next_unused_quad =
6250 triangulation.faces->quads
6251 .template next_free_pair_object<2>(triangulation);
6252
6253 new_quads[2 * q] = next_unused_quad;
6254 new_quads[2 * q + 1] = ++next_unused_quad;
6255
6256 quad->set_children(2 * q, new_quads[2 * q]->index());
6257 }
6258 quad->set_refinement_case(RefinementCase<2>::cut_xy);
6259
6260#ifdef DEBUG
6261 for (const auto &quad : new_quads)
6262 AssertIsNotUsed(quad);
6263#endif
6264
6265 // 3) set vertex indices and set new vertex
6266
6267 // Maximum of 9 vertices per refined quad (9 for Quadrilateral, 6
6268 // for Triangle)
6269 std::array<unsigned int, 9> vertex_indices = {};
6270 unsigned int k = 0;
6271 for (const auto i : quad->vertex_indices())
6272 vertex_indices[k++] = quad->vertex_index(i);
6273
6274 for (const auto i : quad->line_indices())
6275 vertex_indices[k++] = quad->line(i)->child(0)->vertex_index(1);
6276
6277 if (reference_face_type == ReferenceCells::Quadrilateral)
6278 {
6279 current_vertex =
6280 get_next_unused_vertex(current_vertex,
6281 triangulation.vertices_used);
6282 vertex_indices[k++] = current_vertex;
6283
6284 triangulation.vertices[current_vertex] =
6285 quad->center(true, true);
6286 }
6287
6288 // 4) set new lines on quads and their properties
6289 std::array<raw_line_iterator, 12> lines;
6290 unsigned int n_lines = 0;
6291 for (unsigned int l = 0; l < quad->n_lines(); ++l)
6292 for (unsigned int c = 0; c < 2; ++c)
6293 {
6294 static constexpr ::ndarray<unsigned int, 2, 2> index =
6295 {{// child 0, line_orientation=false and true
6296 {{1, 0}},
6297 // child 1, line_orientation=false and true
6298 {{0, 1}}}};
6299
6300 lines[n_lines++] =
6301 quad->line(l)->child(index[c][quad->line_orientation(l)]);
6302 }
6303
6304 for (unsigned int l = 0; l < quad->n_lines(); ++l)
6305 lines[n_lines++] = new_lines[l];
6306
6307 std::array<int, 12> line_indices;
6308 for (unsigned int i = 0; i < n_lines; ++i)
6309 line_indices[i] = lines[i]->index();
6310
6311 static constexpr ::ndarray<unsigned int, 12, 2>
6312 line_vertices_quad{{{{0, 4}},
6313 {{4, 2}},
6314 {{1, 5}},
6315 {{5, 3}},
6316 {{0, 6}},
6317 {{6, 1}},
6318 {{2, 7}},
6319 {{7, 3}},
6320 {{6, 8}},
6321 {{8, 7}},
6322 {{4, 8}},
6323 {{8, 5}}}};
6324
6325 static constexpr ::ndarray<unsigned int, 4, 4>
6326 quad_lines_quad{{{{0, 8, 4, 10}},
6327 {{8, 2, 5, 11}},
6328 {{1, 9, 10, 6}},
6329 {{9, 3, 11, 7}}}};
6330
6331 static constexpr ::ndarray<unsigned int, 12, 2>
6332 line_vertices_tri{{{{0, 3}},
6333 {{3, 1}},
6334 {{1, 4}},
6335 {{4, 2}},
6336 {{2, 5}},
6337 {{5, 0}},
6338 {{3, 4}},
6339 {{4, 5}},
6340 {{3, 5}},
6341 {{X, X}},
6342 {{X, X}},
6343 {{X, X}}}};
6344
6345 static constexpr ::ndarray<unsigned int, 4, 4>
6346 quad_lines_tri{{{{0, 8, 5, X}},
6347 {{1, 2, 6, X}},
6348 {{7, 3, 4, X}},
6349 {{6, 7, 8, X}}}};
6350
6351 static constexpr ::ndarray<unsigned int, 4, 4, 2>
6352 quad_line_vertices_tri{
6353 {{{{{0, 3}}, {{3, 5}}, {{5, 0}}, {{X, X}}}},
6354 {{{{3, 1}}, {{1, 4}}, {{4, 3}}, {{X, X}}}},
6355 {{{{5, 4}}, {{4, 2}}, {{2, 5}}, {{X, X}}}},
6356 {{{{3, 4}}, {{4, 5}}, {{5, 3}}, {{X, X}}}}}};
6357
6358 const auto &line_vertices =
6359 (reference_face_type == ReferenceCells::Quadrilateral) ?
6360 line_vertices_quad :
6361 line_vertices_tri;
6362 const auto &quad_lines =
6363 (reference_face_type == ReferenceCells::Quadrilateral) ?
6364 quad_lines_quad :
6365 quad_lines_tri;
6366
6367 for (unsigned int i = 0, j = 2 * quad->n_lines();
6368 i < quad->n_lines();
6369 ++i, ++j)
6370 {
6371 auto &new_line = new_lines[i];
6372 new_line->set_bounding_object_indices(
6373 {vertex_indices[line_vertices[j][0]],
6374 vertex_indices[line_vertices[j][1]]});
6375 new_line->set_used_flag();
6376 new_line->clear_user_flag();
6377 new_line->clear_user_data();
6378 new_line->clear_children();
6379 new_line->set_boundary_id_internal(quad->boundary_id());
6380 new_line->set_manifold_id(quad->manifold_id());
6381 }
6382
6383 // 5) set properties of quads
6384 for (unsigned int i = 0; i < new_quads.size(); ++i)
6385 {
6386 auto &new_quad = new_quads[i];
6387
6388 // TODO: we assume here that all children have the same type
6389 // as the parent
6390 triangulation.faces->set_quad_type(new_quad->index(),
6391 reference_face_type);
6392
6393 if (reference_face_type == ReferenceCells::Triangle)
6394 new_quad->set_bounding_object_indices(
6395 {line_indices[quad_lines[i][0]],
6396 line_indices[quad_lines[i][1]],
6397 line_indices[quad_lines[i][2]]});
6398 else if (reference_face_type == ReferenceCells::Quadrilateral)
6399 new_quad->set_bounding_object_indices(
6400 {line_indices[quad_lines[i][0]],
6401 line_indices[quad_lines[i][1]],
6402 line_indices[quad_lines[i][2]],
6403 line_indices[quad_lines[i][3]]});
6404 else
6406
6407 new_quad->set_used_flag();
6408 new_quad->clear_user_flag();
6409 new_quad->clear_user_data();
6410 new_quad->clear_children();
6411 new_quad->set_boundary_id_internal(quad->boundary_id());
6412 new_quad->set_manifold_id(quad->manifold_id());
6413
6414#ifdef DEBUG
6415 std::set<unsigned int> s;
6416#endif
6417
6418 // ... and fix orientation of lines of face for triangles,
6419 // using an expensive algorithm, quadrilaterals are treated
6420 // a few lines below by a cheaper algorithm
6421 if (reference_face_type == ReferenceCells::Triangle)
6422 {
6423 for (const auto f : new_quad->line_indices())
6424 {
6425 const std::array<unsigned int, 2> vertices_0 = {
6426 {lines[quad_lines[i][f]]->vertex_index(0),
6427 lines[quad_lines[i][f]]->vertex_index(1)}};
6428
6429 const std::array<unsigned int, 2> vertices_1 = {
6430 {vertex_indices[quad_line_vertices_tri[i][f][0]],
6431 vertex_indices[quad_line_vertices_tri[i][f][1]]}};
6432
6433 const auto orientation =
6435 make_array_view(vertices_0),
6436 make_array_view(vertices_1));
6437
6438#ifdef DEBUG
6439 for (const auto i : vertices_0)
6440 s.insert(i);
6441 for (const auto i : vertices_1)
6442 s.insert(i);
6443#endif
6444
6445 new_quad->set_line_orientation(
6446 f,
6447 orientation ==
6449 default_combined_face_orientation());
6450 }
6451#ifdef DEBUG
6452 AssertDimension(s.size(), 3);
6453#endif
6454 }
6455 }
6456
6457 // fix orientation of lines of faces for quadrilaterals with
6458 // cheap algorithm
6459 if (reference_face_type == ReferenceCells::Quadrilateral)
6460 {
6461 static constexpr ::ndarray<unsigned int, 4, 2>
6462 quad_child_boundary_lines{
6463 {{{0, 2}}, {{1, 3}}, {{0, 1}}, {{2, 3}}}};
6464
6465 for (unsigned int i = 0; i < 4; ++i)
6466 for (unsigned int j = 0; j < 2; ++j)
6467 new_quads[quad_child_boundary_lines[i][j]]
6468 ->set_line_orientation(i, quad->line_orientation(i));
6469 }
6470
6471 quad->clear_user_flag();
6472 }
6473 }
6474
6476 cells_with_distorted_children;
6477
6480 for (unsigned int level = 0; level != triangulation.levels.size() - 1;
6481 ++level)
6482 {
6484 next_unused_hex = triangulation.begin_raw_hex(level + 1);
6485 Assert(hex == triangulation.end() ||
6486 hex->level() >= static_cast<int>(level),
6488
6489 for (; hex != triangulation.end() &&
6490 hex->level() == static_cast<int>(level);
6491 ++hex)
6492 {
6493 if (hex->refine_flag_set() ==
6495 continue;
6496
6497 const auto &reference_cell_type = hex->reference_cell();
6498
6499 const RefinementCase<dim> ref_case = hex->refine_flag_set();
6500 hex->clear_refine_flag();
6501 hex->set_refinement_case(ref_case);
6502
6503 unsigned int n_new_lines = 0;
6504 unsigned int n_new_quads = 0;
6505 unsigned int n_new_hexes = 0;
6506
6507 if (reference_cell_type == ReferenceCells::Hexahedron)
6508 {
6509 n_new_lines = 6;
6510 n_new_quads = 12;
6511 n_new_hexes = 8;
6512 }
6513 else if (reference_cell_type == ReferenceCells::Tetrahedron)
6514 {
6515 n_new_lines = 1;
6516 n_new_quads = 8;
6517 n_new_hexes = 8;
6518 }
6519 else
6521
6522 std::array<raw_line_iterator, 6> new_lines;
6523 for (unsigned int i = 0; i < n_new_lines; ++i)
6524 {
6525 new_lines[i] =
6526 triangulation.faces->lines
6527 .template next_free_single_object<1>(triangulation);
6528
6529 AssertIsNotUsed(new_lines[i]);
6530 new_lines[i]->set_used_flag();
6531 new_lines[i]->clear_user_flag();
6532 new_lines[i]->clear_user_data();
6533 new_lines[i]->clear_children();
6534 new_lines[i]->set_boundary_id_internal(
6536 new_lines[i]->set_manifold_id(hex->manifold_id());
6537 }
6538
6539 std::array<raw_quad_iterator, 12> new_quads;
6540 for (unsigned int i = 0; i < n_new_quads; ++i)
6541 {
6542 new_quads[i] =
6543 triangulation.faces->quads
6544 .template next_free_single_object<2>(triangulation);
6545
6546 auto &new_quad = new_quads[i];
6547
6548 // TODO: faces of children have the same type as the faces
6549 // of the parent
6550 triangulation.faces->set_quad_type(
6551 new_quad->index(),
6552 reference_cell_type.face_reference_cell(0));
6553
6554 AssertIsNotUsed(new_quad);
6555 new_quad->set_used_flag();
6556 new_quad->clear_user_flag();
6557 new_quad->clear_user_data();
6558 new_quad->clear_children();
6559 new_quad->set_boundary_id_internal(
6561 new_quad->set_manifold_id(hex->manifold_id());
6562 for (const auto j : new_quads[i]->line_indices())
6563 new_quad->set_line_orientation(j, true);
6564 }
6565
6566 // we always get 8 children per refined cell
6567 std::array<
6569 8>
6570 new_hexes;
6571 {
6572 for (unsigned int i = 0; i < n_new_hexes; ++i)
6573 {
6574 if (i % 2 == 0)
6575 next_unused_hex =
6576 triangulation.levels[level + 1]->cells.next_free_hex(
6577 triangulation, level + 1);
6578 else
6579 ++next_unused_hex;
6580
6581 new_hexes[i] = next_unused_hex;
6582
6583 auto &new_hex = new_hexes[i];
6584
6585 // children have the same type as the parent
6586 triangulation.levels[new_hex->level()]
6587 ->reference_cell[new_hex->index()] =
6588 reference_cell_type;
6589
6590 AssertIsNotUsed(new_hex);
6591 new_hex->set_used_flag();
6592 new_hex->clear_user_flag();
6593 new_hex->clear_user_data();
6594 new_hex->clear_children();
6595 new_hex->set_material_id(hex->material_id());
6596 new_hex->set_manifold_id(hex->manifold_id());
6597 new_hex->set_subdomain_id(hex->subdomain_id());
6598
6599 if (i % 2)
6600 new_hex->set_parent(hex->index());
6601
6602 // set the orientation flag to its default state for all
6603 // faces initially. later on go the other way round and
6604 // reset faces that are at the boundary of the mother cube
6605 for (const auto f : new_hex->face_indices())
6606 new_hex->set_combined_face_orientation(
6607 f,
6609 }
6610 for (unsigned int i = 0; i < n_new_hexes / 2; ++i)
6611 hex->set_children(2 * i, new_hexes[2 * i]->index());
6612 }
6613
6614 {
6615 // load vertex indices
6616 std::array<unsigned int, 27> vertex_indices = {};
6617
6618 {
6619 unsigned int k = 0;
6620
6621 // avoid a compiler warning by fixing the max number of
6622 // loop iterations to 8
6623 const unsigned int n_vertices =
6624 std::min(hex->n_vertices(), 8u);
6625 for (unsigned int i = 0; i < n_vertices; ++i)
6626 vertex_indices[k++] = hex->vertex_index(i);
6627
6628 const std::array<unsigned int, 12> line_indices =
6629 TriaAccessorImplementation::Implementation::
6630 get_line_indices_of_cell(*hex);
6631
6632 // For the tetrahedron the parent consists of the vertices
6633 // 0,1,2,3, the new vertices 4-9 are defined as the
6634 // midpoints of the edges: 4 -> (0,1), 5 -> (1,2), 6 ->
6635 // (2,0), 7 -> (0,3), 8 -> (1,3), 9 -> (2,3).
6636 // Order is defined by the reference cell, see
6637 // https://dealii.org/developer/doxygen/deal.II/group__simplex.html#simplex_reference_cells.
6638
6639 // Avoid a compiler warning by fixing the max number of loop
6640 // iterations to 12
6641 const unsigned int n_lines = std::min(hex->n_lines(), 12u);
6642 for (unsigned int l = 0; l < n_lines; ++l)
6643 {
6644 raw_line_iterator line(&triangulation,
6645 0,
6646 line_indices[l]);
6647 vertex_indices[k++] = line->child(0)->vertex_index(1);
6648 }
6649
6650 if (reference_cell_type == ReferenceCells::Hexahedron)
6651 {
6652 for (const unsigned int i : hex->face_indices())
6653 vertex_indices[k++] =
6654 hex->face(i)->child(0)->vertex_index(3);
6655
6656 // Set single new vertex in the center
6657 current_vertex =
6658 get_next_unused_vertex(current_vertex,
6659 triangulation.vertices_used);
6660 vertex_indices[k++] = current_vertex;
6661
6662 triangulation.vertices[current_vertex] =
6663 hex->center(true, true);
6664 }
6665 }
6666
6667 unsigned int chosen_line_tetrahedron = 0;
6668 // set up new lines
6669 if (reference_cell_type == ReferenceCells::Hexahedron)
6670 {
6671 static constexpr ::ndarray<unsigned int, 6, 2>
6672 new_line_vertices = {{{{22, 26}},
6673 {{26, 23}},
6674 {{20, 26}},
6675 {{26, 21}},
6676 {{24, 26}},
6677 {{26, 25}}}};
6678 for (unsigned int i = 0; i < n_new_lines; ++i)
6679 new_lines[i]->set_bounding_object_indices(
6680 {vertex_indices[new_line_vertices[i][0]],
6681 vertex_indices[new_line_vertices[i][1]]});
6682 }
6683 else if (reference_cell_type == ReferenceCells::Tetrahedron)
6684 {
6685 // in the tetrahedron case, we have the three
6686 // possibilities (6,8), (5,7), (4,9) -> pick the
6687 // shortest line to guarantee the best possible aspect
6688 // ratios
6689 static constexpr ::ndarray<unsigned int, 3, 2>
6690 new_line_vertices = {{{{6, 8}}, {{5, 7}}, {{4, 9}}}};
6691
6692 // choose line to cut either by refinement case or by
6693 // shortest distance between edge midpoints
6694 std::uint8_t refinement_choice = hex->refine_choice();
6695 if (refinement_choice ==
6696 static_cast<char>(
6698 {
6699 const auto &vertices = triangulation.get_vertices();
6700 double min_distance =
6701 std::numeric_limits<double>::infinity();
6702 for (unsigned int i = 0; i < new_line_vertices.size();
6703 ++i)
6704 {
6705 const double current_distance =
6706 vertices
6707 [vertex_indices[new_line_vertices[i][0]]]
6708 .distance(
6709 vertices[vertex_indices
6710 [new_line_vertices[i][1]]]);
6711 if (current_distance < min_distance)
6712 {
6713 chosen_line_tetrahedron = i;
6714 min_distance = current_distance;
6715 }
6716 }
6717 }
6718 else if (refinement_choice ==
6719 static_cast<char>(
6721 chosen_line_tetrahedron = 0;
6722 else if (refinement_choice ==
6723 static_cast<char>(
6725 chosen_line_tetrahedron = 1;
6726 else if (refinement_choice ==
6727 static_cast<char>(
6729 chosen_line_tetrahedron = 2;
6730 else
6732
6733 hex->set_refinement_case(
6734 RefinementCase<dim>(chosen_line_tetrahedron + 1));
6735
6736 new_lines[0]->set_bounding_object_indices(
6738 [new_line_vertices[chosen_line_tetrahedron][0]],
6740 [new_line_vertices[chosen_line_tetrahedron][1]]});
6741 }
6742
6743 // set up new quads
6744 {
6745 boost::container::small_vector<raw_line_iterator, 30>
6746 relevant_lines;
6747
6748 if (reference_cell_type == ReferenceCells::Hexahedron)
6749 {
6750 relevant_lines.resize(30);
6751 for (unsigned int f = 0, k = 0; f < 6; ++f)
6752 for (unsigned int c = 0; c < 4; ++c, ++k)
6753 {
6754 static constexpr ::
6755 ndarray<unsigned int, 4, 2>
6756 temp = {
6757 {{{0, 1}}, {{3, 0}}, {{0, 3}}, {{3, 2}}}};
6758
6759 relevant_lines[k] =
6760 hex->face(f)
6761 ->isotropic_child(
6763 standard_to_real_face_vertex(
6764 temp[c][0],
6765 hex->face_orientation(f),
6766 hex->face_flip(f),
6767 hex->face_rotation(f)))
6768 ->line(GeometryInfo<dim>::
6769 standard_to_real_face_line(
6770 temp[c][1],
6771 hex->face_orientation(f),
6772 hex->face_flip(f),
6773 hex->face_rotation(f)));
6774 }
6775
6776 for (unsigned int i = 0, k = 24; i < 6; ++i, ++k)
6777 relevant_lines[k] = new_lines[i];
6778 }
6779 else if (reference_cell_type == ReferenceCells::Tetrahedron)
6780 {
6781 // The order of the lines is defined by the ordering
6782 // of the faces of the reference cell and the ordering
6783 // of the lines within a face.
6784 // Each face is split into 4 child triangles, the
6785 // relevant lines are defined by the vertices of the
6786 // center triangles: 0 -> (4,5), 1 -> (5,6), 2 -> (4,6),
6787 // 3 -> (4,7), 4 -> (7,8), 5 -> (4,8), 6 -> (6,9), 7 ->
6788 // (9,7), 8 -> (6,7), 9 -> (5,8), 10 -> (8,9), 11 ->
6789 // (5,9), Line 12 is determined by
6790 // chosen_line_tetrahedron i.e. (6,8), (5,7) or (4,9)
6791
6792 relevant_lines.resize(13);
6793
6794 unsigned int k = 0;
6795 for (unsigned int f = 0; f < 4; ++f)
6796 for (unsigned int l = 0; l < 3; ++l, ++k)
6797 {
6798 // TODO: add comment
6799 static const std::
6800 array<std::array<unsigned int, 3>, 6>
6801 table = {{{{1, 0, 2}}, // 0
6802 {{0, 1, 2}},
6803 {{0, 2, 1}}, // 2
6804 {{1, 2, 0}},
6805 {{2, 1, 0}}, // 4
6806 {{2, 0, 1}}}};
6807
6808 const unsigned char combined_orientation =
6809 hex->combined_face_orientation(f);
6810 relevant_lines[k] =
6811 hex->face(f)
6812 ->child(3 /*center triangle*/)
6813 ->line(table[combined_orientation][l]);
6814 }
6815
6816 relevant_lines[k++] = new_lines[0];
6817 AssertDimension(k, 13);
6818 }
6819 else
6821
6822 boost::container::small_vector<unsigned int, 30>
6823 relevant_line_indices(relevant_lines.size());
6824 for (unsigned int i = 0; i < relevant_line_indices.size();
6825 ++i)
6826 relevant_line_indices[i] = relevant_lines[i]->index();
6827
6828 // It is easierst to start at table cell_vertices,
6829 // there the vertices are listed which build up the
6830 // 8 child tets. To build the child tets, 8 new faces are
6831 // needed. The the vertices, which define the lines of these
6832 // new faces are listed in table_tet. Now only the
6833 // corresponding index of the lines and quads have to be
6834 // listed in new_quad_lines_tet and cell_quads_tet.
6835 const auto &new_quad_lines =
6836 hex->reference_cell().new_isotropic_child_face_lines(
6837 chosen_line_tetrahedron);
6838
6839 // The first 4 define the faces which cut off the
6840 // parent tetrahedron at the edges. the numbers are the
6841 // index of the relevant_lines defined above the last 4
6842 // faces cut apart the remaining octahedron, such that all
6843 // of these contain line number 12. the ordering of the
6844 // faces is arbitrary, the ordering within the faces has to
6845 // follow the righthand convention for triangles
6846 // The table defines the vertices of the lines above
6847 // see relevant_lines for mapping between line indices and
6848 // vertex numbering
6849 const auto &table =
6850 hex->reference_cell()
6851 .new_isotropic_child_face_line_vertices(
6852 chosen_line_tetrahedron);
6853
6854 static constexpr ::ndarray<unsigned int, 4, 2>
6855 representative_lines{
6856 {{{0, 2}}, {{2, 0}}, {{3, 3}}, {{1, 1}}}};
6857
6858 for (unsigned int q = 0; q < n_new_quads; ++q)
6859 {
6860 auto &new_quad = new_quads[q];
6861
6862 if (new_quad->n_lines() == 3)
6863 new_quad->set_bounding_object_indices(
6864 {relevant_line_indices[new_quad_lines[q][0]],
6865 relevant_line_indices[new_quad_lines[q][1]],
6866 relevant_line_indices[new_quad_lines[q][2]]});
6867 else if (new_quad->n_lines() == 4)
6868 new_quad->set_bounding_object_indices(
6869 {relevant_line_indices[new_quad_lines[q][0]],
6870 relevant_line_indices[new_quad_lines[q][1]],
6871 relevant_line_indices[new_quad_lines[q][2]],
6872 relevant_line_indices[new_quad_lines[q][3]]});
6873 else
6875
6876 // On hexes, we must only determine a single line
6877 // according to the representative_lines array above
6878 // (this saves expensive operations), for tets we do
6879 // all lines manually
6880 const unsigned int n_compute_lines =
6881 reference_cell_type == ReferenceCells::Hexahedron ?
6882 1 :
6883 new_quad->n_lines();
6884 for (unsigned int line = 0; line < n_compute_lines;
6885 ++line)
6886 {
6887 const unsigned int l =
6888 (reference_cell_type ==
6890 representative_lines[q % 4][0] :
6891 line;
6892
6893 const std::array<unsigned int, 2> vertices_0 = {
6894 {relevant_lines[new_quad_lines[q][l]]
6895 ->vertex_index(0),
6896 relevant_lines[new_quad_lines[q][l]]
6897 ->vertex_index(1)}};
6898
6899 const std::array<unsigned int, 2> vertices_1 = {
6900 {vertex_indices[table[q][l][0]],
6901 vertex_indices[table[q][l][1]]}};
6902
6903 const auto orientation =
6905 make_array_view(vertices_0),
6906 make_array_view(vertices_1));
6907
6908 new_quad->set_line_orientation(
6909 l,
6910 orientation ==
6912 default_combined_face_orientation());
6913
6914 // on a hex, inject the status of the current line
6915 // also to the line on the other quad along the
6916 // same direction
6917 if (reference_cell_type ==
6919 new_quads[representative_lines[q % 4][1] + q -
6920 (q % 4)]
6921 ->set_line_orientation(
6922 l,
6923 orientation ==
6925 default_combined_face_orientation());
6926 }
6927 }
6928 }
6929
6930 // set up new hex
6931 {
6932 std::array<int, 36> quad_indices;
6933
6934 if (reference_cell_type == ReferenceCells::Hexahedron)
6935 {
6936 for (unsigned int i = 0; i < n_new_quads; ++i)
6937 quad_indices[i] = new_quads[i]->index();
6938
6939 for (unsigned int f = 0, k = n_new_quads; f < 6; ++f)
6940 for (unsigned int c = 0; c < 4; ++c, ++k)
6941 quad_indices[k] =
6942 hex->face(f)->isotropic_child_index(
6944 c,
6945 hex->face_orientation(f),
6946 hex->face_flip(f),
6947 hex->face_rotation(f)));
6948 }
6949 else if (reference_cell_type == ReferenceCells::Tetrahedron)
6950 {
6951 // list of the indices of the surfaces which define the
6952 // 8 new tets. the indices 0-7 are the new quads defined
6953 // above (so 0-3 cut off the corners and 4-7 separate
6954 // the remaining octahedral), the indices between 8-11
6955 // are the children of the first face, from 12-15 of the
6956 // second, etc.
6957 for (unsigned int i = 0; i < n_new_quads; ++i)
6958 quad_indices[i] = new_quads[i]->index();
6959
6960 for (unsigned int f = 0, k = n_new_quads; f < 4; ++f)
6961 for (unsigned int c = 0; c < 4; ++c, ++k)
6962 {
6963 const unsigned char combined_orientation =
6964 hex->combined_face_orientation(f);
6965 quad_indices[k] = hex->face(f)->child_index(
6966 (c == 3) ? 3 :
6967 reference_cell_type
6968 .standard_to_real_face_vertex(
6969 c, f, combined_orientation));
6970 }
6971 }
6972 else
6973 {
6975 }
6976
6977 // indices of the faces which define the new tets
6978 // the ordering of the tets is arbitrary
6979 // the first 4 determine the tets cutting of the corners
6980 // the last 4 are ordered after their appearance in the
6981 // faces.
6982 // the ordering within the faces is determined by
6983 // convention for the tetrahedron unit cell, see
6984 // cell_vertices_tet below
6985 const auto &cell_quads =
6986 hex->reference_cell().new_isotropic_child_cell_faces(
6987 chosen_line_tetrahedron);
6988
6989 for (unsigned int c = 0;
6990 c < GeometryInfo<dim>::max_children_per_cell;
6991 ++c)
6992 {
6993 auto &new_hex = new_hexes[c];
6994
6995 if (new_hex->n_faces() == 4)
6996 {
6997 new_hex->set_bounding_object_indices(
6998 {quad_indices[cell_quads[c][0]],
6999 quad_indices[cell_quads[c][1]],
7000 quad_indices[cell_quads[c][2]],
7001 quad_indices[cell_quads[c][3]]});
7002
7003
7004 // for tets, we need to go through the faces and
7005 // figure the orientation out the hard way
7006 for (const auto f : new_hex->face_indices())
7007 {
7008 const auto &face = new_hex->face(f);
7009
7010 Assert(face->n_vertices() == 3,
7012
7013 const std::array<unsigned int, 3> vertices_0 = {
7014 {face->vertex_index(0),
7015 face->vertex_index(1),
7016 face->vertex_index(2)}};
7017
7018 // the 8 child tets are each defined by 4
7019 // vertices the ordering of the tets has to be
7020 // consistent with above the ordering within the
7021 // tets is given by the reference tet i.e.
7022 // looking at the fifth line the first 3
7023 // vertices are given by face 11, the last
7024 // vertex is the remaining of the tet
7025 const auto new_hex_vertices =
7026 hex->reference_cell()
7027 .new_isotropic_child_cell_vertices(
7028 chosen_line_tetrahedron)[c];
7029
7030 // arrange after vertices of the faces of the
7031 // unit cell
7032 const std::array<unsigned int, 3> vertices_1 = {
7033 {
7035 [new_hex_vertices
7037 .face_to_cell_vertices(f, 0, 1)]],
7039 [new_hex_vertices
7041 .face_to_cell_vertices(f, 1, 1)]],
7043 [new_hex_vertices
7045 .face_to_cell_vertices(f, 2, 1)]],
7046 }};
7047
7048 new_hex->set_combined_face_orientation(
7049 f,
7050 face->reference_cell()
7051 .get_combined_orientation(
7052 make_array_view(vertices_1),
7053 make_array_view(vertices_0)));
7054 }
7055 }
7056 else if (new_hex->n_faces() == 6)
7057 new_hex->set_bounding_object_indices(
7058 {quad_indices[cell_quads[c][0]],
7059 quad_indices[cell_quads[c][1]],
7060 quad_indices[cell_quads[c][2]],
7061 quad_indices[cell_quads[c][3]],
7062 quad_indices[cell_quads[c][4]],
7063 quad_indices[cell_quads[c][5]]});
7064 else
7066 }
7067
7068 // for hexes, we can simply inherit the orientation values
7069 // from the parent on the outer faces; the inner faces can
7070 // be skipped as their orientation is always the default
7071 // one set above
7072 static constexpr ::ndarray<unsigned int, 6, 4>
7073 face_to_child_indices_hex{{{{0, 2, 4, 6}},
7074 {{1, 3, 5, 7}},
7075 {{0, 1, 4, 5}},
7076 {{2, 3, 6, 7}},
7077 {{0, 1, 2, 3}},
7078 {{4, 5, 6, 7}}}};
7079 if (hex->n_faces() == 6)
7080 for (const auto f : hex->face_indices())
7081 {
7082 const unsigned char combined_orientation =
7083 hex->combined_face_orientation(f);
7084 for (unsigned int c = 0; c < 4; ++c)
7085 new_hexes[face_to_child_indices_hex[f][c]]
7086 ->set_combined_face_orientation(
7087 f, combined_orientation);
7088 }
7089 }
7090 }
7091
7092 if (check_for_distorted_cells &&
7093 has_distorted_children<dim, spacedim>(hex))
7094 cells_with_distorted_children.distorted_cells.push_back(hex);
7095
7096 triangulation.signals.post_refinement_on_cell(hex);
7097 }
7098 }
7099
7100 triangulation.faces->quads.clear_user_data();
7101
7102 return cells_with_distorted_children;
7103 }
7104
7109 template <int spacedim>
7112 const bool check_for_distorted_cells)
7113 {
7114 const unsigned int dim = 3;
7115
7116 {
7117 bool flag_isotropic_mesh = true;
7119 cell = triangulation.begin(),
7120 endc = triangulation.end();
7121 for (; cell != endc; ++cell)
7122 if (cell->used())
7123 if (triangulation.get_anisotropic_refinement_flag() ||
7124 cell->refine_flag_set() == RefinementCase<dim>::cut_x ||
7125 cell->refine_flag_set() == RefinementCase<dim>::cut_y ||
7126 cell->refine_flag_set() == RefinementCase<dim>::cut_z ||
7127 cell->refine_flag_set() == RefinementCase<dim>::cut_xy ||
7128 cell->refine_flag_set() == RefinementCase<dim>::cut_xz ||
7129 cell->refine_flag_set() == RefinementCase<dim>::cut_yz)
7130 {
7131 flag_isotropic_mesh = false;
7132 break;
7133 }
7134
7135 if (flag_isotropic_mesh)
7136 return execute_refinement_isotropic(triangulation,
7137 check_for_distorted_cells);
7138 }
7139
7140 // this function probably also works for spacedim>3 but it
7141 // isn't tested. it will probably be necessary to pull new
7142 // vertices onto the manifold just as we do for the other
7143 // functions above.
7144 Assert(spacedim == 3, ExcNotImplemented());
7145
7146 // Check whether a new level is needed. We have to check for
7147 // this on the highest level only
7148 for (const auto &cell : triangulation.active_cell_iterators_on_level(
7149 triangulation.levels.size() - 1))
7150 if (cell->refine_flag_set())
7151 {
7152 triangulation.levels.push_back(
7153 std::make_unique<
7155 break;
7156 }
7157
7158
7159 // first clear user flags for quads and lines; we're going to
7160 // use them to flag which lines and quads need refinement
7161 triangulation.faces->quads.clear_user_data();
7162
7165 line != triangulation.end_line();
7166 ++line)
7167 line->clear_user_flag();
7170 quad != triangulation.end_quad();
7171 ++quad)
7172 quad->clear_user_flag();
7173
7174 // create an array of face refine cases. User indices of faces
7175 // will be set to values corresponding with indices in this
7176 // array.
7177 const RefinementCase<dim - 1> face_refinement_cases[4] = {
7178 RefinementCase<dim - 1>::no_refinement,
7179 RefinementCase<dim - 1>::cut_x,
7180 RefinementCase<dim - 1>::cut_y,
7181 RefinementCase<dim - 1>::cut_xy};
7182
7183 // check how much space is needed on every level. We need not
7184 // check the highest level since either
7185 // - on the highest level no cells are flagged for refinement
7186 // - there are, but prepare_refinement added another empty
7187 // level which then is the highest level
7188
7189 // variables to hold the number of newly to be created
7190 // vertices, lines and quads. as these are stored globally,
7191 // declare them outside the loop over al levels. we need lines
7192 // and quads in pairs for refinement of old ones and lines and
7193 // quads, that can be stored as single ones, as they are newly
7194 // created in the inside of an existing cell
7195 unsigned int needed_vertices = 0;
7196 unsigned int needed_lines_single = 0;
7197 unsigned int needed_quads_single = 0;
7198 unsigned int needed_lines_pair = 0;
7199 unsigned int needed_quads_pair = 0;
7200 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
7201 {
7202 // count number of flagged cells on this level and compute
7203 // how many new vertices and new lines will be needed
7204 unsigned int new_cells = 0;
7205
7206 for (const auto &acell :
7207 triangulation.active_cell_iterators_on_level(level))
7208 if (acell->refine_flag_set())
7209 {
7210 RefinementCase<dim> ref_case = acell->refine_flag_set();
7211
7212 // now for interior vertices, lines and quads, which
7213 // are needed in any case
7214 if (ref_case == RefinementCase<dim>::cut_x ||
7215 ref_case == RefinementCase<dim>::cut_y ||
7216 ref_case == RefinementCase<dim>::cut_z)
7217 {
7218 ++needed_quads_single;
7219 new_cells += 2;
7220 triangulation.anisotropic_refinement = true;
7221 }
7222 else if (ref_case == RefinementCase<dim>::cut_xy ||
7223 ref_case == RefinementCase<dim>::cut_xz ||
7224 ref_case == RefinementCase<dim>::cut_yz)
7225 {
7226 ++needed_lines_single;
7227 needed_quads_single += 4;
7228 new_cells += 4;
7229 triangulation.anisotropic_refinement = true;
7230 }
7231 else if (ref_case == RefinementCase<dim>::cut_xyz)
7232 {
7233 ++needed_vertices;
7234 needed_lines_single += 6;
7235 needed_quads_single += 12;
7236 new_cells += 8;
7237 }
7238 else
7239 {
7240 // we should never get here
7242 }
7243
7244 // mark all faces for refinement; checking locally
7245 // if and how the neighbor would like to refine
7246 // these is difficult so we only flag them and after
7247 // visiting all cells, we decide which faces need
7248 // which refinement;
7249 for (const unsigned int face :
7251 {
7253 aface = acell->face(face);
7254 // get the RefineCase this faces has for the
7255 // given RefineCase of the cell
7256 RefinementCase<dim - 1> face_ref_case =
7258 ref_case,
7259 face,
7260 acell->face_orientation(face),
7261 acell->face_flip(face),
7262 acell->face_rotation(face));
7263 // only do something, if this face has to be
7264 // refined
7265 if (face_ref_case)
7266 {
7267 if (face_ref_case ==
7269 {
7270 if (aface->n_active_descendants() < 4)
7271 // we use user_flags to denote needed
7272 // isotropic refinement
7273 aface->set_user_flag();
7274 }
7275 else if (aface->refinement_case() != face_ref_case)
7276 // we use user_indices to denote needed
7277 // anisotropic refinement. note, that we
7278 // can have at most one anisotropic
7279 // refinement case for this face, as
7280 // otherwise prepare_refinement() would
7281 // have changed one of the cells to yield
7282 // isotropic refinement at this
7283 // face. therefore we set the user_index
7284 // uniquely
7285 {
7286 Assert(aface->refinement_case() ==
7288 dim - 1>::isotropic_refinement ||
7289 aface->refinement_case() ==
7292 aface->set_user_index(face_ref_case);
7293 }
7294 }
7295 } // for all faces
7296
7297 // flag all lines, that have to be refined
7298 for (unsigned int line = 0;
7299 line < GeometryInfo<dim>::lines_per_cell;
7300 ++line)
7302 line) &&
7303 !acell->line(line)->has_children())
7304 acell->line(line)->set_user_flag();
7305
7306 } // if refine_flag set and for all cells on this level
7307
7308
7309 // count number of used cells on the next higher level
7310 const unsigned int used_cells =
7311 std::count(triangulation.levels[level + 1]->cells.used.begin(),
7312 triangulation.levels[level + 1]->cells.used.end(),
7313 true);
7314
7315
7316 // reserve space for the used_cells cells already existing
7317 // on the next higher level as well as for the
7318 // 8*flagged_cells that will be created on that level
7319 reserve_space(*triangulation.levels[level + 1],
7320 used_cells + new_cells,
7321 3,
7322 spacedim);
7323 // reserve space for 8*flagged_cells new hexes on the next
7324 // higher level
7325 reserve_space(triangulation.levels[level + 1]->cells, new_cells);
7326 } // for all levels
7327 // now count the quads and lines which were flagged for
7328 // refinement
7331 quad != triangulation.end_quad();
7332 ++quad)
7333 {
7334 if (quad->user_flag_set())
7335 {
7336 // isotropic refinement: 1 interior vertex, 4 quads
7337 // and 4 interior lines. we store the interior lines
7338 // in pairs in case the face is already or will be
7339 // refined anisotropically
7340 needed_quads_pair += 4;
7341 needed_lines_pair += 4;
7342 needed_vertices += 1;
7343 }
7344 if (quad->user_index())
7345 {
7346 // anisotropic refinement: 1 interior
7347 // line and two quads
7348 needed_quads_pair += 2;
7349 needed_lines_single += 1;
7350 // there is a kind of complicated situation here which
7351 // requires our attention. if the quad is refined
7352 // isotropcally, two of the interior lines will get a
7353 // new mother line - the interior line of our
7354 // anisotropically refined quad. if those two lines
7355 // are not consecutive, we cannot do so and have to
7356 // replace them by two lines that are consecutive. we
7357 // try to avoid that situation, but it may happen
7358 // nevertheless through repeated refinement and
7359 // coarsening. thus we have to check here, as we will
7360 // need some additional space to store those new lines
7361 // in case we need them...
7362 if (quad->has_children())
7363 {
7364 Assert(quad->refinement_case() ==
7367 if ((face_refinement_cases[quad->user_index()] ==
7369 (quad->child(0)->line_index(1) + 1 !=
7370 quad->child(2)->line_index(1))) ||
7371 (face_refinement_cases[quad->user_index()] ==
7373 (quad->child(0)->line_index(3) + 1 !=
7374 quad->child(1)->line_index(3))))
7375 needed_lines_pair += 2;
7376 }
7377 }
7378 }
7379
7382 line != triangulation.end_line();
7383 ++line)
7384 if (line->user_flag_set())
7385 {
7386 needed_lines_pair += 2;
7387 needed_vertices += 1;
7388 }
7389
7390 // reserve space for needed_lines new lines stored in pairs
7391 reserve_space(triangulation.faces->lines,
7392 needed_lines_pair,
7393 needed_lines_single);
7394 // reserve space for needed_quads new quads stored in pairs
7396 needed_quads_pair,
7397 needed_quads_single);
7398 reserve_space(triangulation.faces->quads,
7399 needed_quads_pair,
7400 needed_quads_single);
7401
7402
7403 // add to needed vertices how many vertices are already in use
7404 needed_vertices += std::count(triangulation.vertices_used.begin(),
7405 triangulation.vertices_used.end(),
7406 true);
7407 // if we need more vertices: create them, if not: leave the
7408 // array as is, since shrinking is not really possible because
7409 // some of the vertices at the end may be in use
7410 if (needed_vertices > triangulation.vertices.size())
7411 {
7412 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
7413 triangulation.vertices_used.resize(needed_vertices, false);
7414 }
7415
7416
7417 //-----------------------------------------
7418 // Before we start with the actual refinement, we do some
7419 // sanity checks if in debug mode. especially, we try to catch
7420 // the notorious problem with lines being twice refined,
7421 // i.e. there are cells adjacent at one line ("around the
7422 // edge", but not at a face), with two cells differing by more
7423 // than one refinement level
7424 //
7425 // this check is very simple to implement here, since we have
7426 // all lines flagged if they shall be refined
7427#ifdef DEBUG
7428 for (const auto &cell : triangulation.active_cell_iterators())
7429 if (!cell->refine_flag_set())
7430 for (unsigned int line = 0;
7431 line < GeometryInfo<dim>::lines_per_cell;
7432 ++line)
7433 if (cell->line(line)->has_children())
7434 for (unsigned int c = 0; c < 2; ++c)
7435 Assert(cell->line(line)->child(c)->user_flag_set() == false,
7437#endif
7438
7439 //-----------------------------------------
7440 // Do refinement on every level
7441 //
7442 // To make life a bit easier, we first refine those lines and
7443 // quads that were flagged for refinement and then compose the
7444 // newly to be created cells.
7445 //
7446 // index of next unused vertex
7447 unsigned int next_unused_vertex = 0;
7448
7449 // first for lines
7450 {
7451 // only active objects can be refined further
7454 endl = triangulation.end_line();
7456 next_unused_line = triangulation.begin_raw_line();
7457
7458 for (; line != endl; ++line)
7459 if (line->user_flag_set())
7460 {
7461 // this line needs to be refined
7462
7463 // find the next unused vertex and set it
7464 // appropriately
7465 while (triangulation.vertices_used[next_unused_vertex] == true)
7466 ++next_unused_vertex;
7467 Assert(
7468 next_unused_vertex < triangulation.vertices.size(),
7469 ExcMessage(
7470 "Internal error: During refinement, the triangulation wants to access an element of the 'vertices' array but it turns out that the array is not large enough."));
7471 triangulation.vertices_used[next_unused_vertex] = true;
7472
7473 triangulation.vertices[next_unused_vertex] = line->center(true);
7474
7475 // now that we created the right point, make up the
7476 // two child lines (++ takes care of the end of the
7477 // vector)
7478 next_unused_line =
7479 triangulation.faces->lines.template next_free_pair_object<1>(
7481 Assert(next_unused_line.state() == IteratorState::valid,
7483
7484 // now we found two consecutive unused lines, such
7485 // that the children of a line will be consecutive.
7486 // then set the child pointer of the present line
7487 line->set_children(0, next_unused_line->index());
7488
7489 // set the two new lines
7491 children[2] = {next_unused_line, ++next_unused_line};
7492
7493 // some tests; if any of the iterators should be
7494 // invalid, then already dereferencing will fail
7495 AssertIsNotUsed(children[0]);
7496 AssertIsNotUsed(children[1]);
7497
7498 children[0]->set_bounding_object_indices(
7499 {line->vertex_index(0), next_unused_vertex});
7500 children[1]->set_bounding_object_indices(
7501 {next_unused_vertex, line->vertex_index(1)});
7502
7503 children[0]->set_used_flag();
7504 children[1]->set_used_flag();
7505 children[0]->clear_children();
7506 children[1]->clear_children();
7507 children[0]->clear_user_data();
7508 children[1]->clear_user_data();
7509 children[0]->clear_user_flag();
7510 children[1]->clear_user_flag();
7511
7512 children[0]->set_boundary_id_internal(line->boundary_id());
7513 children[1]->set_boundary_id_internal(line->boundary_id());
7514
7515 children[0]->set_manifold_id(line->manifold_id());
7516 children[1]->set_manifold_id(line->manifold_id());
7517
7518 // finally clear flag
7519 // indicating the need
7520 // for refinement
7521 line->clear_user_flag();
7522 }
7523 }
7524
7525
7526 //-------------------------------------
7527 // now refine marked quads
7528 //-------------------------------------
7529
7530 // here we encounter several cases:
7531
7532 // a) the quad is unrefined and shall be refined isotropically
7533
7534 // b) the quad is unrefined and shall be refined
7535 // anisotropically
7536
7537 // c) the quad is unrefined and shall be refined both
7538 // anisotropically and isotropically (this is reduced to case
7539 // b) and then case b) for the children again)
7540
7541 // d) the quad is refined anisotropically and shall be refined
7542 // isotropically (this is reduced to case b) for the
7543 // anisotropic children)
7544
7545 // e) the quad is refined isotropically and shall be refined
7546 // anisotropically (this is transformed to case c), however we
7547 // might have to renumber/rename children...)
7548
7549 // we need a loop in cases c) and d), as the anisotropic
7550 // children might have a lower index than the mother quad
7551 for (unsigned int loop = 0; loop < 2; ++loop)
7552 {
7553 // usually, only active objects can be refined
7554 // further. however, in cases d) and e) that is not true,
7555 // so we have to use 'normal' iterators here
7557 quad = triangulation.begin_quad(),
7558 endq = triangulation.end_quad();
7560 next_unused_line = triangulation.begin_raw_line();
7562 next_unused_quad = triangulation.begin_raw_quad();
7563
7564 for (; quad != endq; ++quad)
7565 {
7566 if (quad->user_index())
7567 {
7568 RefinementCase<dim - 1> aniso_quad_ref_case =
7569 face_refinement_cases[quad->user_index()];
7570 // there is one unlikely event here, where we
7571 // already have refind the face: if the face was
7572 // refined anisotropically and we want to refine
7573 // it isotropically, both children are flagged for
7574 // anisotropic refinement. however, if those
7575 // children were already flagged for anisotropic
7576 // refinement, they might already be processed and
7577 // refined.
7578 if (aniso_quad_ref_case == quad->refinement_case())
7579 continue;
7580
7581 Assert(quad->refinement_case() ==
7583 quad->refinement_case() ==
7586
7587 // this quad needs to be refined anisotropically
7588 Assert(quad->user_index() ==
7590 quad->user_index() ==
7593
7594 // make the new line interior to the quad
7596 new_line;
7597
7598 new_line =
7599 triangulation.faces->lines
7600 .template next_free_single_object<1>(triangulation);
7601 AssertIsNotUsed(new_line);
7602
7603 // first collect the
7604 // indices of the vertices:
7605 // *--1--*
7606 // | | |
7607 // | | | cut_x
7608 // | | |
7609 // *--0--*
7610 //
7611 // *-----*
7612 // | |
7613 // 0-----1 cut_y
7614 // | |
7615 // *-----*
7616 unsigned int vertex_indices[2];
7617 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
7618 {
7619 vertex_indices[0] =
7620 quad->line(2)->child(0)->vertex_index(1);
7621 vertex_indices[1] =
7622 quad->line(3)->child(0)->vertex_index(1);
7623 }
7624 else
7625 {
7626 vertex_indices[0] =
7627 quad->line(0)->child(0)->vertex_index(1);
7628 vertex_indices[1] =
7629 quad->line(1)->child(0)->vertex_index(1);
7630 }
7631
7632 new_line->set_bounding_object_indices(
7634 new_line->set_used_flag();
7635 new_line->clear_user_flag();
7636 new_line->clear_user_data();
7637 new_line->clear_children();
7638 new_line->set_boundary_id_internal(quad->boundary_id());
7639 new_line->set_manifold_id(quad->manifold_id());
7640
7641 // child 0 and 1 of a line are switched if the
7642 // line orientation is false. set up a miniature
7643 // table, indicating which child to take for line
7644 // orientations false and true. first index: child
7645 // index in standard orientation, second index:
7646 // line orientation
7647 const unsigned int index[2][2] = {
7648 {1, 0}, // child 0, line_orientation=false and true
7649 {0, 1}}; // child 1, line_orientation=false and true
7650
7651 // find some space (consecutive) for the two newly
7652 // to be created quads.
7654 new_quads[2];
7655
7656 next_unused_quad =
7657 triangulation.faces->quads
7658 .template next_free_pair_object<2>(triangulation);
7659 new_quads[0] = next_unused_quad;
7660 AssertIsNotUsed(new_quads[0]);
7661
7662 ++next_unused_quad;
7663 new_quads[1] = next_unused_quad;
7664 AssertIsNotUsed(new_quads[1]);
7665
7666 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
7667 {
7668 new_quads[0]->set_bounding_object_indices(
7669 {static_cast<int>(quad->line_index(0)),
7670 new_line->index(),
7671 quad->line(2)
7672 ->child(index[0][quad->line_orientation(2)])
7673 ->index(),
7674 quad->line(3)
7675 ->child(index[0][quad->line_orientation(3)])
7676 ->index()});
7677 new_quads[1]->set_bounding_object_indices(
7678 {new_line->index(),
7679 static_cast<int>(quad->line_index(1)),
7680 quad->line(2)
7681 ->child(index[1][quad->line_orientation(2)])
7682 ->index(),
7683 quad->line(3)
7684 ->child(index[1][quad->line_orientation(3)])
7685 ->index()});
7686 }
7687 else
7688 {
7689 new_quads[0]->set_bounding_object_indices(
7690 {quad->line(0)
7691 ->child(index[0][quad->line_orientation(0)])
7692 ->index(),
7693 quad->line(1)
7694 ->child(index[0][quad->line_orientation(1)])
7695 ->index(),
7696 static_cast<int>(quad->line_index(2)),
7697 new_line->index()});
7698 new_quads[1]->set_bounding_object_indices(
7699 {quad->line(0)
7700 ->child(index[1][quad->line_orientation(0)])
7701 ->index(),
7702 quad->line(1)
7703 ->child(index[1][quad->line_orientation(1)])
7704 ->index(),
7705 new_line->index(),
7706 static_cast<int>(quad->line_index(3))});
7707 }
7708
7709 for (const auto &new_quad : new_quads)
7710 {
7711 new_quad->set_used_flag();
7712 new_quad->clear_user_flag();
7713 new_quad->clear_user_data();
7714 new_quad->clear_children();
7715 new_quad->set_boundary_id_internal(quad->boundary_id());
7716 new_quad->set_manifold_id(quad->manifold_id());
7717 // set all line orientations to true, change
7718 // this after the loop, as we have to consider
7719 // different lines for each child
7720 for (unsigned int j = 0;
7721 j < GeometryInfo<dim>::lines_per_face;
7722 ++j)
7723 new_quad->set_line_orientation(j, true);
7724 }
7725 // now set the line orientation of children of
7726 // outer lines correctly, the lines in the
7727 // interior of the refined quad are automatically
7728 // oriented conforming to the standard
7729 new_quads[0]->set_line_orientation(
7730 0, quad->line_orientation(0));
7731 new_quads[0]->set_line_orientation(
7732 2, quad->line_orientation(2));
7733 new_quads[1]->set_line_orientation(
7734 1, quad->line_orientation(1));
7735 new_quads[1]->set_line_orientation(
7736 3, quad->line_orientation(3));
7737 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
7738 {
7739 new_quads[0]->set_line_orientation(
7740 3, quad->line_orientation(3));
7741 new_quads[1]->set_line_orientation(
7742 2, quad->line_orientation(2));
7743 }
7744 else
7745 {
7746 new_quads[0]->set_line_orientation(
7747 1, quad->line_orientation(1));
7748 new_quads[1]->set_line_orientation(
7749 0, quad->line_orientation(0));
7750 }
7751
7752 // test, whether this face is refined
7753 // isotropically already. if so, set the correct
7754 // children pointers.
7755 if (quad->refinement_case() ==
7756 RefinementCase<dim - 1>::cut_xy)
7757 {
7758 // we will put a new refinemnt level of
7759 // anisotropic refinement between the
7760 // unrefined and isotropically refined quad
7761 // ending up with the same fine quads but
7762 // introducing anisotropically refined ones as
7763 // children of the unrefined quad and mother
7764 // cells of the original fine ones.
7765
7766 // this process includes the creation of a new
7767 // middle line which we will assign as the
7768 // mother line of two of the existing inner
7769 // lines. If those inner lines are not
7770 // consecutive in memory, we won't find them
7771 // later on, so we have to create new ones
7772 // instead and replace all occurrences of the
7773 // old ones with those new ones. As this is
7774 // kind of ugly, we hope we don't have to do
7775 // it often...
7777 old_child[2];
7778 if (aniso_quad_ref_case ==
7780 {
7781 old_child[0] = quad->child(0)->line(1);
7782 old_child[1] = quad->child(2)->line(1);
7783 }
7784 else
7785 {
7786 Assert(aniso_quad_ref_case ==
7789
7790 old_child[0] = quad->child(0)->line(3);
7791 old_child[1] = quad->child(1)->line(3);
7792 }
7793
7794 if (old_child[0]->index() + 1 != old_child[1]->index())
7795 {
7796 // this is exactly the ugly case we talked
7797 // about. so, no complaining, lets get
7798 // two new lines and copy all info
7799 typename Triangulation<dim,
7800 spacedim>::raw_line_iterator
7801 new_child[2];
7802
7803 new_child[0] = new_child[1] =
7804 triangulation.faces->lines
7805 .template next_free_pair_object<1>(
7807 ++new_child[1];
7808
7809 new_child[0]->set_used_flag();
7810 new_child[1]->set_used_flag();
7811
7812 const int old_index_0 = old_child[0]->index(),
7813 old_index_1 = old_child[1]->index(),
7814 new_index_0 = new_child[0]->index(),
7815 new_index_1 = new_child[1]->index();
7816
7817 // loop over all quads and replace the old
7818 // lines
7819 for (unsigned int q = 0;
7820 q < triangulation.faces->quads.n_objects();
7821 ++q)
7822 for (unsigned int l = 0;
7823 l < GeometryInfo<dim>::lines_per_face;
7824 ++l)
7825 {
7826 const int this_index =
7827 triangulation.faces->quads
7828 .get_bounding_object_indices(q)[l];
7829 if (this_index == old_index_0)
7830 triangulation.faces->quads
7831 .get_bounding_object_indices(q)[l] =
7832 new_index_0;
7833 else if (this_index == old_index_1)
7834 triangulation.faces->quads
7835 .get_bounding_object_indices(q)[l] =
7836 new_index_1;
7837 }
7838 // now we have to copy all information of
7839 // the two lines
7840 for (unsigned int i = 0; i < 2; ++i)
7841 {
7842 Assert(!old_child[i]->has_children(),
7844
7845 new_child[i]->set_bounding_object_indices(
7846 {old_child[i]->vertex_index(0),
7847 old_child[i]->vertex_index(1)});
7848 new_child[i]->set_boundary_id_internal(
7849 old_child[i]->boundary_id());
7850 new_child[i]->set_manifold_id(
7851 old_child[i]->manifold_id());
7852 new_child[i]->set_user_index(
7853 old_child[i]->user_index());
7854 if (old_child[i]->user_flag_set())
7855 new_child[i]->set_user_flag();
7856 else
7857 new_child[i]->clear_user_flag();
7858
7859 new_child[i]->clear_children();
7860
7861 old_child[i]->clear_user_flag();
7862 old_child[i]->clear_user_index();
7863 old_child[i]->clear_used_flag();
7864 }
7865 }
7866 // now that we cared about the lines, go on
7867 // with the quads themselves, where we might
7868 // encounter similar situations...
7869 if (aniso_quad_ref_case ==
7871 {
7872 new_line->set_children(
7873 0, quad->child(0)->line_index(1));
7874 Assert(new_line->child(1) ==
7875 quad->child(2)->line(1),
7877 // now evereything is quite
7878 // complicated. we have the children
7879 // numbered according to
7880 //
7881 // *---*---*
7882 // |n+2|n+3|
7883 // *---*---*
7884 // | n |n+1|
7885 // *---*---*
7886 //
7887 // from the original isotropic
7888 // refinement. we have to reorder them as
7889 //
7890 // *---*---*
7891 // |n+1|n+3|
7892 // *---*---*
7893 // | n |n+2|
7894 // *---*---*
7895 //
7896 // such that n and n+1 are consecutive
7897 // children of m and n+2 and n+3 are
7898 // consecutive children of m+1, where m
7899 // and m+1 are given as in
7900 //
7901 // *---*---*
7902 // | | |
7903 // | m |m+1|
7904 // | | |
7905 // *---*---*
7906 //
7907 // this is a bit ugly, of course: loop
7908 // over all cells on all levels and look
7909 // for faces n+1 (switch_1) and n+2
7910 // (switch_2).
7911 const typename Triangulation<dim, spacedim>::
7912 quad_iterator switch_1 = quad->child(1),
7913 switch_2 = quad->child(2);
7914 const int switch_1_index = switch_1->index();
7915 const int switch_2_index = switch_2->index();
7916 for (unsigned int l = 0;
7917 l < triangulation.levels.size();
7918 ++l)
7919 for (unsigned int h = 0;
7920 h <
7921 triangulation.levels[l]->cells.n_objects();
7922 ++h)
7923 for (const unsigned int q :
7925 {
7926 const int face_index =
7928 ->cells.get_bounding_object_indices(
7929 h)[q];
7930 if (face_index == switch_1_index)
7931 triangulation.levels[l]
7932 ->cells.get_bounding_object_indices(
7933 h)[q] = switch_2_index;
7934 else if (face_index == switch_2_index)
7935 triangulation.levels[l]
7936 ->cells.get_bounding_object_indices(
7937 h)[q] = switch_1_index;
7938 }
7939 // now we have to copy all information of
7940 // the two quads
7941 const unsigned int switch_1_lines[4] = {
7942 switch_1->line_index(0),
7943 switch_1->line_index(1),
7944 switch_1->line_index(2),
7945 switch_1->line_index(3)};
7946 const bool switch_1_line_orientations[4] = {
7947 switch_1->line_orientation(0),
7948 switch_1->line_orientation(1),
7949 switch_1->line_orientation(2),
7950 switch_1->line_orientation(3)};
7951 const types::boundary_id switch_1_boundary_id =
7952 switch_1->boundary_id();
7953 const unsigned int switch_1_user_index =
7954 switch_1->user_index();
7955 const bool switch_1_user_flag =
7956 switch_1->user_flag_set();
7957 const RefinementCase<dim - 1>
7958 switch_1_refinement_case =
7959 switch_1->refinement_case();
7960 const int switch_1_first_child_pair =
7961 (switch_1_refinement_case ?
7962 switch_1->child_index(0) :
7963 -1);
7964 const int switch_1_second_child_pair =
7965 (switch_1_refinement_case ==
7966 RefinementCase<dim - 1>::cut_xy ?
7967 switch_1->child_index(2) :
7968 -1);
7969
7970 switch_1->set_bounding_object_indices(
7971 {switch_2->line_index(0),
7972 switch_2->line_index(1),
7973 switch_2->line_index(2),
7974 switch_2->line_index(3)});
7975 switch_1->set_line_orientation(
7976 0, switch_2->line_orientation(0));
7977 switch_1->set_line_orientation(
7978 1, switch_2->line_orientation(1));
7979 switch_1->set_line_orientation(
7980 2, switch_2->line_orientation(2));
7981 switch_1->set_line_orientation(
7982 3, switch_2->line_orientation(3));
7983 switch_1->set_boundary_id_internal(
7984 switch_2->boundary_id());
7985 switch_1->set_manifold_id(switch_2->manifold_id());
7986 switch_1->set_user_index(switch_2->user_index());
7987 if (switch_2->user_flag_set())
7988 switch_1->set_user_flag();
7989 else
7990 switch_1->clear_user_flag();
7991 switch_1->clear_refinement_case();
7992 switch_1->set_refinement_case(
7993 switch_2->refinement_case());
7994 switch_1->clear_children();
7995 if (switch_2->refinement_case())
7996 switch_1->set_children(0,
7997 switch_2->child_index(0));
7998 if (switch_2->refinement_case() ==
7999 RefinementCase<dim - 1>::cut_xy)
8000 switch_1->set_children(2,
8001 switch_2->child_index(2));
8002
8003 switch_2->set_bounding_object_indices(
8004 {switch_1_lines[0],
8005 switch_1_lines[1],
8006 switch_1_lines[2],
8007 switch_1_lines[3]});
8008 switch_2->set_line_orientation(
8009 0, switch_1_line_orientations[0]);
8010 switch_2->set_line_orientation(
8011 1, switch_1_line_orientations[1]);
8012 switch_2->set_line_orientation(
8013 2, switch_1_line_orientations[2]);
8014 switch_2->set_line_orientation(
8015 3, switch_1_line_orientations[3]);
8016 switch_2->set_boundary_id_internal(
8017 switch_1_boundary_id);
8018 switch_2->set_manifold_id(switch_1->manifold_id());
8019 switch_2->set_user_index(switch_1_user_index);
8020 if (switch_1_user_flag)
8021 switch_2->set_user_flag();
8022 else
8023 switch_2->clear_user_flag();
8024 switch_2->clear_refinement_case();
8025 switch_2->set_refinement_case(
8026 switch_1_refinement_case);
8027 switch_2->clear_children();
8028 switch_2->set_children(0,
8029 switch_1_first_child_pair);
8030 switch_2->set_children(2,
8031 switch_1_second_child_pair);
8032
8033 new_quads[0]->set_refinement_case(
8035 new_quads[0]->set_children(0, quad->child_index(0));
8036 new_quads[1]->set_refinement_case(
8038 new_quads[1]->set_children(0, quad->child_index(2));
8039 }
8040 else
8041 {
8042 new_quads[0]->set_refinement_case(
8044 new_quads[0]->set_children(0, quad->child_index(0));
8045 new_quads[1]->set_refinement_case(
8047 new_quads[1]->set_children(0, quad->child_index(2));
8048 new_line->set_children(
8049 0, quad->child(0)->line_index(3));
8050 Assert(new_line->child(1) ==
8051 quad->child(1)->line(3),
8053 }
8054 quad->clear_children();
8055 }
8056
8057 // note these quads as children to the present one
8058 quad->set_children(0, new_quads[0]->index());
8059
8060 quad->set_refinement_case(aniso_quad_ref_case);
8061
8062 // finally clear flag indicating the need for
8063 // refinement
8064 quad->clear_user_data();
8065 } // if (anisotropic refinement)
8066
8067 if (quad->user_flag_set())
8068 {
8069 // this quad needs to be refined isotropically
8070
8071 // first of all: we only get here in the first run
8072 // of the loop
8073 Assert(loop == 0, ExcInternalError());
8074
8075 // find the next unused vertex. we'll need this in
8076 // any case
8077 while (triangulation.vertices_used[next_unused_vertex] ==
8078 true)
8079 ++next_unused_vertex;
8080 Assert(
8081 next_unused_vertex < triangulation.vertices.size(),
8082 ExcMessage(
8083 "Internal error: During refinement, the triangulation wants to access an element of the 'vertices' array but it turns out that the array is not large enough."));
8084
8085 // now: if the quad is refined anisotropically
8086 // already, set the anisotropic refinement flag
8087 // for both children. Additionally, we have to
8088 // refine the inner line, as it is an outer line
8089 // of the two (anisotropic) children
8090 const RefinementCase<dim - 1> quad_ref_case =
8091 quad->refinement_case();
8092
8093 if (quad_ref_case == RefinementCase<dim - 1>::cut_x ||
8094 quad_ref_case == RefinementCase<dim - 1>::cut_y)
8095 {
8096 // set the 'opposite' refine case for children
8097 quad->child(0)->set_user_index(
8098 RefinementCase<dim - 1>::cut_xy - quad_ref_case);
8099 quad->child(1)->set_user_index(
8100 RefinementCase<dim - 1>::cut_xy - quad_ref_case);
8101 // refine the inner line
8103 middle_line;
8104 if (quad_ref_case == RefinementCase<dim - 1>::cut_x)
8105 middle_line = quad->child(0)->line(1);
8106 else
8107 middle_line = quad->child(0)->line(3);
8108
8109 // if the face has been refined
8110 // anisotropically in the last refinement step
8111 // it might be, that it is flagged already and
8112 // that the middle line is thus refined
8113 // already. if not create children.
8114 if (!middle_line->has_children())
8115 {
8116 // set the middle vertex
8117 // appropriately. double refinement of
8118 // quads can only happen in the interior
8119 // of the domain, so we need not care
8120 // about boundary quads here
8121 triangulation.vertices[next_unused_vertex] =
8122 middle_line->center(true);
8123 triangulation.vertices_used[next_unused_vertex] =
8124 true;
8125
8126 // now search a slot for the two
8127 // child lines
8128 next_unused_line =
8129 triangulation.faces->lines
8130 .template next_free_pair_object<1>(
8132
8133 // set the child pointer of the present
8134 // line
8135 middle_line->set_children(
8136 0, next_unused_line->index());
8137
8138 // set the two new lines
8139 const typename Triangulation<dim, spacedim>::
8140 raw_line_iterator children[2] = {
8141 next_unused_line, ++next_unused_line};
8142
8143 // some tests; if any of the iterators
8144 // should be invalid, then already
8145 // dereferencing will fail
8146 AssertIsNotUsed(children[0]);
8147 AssertIsNotUsed(children[1]);
8148
8149 children[0]->set_bounding_object_indices(
8150 {middle_line->vertex_index(0),
8151 next_unused_vertex});
8152 children[1]->set_bounding_object_indices(
8153 {next_unused_vertex,
8154 middle_line->vertex_index(1)});
8155
8156 children[0]->set_used_flag();
8157 children[1]->set_used_flag();
8158 children[0]->clear_children();
8159 children[1]->clear_children();
8160 children[0]->clear_user_data();
8161 children[1]->clear_user_data();
8162 children[0]->clear_user_flag();
8163 children[1]->clear_user_flag();
8164
8165 children[0]->set_boundary_id_internal(
8166 middle_line->boundary_id());
8167 children[1]->set_boundary_id_internal(
8168 middle_line->boundary_id());
8169
8170 children[0]->set_manifold_id(
8171 middle_line->manifold_id());
8172 children[1]->set_manifold_id(
8173 middle_line->manifold_id());
8174 }
8175 // now remove the flag from the quad and go to
8176 // the next quad, the actual refinement of the
8177 // quad takes place later on in this pass of
8178 // the loop or in the next one
8179 quad->clear_user_flag();
8180 continue;
8181 } // if (several refinement cases)
8182
8183 // if we got here, we have an unrefined quad and
8184 // have to do the usual work like in an purely
8185 // isotropic refinement
8186 Assert(quad_ref_case ==
8189
8190 // set the middle vertex appropriately: it might be that
8191 // the quad itself is not at the boundary, but that one of
8192 // its lines actually is. in this case, the newly created
8193 // vertices at the centers of the lines are not
8194 // necessarily the mean values of the adjacent vertices,
8195 // so do not compute the new vertex as the mean value of
8196 // the 4 vertices of the face, but rather as a weighted
8197 // mean value of the 8 vertices which we already have (the
8198 // four old ones, and the four ones inserted as middle
8199 // points for the four lines). summing up some more points
8200 // is generally cheaper than first asking whether one of
8201 // the lines is at the boundary
8202 //
8203 // note that the exact weights are chosen such as to
8204 // minimize the distortion of the four new quads from the
8205 // optimal shape. their description uses the formulas
8206 // underlying the TransfiniteInterpolationManifold
8207 // implementation
8208 triangulation.vertices[next_unused_vertex] =
8209 quad->center(true, true);
8210 triangulation.vertices_used[next_unused_vertex] = true;
8211
8212 // now that we created the right point, make up
8213 // the four lines interior to the quad (++ takes
8214 // care of the end of the vector)
8216 new_lines[4];
8217
8218 for (unsigned int i = 0; i < 4; ++i)
8219 {
8220 if (i % 2 == 0)
8221 // search a free pair of lines for 0. and
8222 // 2. line, so that two of them end up
8223 // together, which is necessary if later on
8224 // we want to refine the quad
8225 // anisotropically and the two lines end up
8226 // as children of new line
8227 next_unused_line =
8228 triangulation.faces->lines
8229 .template next_free_pair_object<1>(triangulation);
8230
8231 new_lines[i] = next_unused_line;
8232 ++next_unused_line;
8233
8234 AssertIsNotUsed(new_lines[i]);
8235 }
8236
8237 // set the data of the four lines. first collect
8238 // the indices of the five vertices:
8239 //
8240 // *--3--*
8241 // | | |
8242 // 0--4--1
8243 // | | |
8244 // *--2--*
8245 //
8246 // the lines are numbered as follows:
8247 //
8248 // *--*--*
8249 // | 1 |
8250 // *2-*-3*
8251 // | 0 |
8252 // *--*--*
8253
8254 const unsigned int vertex_indices[5] = {
8255 quad->line(0)->child(0)->vertex_index(1),
8256 quad->line(1)->child(0)->vertex_index(1),
8257 quad->line(2)->child(0)->vertex_index(1),
8258 quad->line(3)->child(0)->vertex_index(1),
8259 next_unused_vertex};
8260
8261 new_lines[0]->set_bounding_object_indices(
8263 new_lines[1]->set_bounding_object_indices(
8265 new_lines[2]->set_bounding_object_indices(
8267 new_lines[3]->set_bounding_object_indices(
8269
8270 for (const auto &new_line : new_lines)
8271 {
8272 new_line->set_used_flag();
8273 new_line->clear_user_flag();
8274 new_line->clear_user_data();
8275 new_line->clear_children();
8276 new_line->set_boundary_id_internal(quad->boundary_id());
8277 new_line->set_manifold_id(quad->manifold_id());
8278 }
8279
8280 // now for the quads. again, first collect some
8281 // data about the indices of the lines, with the
8282 // following numbering:
8283 //
8284 // .-6-.-7-.
8285 // 1 9 3
8286 // .-10.11-.
8287 // 0 8 2
8288 // .-4-.-5-.
8289
8290 // child 0 and 1 of a line are switched if the
8291 // line orientation is false. set up a miniature
8292 // table, indicating which child to take for line
8293 // orientations false and true. first index: child
8294 // index in standard orientation, second index:
8295 // line orientation
8296 const unsigned int index[2][2] = {
8297 {1, 0}, // child 0, line_orientation=false and true
8298 {0, 1}}; // child 1, line_orientation=false and true
8299
8300 const int line_indices[12] = {
8301 quad->line(0)
8302 ->child(index[0][quad->line_orientation(0)])
8303 ->index(),
8304 quad->line(0)
8305 ->child(index[1][quad->line_orientation(0)])
8306 ->index(),
8307 quad->line(1)
8308 ->child(index[0][quad->line_orientation(1)])
8309 ->index(),
8310 quad->line(1)
8311 ->child(index[1][quad->line_orientation(1)])
8312 ->index(),
8313 quad->line(2)
8314 ->child(index[0][quad->line_orientation(2)])
8315 ->index(),
8316 quad->line(2)
8317 ->child(index[1][quad->line_orientation(2)])
8318 ->index(),
8319 quad->line(3)
8320 ->child(index[0][quad->line_orientation(3)])
8321 ->index(),
8322 quad->line(3)
8323 ->child(index[1][quad->line_orientation(3)])
8324 ->index(),
8325 new_lines[0]->index(),
8326 new_lines[1]->index(),
8327 new_lines[2]->index(),
8328 new_lines[3]->index()};
8329
8330 // find some space (consecutive)
8331 // for the first two newly to be
8332 // created quads.
8334 new_quads[4];
8335
8336 next_unused_quad =
8337 triangulation.faces->quads
8338 .template next_free_pair_object<2>(triangulation);
8339
8340 new_quads[0] = next_unused_quad;
8341 AssertIsNotUsed(new_quads[0]);
8342
8343 ++next_unused_quad;
8344 new_quads[1] = next_unused_quad;
8345 AssertIsNotUsed(new_quads[1]);
8346
8347 next_unused_quad =
8348 triangulation.faces->quads
8349 .template next_free_pair_object<2>(triangulation);
8350 new_quads[2] = next_unused_quad;
8351 AssertIsNotUsed(new_quads[2]);
8352
8353 ++next_unused_quad;
8354 new_quads[3] = next_unused_quad;
8355 AssertIsNotUsed(new_quads[3]);
8356
8357 // note these quads as children to the present one
8358 quad->set_children(0, new_quads[0]->index());
8359 quad->set_children(2, new_quads[2]->index());
8360 quad->set_refinement_case(RefinementCase<2>::cut_xy);
8361
8362 new_quads[0]->set_bounding_object_indices(
8363 {line_indices[0],
8364 line_indices[8],
8365 line_indices[4],
8366 line_indices[10]});
8367 new_quads[1]->set_bounding_object_indices(
8368 {line_indices[8],
8369 line_indices[2],
8370 line_indices[5],
8371 line_indices[11]});
8372 new_quads[2]->set_bounding_object_indices(
8373 {line_indices[1],
8374 line_indices[9],
8375 line_indices[10],
8376 line_indices[6]});
8377 new_quads[3]->set_bounding_object_indices(
8378 {line_indices[9],
8379 line_indices[3],
8380 line_indices[11],
8381 line_indices[7]});
8382 for (const auto &new_quad : new_quads)
8383 {
8384 new_quad->set_used_flag();
8385 new_quad->clear_user_flag();
8386 new_quad->clear_user_data();
8387 new_quad->clear_children();
8388 new_quad->set_boundary_id_internal(quad->boundary_id());
8389 new_quad->set_manifold_id(quad->manifold_id());
8390 // set all line orientations to true, change
8391 // this after the loop, as we have to consider
8392 // different lines for each child
8393 for (unsigned int j = 0;
8394 j < GeometryInfo<dim>::lines_per_face;
8395 ++j)
8396 new_quad->set_line_orientation(j, true);
8397 }
8398 // now set the line orientation of children of
8399 // outer lines correctly, the lines in the
8400 // interior of the refined quad are automatically
8401 // oriented conforming to the standard
8402 new_quads[0]->set_line_orientation(
8403 0, quad->line_orientation(0));
8404 new_quads[0]->set_line_orientation(
8405 2, quad->line_orientation(2));
8406 new_quads[1]->set_line_orientation(
8407 1, quad->line_orientation(1));
8408 new_quads[1]->set_line_orientation(
8409 2, quad->line_orientation(2));
8410 new_quads[2]->set_line_orientation(
8411 0, quad->line_orientation(0));
8412 new_quads[2]->set_line_orientation(
8413 3, quad->line_orientation(3));
8414 new_quads[3]->set_line_orientation(
8415 1, quad->line_orientation(1));
8416 new_quads[3]->set_line_orientation(
8417 3, quad->line_orientation(3));
8418
8419 // finally clear flag indicating the need for
8420 // refinement
8421 quad->clear_user_flag();
8422 } // if (isotropic refinement)
8423 } // for all quads
8424 } // looped two times over all quads, all quads refined now
8425
8426 //---------------------------------
8427 // Now, finally, set up the new
8428 // cells
8429 //---------------------------------
8430
8432 cells_with_distorted_children;
8433
8434 for (unsigned int level = 0; level != triangulation.levels.size() - 1;
8435 ++level)
8436 {
8437 // only active objects can be refined further; remember
8438 // that we won't operate on the finest level, so
8439 // triangulation.begin_*(level+1) is allowed
8442 endh = triangulation.begin_active_hex(level + 1);
8444 next_unused_hex = triangulation.begin_raw_hex(level + 1);
8445
8446 for (; hex != endh; ++hex)
8447 if (hex->refine_flag_set())
8448 {
8449 // this hex needs to be refined
8450
8451 // clear flag indicating the need for refinement. do
8452 // it here already, since we can't do it anymore
8453 // once the cell has children
8454 const RefinementCase<dim> ref_case = hex->refine_flag_set();
8455 hex->clear_refine_flag();
8456 hex->set_refinement_case(ref_case);
8457
8458 // depending on the refine case we might have to
8459 // create additional vertices, lines and quads
8460 // interior of the hex before the actual children
8461 // can be set up.
8462
8463 // in a first step: reserve the needed space for
8464 // lines, quads and hexes and initialize them
8465 // correctly
8466
8467 unsigned int n_new_lines = 0;
8468 unsigned int n_new_quads = 0;
8469 unsigned int n_new_hexes = 0;
8470 switch (ref_case)
8471 {
8475 n_new_lines = 0;
8476 n_new_quads = 1;
8477 n_new_hexes = 2;
8478 break;
8482 n_new_lines = 1;
8483 n_new_quads = 4;
8484 n_new_hexes = 4;
8485 break;
8487 n_new_lines = 6;
8488 n_new_quads = 12;
8489 n_new_hexes = 8;
8490 break;
8491 default:
8493 break;
8494 }
8495
8496 // find some space for the newly to be created
8497 // interior lines and initialize them.
8498 std::vector<
8500 new_lines(n_new_lines);
8501 for (unsigned int i = 0; i < n_new_lines; ++i)
8502 {
8503 new_lines[i] =
8504 triangulation.faces->lines
8505 .template next_free_single_object<1>(triangulation);
8506
8507 AssertIsNotUsed(new_lines[i]);
8508 new_lines[i]->set_used_flag();
8509 new_lines[i]->clear_user_flag();
8510 new_lines[i]->clear_user_data();
8511 new_lines[i]->clear_children();
8512 // interior line
8513 new_lines[i]->set_boundary_id_internal(
8515 // they inherit geometry description of the hex they
8516 // belong to
8517 new_lines[i]->set_manifold_id(hex->manifold_id());
8518 }
8519
8520 // find some space for the newly to be created
8521 // interior quads and initialize them.
8522 std::vector<
8524 new_quads(n_new_quads);
8525 for (unsigned int i = 0; i < n_new_quads; ++i)
8526 {
8527 new_quads[i] =
8528 triangulation.faces->quads
8529 .template next_free_single_object<2>(triangulation);
8530
8531 AssertIsNotUsed(new_quads[i]);
8532 new_quads[i]->set_used_flag();
8533 new_quads[i]->clear_user_flag();
8534 new_quads[i]->clear_user_data();
8535 new_quads[i]->clear_children();
8536 // interior quad
8537 new_quads[i]->set_boundary_id_internal(
8539 // they inherit geometry description of the hex they
8540 // belong to
8541 new_quads[i]->set_manifold_id(hex->manifold_id());
8542 // set all line orientation flags to true by
8543 // default, change this afterwards, if necessary
8544 for (unsigned int j = 0;
8545 j < GeometryInfo<dim>::lines_per_face;
8546 ++j)
8547 new_quads[i]->set_line_orientation(j, true);
8548 }
8549
8550 types::subdomain_id subdomainid = hex->subdomain_id();
8551
8552 // find some space for the newly to be created hexes
8553 // and initialize them.
8554 std::vector<
8556 new_hexes(n_new_hexes);
8557 for (unsigned int i = 0; i < n_new_hexes; ++i)
8558 {
8559 if (i % 2 == 0)
8560 next_unused_hex =
8561 triangulation.levels[level + 1]->cells.next_free_hex(
8562 triangulation, level + 1);
8563 else
8564 ++next_unused_hex;
8565
8566 new_hexes[i] = next_unused_hex;
8567
8568 AssertIsNotUsed(new_hexes[i]);
8569 new_hexes[i]->set_used_flag();
8570 new_hexes[i]->clear_user_flag();
8571 new_hexes[i]->clear_user_data();
8572 new_hexes[i]->clear_children();
8573 // inherit material
8574 // properties
8575 new_hexes[i]->set_material_id(hex->material_id());
8576 new_hexes[i]->set_manifold_id(hex->manifold_id());
8577 new_hexes[i]->set_subdomain_id(subdomainid);
8578
8579 if (i % 2)
8580 new_hexes[i]->set_parent(hex->index());
8581 // set the face_orientation flag to true for all
8582 // faces initially, as this is the default value
8583 // which is true for all faces interior to the
8584 // hex. later on go the other way round and
8585 // reset faces that are at the boundary of the
8586 // mother cube
8587 //
8588 // the same is true for the face_flip and
8589 // face_rotation flags. however, the latter two
8590 // are set to false by default as this is the
8591 // standard value
8592 for (const unsigned int f :
8594 new_hexes[i]->set_combined_face_orientation(
8595 f,
8597 }
8598 // note these hexes as children to the present cell
8599 for (unsigned int i = 0; i < n_new_hexes / 2; ++i)
8600 hex->set_children(2 * i, new_hexes[2 * i]->index());
8601
8602 // we have to take into account whether the
8603 // different faces are oriented correctly or in the
8604 // opposite direction, so store that up front
8605
8606 // face_orientation
8607 const bool f_or[6] = {hex->face_orientation(0),
8608 hex->face_orientation(1),
8609 hex->face_orientation(2),
8610 hex->face_orientation(3),
8611 hex->face_orientation(4),
8612 hex->face_orientation(5)};
8613
8614 // face_flip
8615 const bool f_fl[6] = {hex->face_flip(0),
8616 hex->face_flip(1),
8617 hex->face_flip(2),
8618 hex->face_flip(3),
8619 hex->face_flip(4),
8620 hex->face_flip(5)};
8621
8622 // face_rotation
8623 const bool f_ro[6] = {hex->face_rotation(0),
8624 hex->face_rotation(1),
8625 hex->face_rotation(2),
8626 hex->face_rotation(3),
8627 hex->face_rotation(4),
8628 hex->face_rotation(5)};
8629
8630 // combined orientation
8631 const unsigned char f_co[6] = {
8632 hex->combined_face_orientation(0),
8633 hex->combined_face_orientation(1),
8634 hex->combined_face_orientation(2),
8635 hex->combined_face_orientation(3),
8636 hex->combined_face_orientation(4),
8637 hex->combined_face_orientation(5)};
8638
8639 // little helper table, indicating, whether the
8640 // child with index 0 or with index 1 can be found
8641 // at the standard origin of an anisotropically
8642 // refined quads in real orientation index 1:
8643 // (RefineCase - 1) index 2: face_flip
8644
8645 // index 3: face rotation
8646 // note: face orientation has no influence
8647 const unsigned int child_at_origin[2][2][2] = {
8648 {{0, 0}, // RefinementCase<dim>::cut_x, face_flip=false,
8649 // face_rotation=false and true
8650 {1, 1}}, // RefinementCase<dim>::cut_x, face_flip=true,
8651 // face_rotation=false and true
8652 {{0, 1}, // RefinementCase<dim>::cut_y, face_flip=false,
8653 // face_rotation=false and true
8654 {1, 0}}}; // RefinementCase<dim>::cut_y, face_flip=true,
8655 // face_rotation=false and true
8656
8657 //-------------------------------------
8658 //
8659 // in the following we will do the same thing for
8660 // each refinement case: create a new vertex (if
8661 // needed), create new interior lines (if needed),
8662 // create new interior quads and afterwards build
8663 // the children hexes out of these and the existing
8664 // subfaces of the outer quads (which have been
8665 // created above). However, even if the steps are
8666 // quite similar, the actual work strongly depends
8667 // on the actual refinement case. therefore, we use
8668 // separate blocks of code for each of these cases,
8669 // which hopefully increases the readability to some
8670 // extend.
8671
8672 switch (ref_case)
8673 {
8675 {
8676 //----------------------------
8677 //
8678 // RefinementCase<dim>::cut_x
8679 //
8680 // the refined cube will look
8681 // like this:
8682 //
8683 // *----*----*
8684 // / / /|
8685 // / / / |
8686 // / / / |
8687 // *----*----* |
8688 // | | | |
8689 // | | | *
8690 // | | | /
8691 // | | | /
8692 // | | |/
8693 // *----*----*
8694 //
8695 // again, first collect some data about the
8696 // indices of the lines, with the following
8697 // numbering:
8698
8699 // face 2: front plane
8700 // (note: x,y exchanged)
8701 // *---*---*
8702 // | | |
8703 // | 0 |
8704 // | | |
8705 // *---*---*
8706 // m0
8707 // face 3: back plane
8708 // (note: x,y exchanged)
8709 // m1
8710 // *---*---*
8711 // | | |
8712 // | 1 |
8713 // | | |
8714 // *---*---*
8715 // face 4: bottom plane
8716 // *---*---*
8717 // / / /
8718 // / 2 /
8719 // / / /
8720 // *---*---*
8721 // m0
8722 // face 5: top plane
8723 // m1
8724 // *---*---*
8725 // / / /
8726 // / 3 /
8727 // / / /
8728 // *---*---*
8729
8730 // set up a list of line iterators first. from
8731 // this, construct lists of line_indices and
8732 // line orientations later on
8733 const typename Triangulation<dim, spacedim>::
8734 raw_line_iterator lines[4] = {
8735 hex->face(2)->child(0)->line(
8736 (hex->face(2)->refinement_case() ==
8738 1 :
8739 3), // 0
8740 hex->face(3)->child(0)->line(
8741 (hex->face(3)->refinement_case() ==
8743 1 :
8744 3), // 1
8745 hex->face(4)->child(0)->line(
8746 (hex->face(4)->refinement_case() ==
8748 1 :
8749 3), // 2
8750 hex->face(5)->child(0)->line(
8751 (hex->face(5)->refinement_case() ==
8753 1 :
8754 3) // 3
8755 };
8756
8757 unsigned int line_indices[4];
8758 for (unsigned int i = 0; i < 4; ++i)
8759 line_indices[i] = lines[i]->index();
8760
8761 // the orientation of lines for the inner quads
8762 // is quite tricky. as these lines are newly
8763 // created ones and thus have no parents, they
8764 // cannot inherit this property. set up an array
8765 // and fill it with the respective values
8766 bool line_orientation[4];
8767
8768 // the middle vertex marked as m0 above is the
8769 // start vertex for lines 0 and 2 in standard
8770 // orientation, whereas m1 is the end vertex of
8771 // lines 1 and 3 in standard orientation
8772 const unsigned int middle_vertices[2] = {
8773 hex->line(2)->child(0)->vertex_index(1),
8774 hex->line(7)->child(0)->vertex_index(1)};
8775
8776 for (unsigned int i = 0; i < 4; ++i)
8777 if (lines[i]->vertex_index(i % 2) ==
8778 middle_vertices[i % 2])
8779 line_orientation[i] = true;
8780 else
8781 {
8782 // it must be the other
8783 // way round then
8784 Assert(lines[i]->vertex_index((i + 1) % 2) ==
8785 middle_vertices[i % 2],
8787 line_orientation[i] = false;
8788 }
8789
8790 // set up the new quad, line numbering is as
8791 // indicated above
8792 new_quads[0]->set_bounding_object_indices(
8793 {line_indices[0],
8794 line_indices[1],
8795 line_indices[2],
8796 line_indices[3]});
8797
8798 new_quads[0]->set_line_orientation(
8799 0, line_orientation[0]);
8800 new_quads[0]->set_line_orientation(
8801 1, line_orientation[1]);
8802 new_quads[0]->set_line_orientation(
8803 2, line_orientation[2]);
8804 new_quads[0]->set_line_orientation(
8805 3, line_orientation[3]);
8806
8807 // the quads are numbered as follows:
8808 //
8809 // planes in the interior of the old hex:
8810 //
8811 // *
8812 // /|
8813 // / | x
8814 // / | *-------* *---------*
8815 // * | | | / /
8816 // | 0 | | | / /
8817 // | * | | / /
8818 // | / *-------*y *---------*x
8819 // | /
8820 // |/
8821 // *
8822 //
8823 // children of the faces of the old hex
8824 //
8825 // *---*---* *---*---*
8826 // /| | | / / /|
8827 // / | | | / 9 / 10/ |
8828 // / | 5 | 6 | / / / |
8829 // * | | | *---*---* |
8830 // | 1 *---*---* | | | 2 *
8831 // | / / / | | | /
8832 // | / 7 / 8 / | 3 | 4 | /
8833 // |/ / / | | |/
8834 // *---*---* *---*---*
8835 //
8836 // note that we have to take care of the
8837 // orientation of faces.
8838 const int quad_indices[11] = {
8839 new_quads[0]->index(), // 0
8840
8841 hex->face(0)->index(), // 1
8842
8843 hex->face(1)->index(), // 2
8844
8845 hex->face(2)->child_index(
8846 child_at_origin[hex->face(2)->refinement_case() -
8847 1][f_fl[2]][f_ro[2]]), // 3
8848 hex->face(2)->child_index(
8849 1 -
8850 child_at_origin[hex->face(2)->refinement_case() -
8851 1][f_fl[2]][f_ro[2]]),
8852
8853 hex->face(3)->child_index(
8854 child_at_origin[hex->face(3)->refinement_case() -
8855 1][f_fl[3]][f_ro[3]]), // 5
8856 hex->face(3)->child_index(
8857 1 -
8858 child_at_origin[hex->face(3)->refinement_case() -
8859 1][f_fl[3]][f_ro[3]]),
8860
8861 hex->face(4)->child_index(
8862 child_at_origin[hex->face(4)->refinement_case() -
8863 1][f_fl[4]][f_ro[4]]), // 7
8864 hex->face(4)->child_index(
8865 1 -
8866 child_at_origin[hex->face(4)->refinement_case() -
8867 1][f_fl[4]][f_ro[4]]),
8868
8869 hex->face(5)->child_index(
8870 child_at_origin[hex->face(5)->refinement_case() -
8871 1][f_fl[5]][f_ro[5]]), // 9
8872 hex->face(5)->child_index(
8873 1 -
8874 child_at_origin[hex->face(5)->refinement_case() -
8875 1][f_fl[5]][f_ro[5]])
8876
8877 };
8878
8879 new_hexes[0]->set_bounding_object_indices(
8880 {quad_indices[1],
8881 quad_indices[0],
8882 quad_indices[3],
8883 quad_indices[5],
8884 quad_indices[7],
8885 quad_indices[9]});
8886 new_hexes[1]->set_bounding_object_indices(
8887 {quad_indices[0],
8888 quad_indices[2],
8889 quad_indices[4],
8890 quad_indices[6],
8891 quad_indices[8],
8892 quad_indices[10]});
8893 break;
8894 }
8895
8897 {
8898 //----------------------------
8899 //
8900 // RefinementCase<dim>::cut_y
8901 //
8902 // the refined cube will look like this:
8903 //
8904 // *---------*
8905 // / /|
8906 // *---------* |
8907 // / /| |
8908 // *---------* | |
8909 // | | | |
8910 // | | | *
8911 // | | |/
8912 // | | *
8913 // | |/
8914 // *---------*
8915 //
8916 // again, first collect some data about the
8917 // indices of the lines, with the following
8918 // numbering:
8919
8920 // face 0: left plane
8921 // *
8922 // /|
8923 // * |
8924 // /| |
8925 // * | |
8926 // | 0 |
8927 // | | *
8928 // | |/
8929 // | *m0
8930 // |/
8931 // *
8932 // face 1: right plane
8933 // *
8934 // /|
8935 // m1* |
8936 // /| |
8937 // * | |
8938 // | 1 |
8939 // | | *
8940 // | |/
8941 // | *
8942 // |/
8943 // *
8944 // face 4: bottom plane
8945 // *-------*
8946 // / /
8947 // m0*---2---*
8948 // / /
8949 // *-------*
8950 // face 5: top plane
8951 // *-------*
8952 // / /
8953 // *---3---*m1
8954 // / /
8955 // *-------*
8956
8957 // set up a list of line iterators first. from
8958 // this, construct lists of line_indices and
8959 // line orientations later on
8960 const typename Triangulation<dim, spacedim>::
8961 raw_line_iterator lines[4] = {
8962 hex->face(0)->child(0)->line(
8963 (hex->face(0)->refinement_case() ==
8965 1 :
8966 3), // 0
8967 hex->face(1)->child(0)->line(
8968 (hex->face(1)->refinement_case() ==
8970 1 :
8971 3), // 1
8972 hex->face(4)->child(0)->line(
8973 (hex->face(4)->refinement_case() ==
8975 1 :
8976 3), // 2
8977 hex->face(5)->child(0)->line(
8978 (hex->face(5)->refinement_case() ==
8980 1 :
8981 3) // 3
8982 };
8983
8984 unsigned int line_indices[4];
8985 for (unsigned int i = 0; i < 4; ++i)
8986 line_indices[i] = lines[i]->index();
8987
8988 // the orientation of lines for the inner quads
8989 // is quite tricky. as these lines are newly
8990 // created ones and thus have no parents, they
8991 // cannot inherit this property. set up an array
8992 // and fill it with the respective values
8993 bool line_orientation[4];
8994
8995 // the middle vertex marked as m0 above is the
8996 // start vertex for lines 0 and 2 in standard
8997 // orientation, whereas m1 is the end vertex of
8998 // lines 1 and 3 in standard orientation
8999 const unsigned int middle_vertices[2] = {
9000 hex->line(0)->child(0)->vertex_index(1),
9001 hex->line(5)->child(0)->vertex_index(1)};
9002
9003 for (unsigned int i = 0; i < 4; ++i)
9004 if (lines[i]->vertex_index(i % 2) ==
9005 middle_vertices[i % 2])
9006 line_orientation[i] = true;
9007 else
9008 {
9009 // it must be the other way round then
9010 Assert(lines[i]->vertex_index((i + 1) % 2) ==
9011 middle_vertices[i % 2],
9013 line_orientation[i] = false;
9014 }
9015
9016 // set up the new quad, line numbering is as
9017 // indicated above
9018 new_quads[0]->set_bounding_object_indices(
9019 {line_indices[2],
9020 line_indices[3],
9021 line_indices[0],
9022 line_indices[1]});
9023
9024 new_quads[0]->set_line_orientation(
9025 0, line_orientation[2]);
9026 new_quads[0]->set_line_orientation(
9027 1, line_orientation[3]);
9028 new_quads[0]->set_line_orientation(
9029 2, line_orientation[0]);
9030 new_quads[0]->set_line_orientation(
9031 3, line_orientation[1]);
9032
9033 // the quads are numbered as follows:
9034 //
9035 // planes in the interior of the old hex:
9036 //
9037 // *
9038 // /|
9039 // / | x
9040 // / | *-------* *---------*
9041 // * | | | / /
9042 // | | | 0 | / /
9043 // | * | | / /
9044 // | / *-------*y *---------*x
9045 // | /
9046 // |/
9047 // *
9048 //
9049 // children of the faces of the old hex
9050 //
9051 // *-------* *-------*
9052 // /| | / 10 /|
9053 // * | | *-------* |
9054 // /| | 6 | / 9 /| |
9055 // * |2| | *-------* |4|
9056 // | | *-------* | | | *
9057 // |1|/ 8 / | |3|/
9058 // | *-------* | 5 | *
9059 // |/ 7 / | |/
9060 // *-------* *-------*
9061 //
9062 // note that we have to take care of the
9063 // orientation of faces.
9064 const int quad_indices[11] = {
9065 new_quads[0]->index(), // 0
9066
9067 hex->face(0)->child_index(
9068 child_at_origin[hex->face(0)->refinement_case() -
9069 1][f_fl[0]][f_ro[0]]), // 1
9070 hex->face(0)->child_index(
9071 1 -
9072 child_at_origin[hex->face(0)->refinement_case() -
9073 1][f_fl[0]][f_ro[0]]),
9074
9075 hex->face(1)->child_index(
9076 child_at_origin[hex->face(1)->refinement_case() -
9077 1][f_fl[1]][f_ro[1]]), // 3
9078 hex->face(1)->child_index(
9079 1 -
9080 child_at_origin[hex->face(1)->refinement_case() -
9081 1][f_fl[1]][f_ro[1]]),
9082
9083 hex->face(2)->index(), // 5
9084
9085 hex->face(3)->index(), // 6
9086
9087 hex->face(4)->child_index(
9088 child_at_origin[hex->face(4)->refinement_case() -
9089 1][f_fl[4]][f_ro[4]]), // 7
9090 hex->face(4)->child_index(
9091 1 -
9092 child_at_origin[hex->face(4)->refinement_case() -
9093 1][f_fl[4]][f_ro[4]]),
9094
9095 hex->face(5)->child_index(
9096 child_at_origin[hex->face(5)->refinement_case() -
9097 1][f_fl[5]][f_ro[5]]), // 9
9098 hex->face(5)->child_index(
9099 1 -
9100 child_at_origin[hex->face(5)->refinement_case() -
9101 1][f_fl[5]][f_ro[5]])
9102
9103 };
9104
9105 new_hexes[0]->set_bounding_object_indices(
9106 {quad_indices[1],
9107 quad_indices[3],
9108 quad_indices[5],
9109 quad_indices[0],
9110 quad_indices[7],
9111 quad_indices[9]});
9112 new_hexes[1]->set_bounding_object_indices(
9113 {quad_indices[2],
9114 quad_indices[4],
9115 quad_indices[0],
9116 quad_indices[6],
9117 quad_indices[8],
9118 quad_indices[10]});
9119 break;
9120 }
9121
9123 {
9124 //----------------------------
9125 //
9126 // RefinementCase<dim>::cut_z
9127 //
9128 // the refined cube will look like this:
9129 //
9130 // *---------*
9131 // / /|
9132 // / / |
9133 // / / *
9134 // *---------* /|
9135 // | | / |
9136 // | |/ *
9137 // *---------* /
9138 // | | /
9139 // | |/
9140 // *---------*
9141 //
9142 // again, first collect some data about the
9143 // indices of the lines, with the following
9144 // numbering:
9145
9146 // face 0: left plane
9147 // *
9148 // /|
9149 // / |
9150 // / *
9151 // * /|
9152 // | 0 |
9153 // |/ *
9154 // m0* /
9155 // | /
9156 // |/
9157 // *
9158 // face 1: right plane
9159 // *
9160 // /|
9161 // / |
9162 // / *m1
9163 // * /|
9164 // | 1 |
9165 // |/ *
9166 // * /
9167 // | /
9168 // |/
9169 // *
9170 // face 2: front plane
9171 // (note: x,y exchanged)
9172 // *-------*
9173 // | |
9174 // m0*---2---*
9175 // | |
9176 // *-------*
9177 // face 3: back plane
9178 // (note: x,y exchanged)
9179 // *-------*
9180 // | |
9181 // *---3---*m1
9182 // | |
9183 // *-------*
9184
9185 // set up a list of line iterators first. from
9186 // this, construct lists of line_indices and
9187 // line orientations later on
9188 const typename Triangulation<dim, spacedim>::
9189 raw_line_iterator lines[4] = {
9190 hex->face(0)->child(0)->line(
9191 (hex->face(0)->refinement_case() ==
9193 1 :
9194 3), // 0
9195 hex->face(1)->child(0)->line(
9196 (hex->face(1)->refinement_case() ==
9198 1 :
9199 3), // 1
9200 hex->face(2)->child(0)->line(
9201 (hex->face(2)->refinement_case() ==
9203 1 :
9204 3), // 2
9205 hex->face(3)->child(0)->line(
9206 (hex->face(3)->refinement_case() ==
9208 1 :
9209 3) // 3
9210 };
9211
9212 unsigned int line_indices[4];
9213 for (unsigned int i = 0; i < 4; ++i)
9214 line_indices[i] = lines[i]->index();
9215
9216 // the orientation of lines for the inner quads
9217 // is quite tricky. as these lines are newly
9218 // created ones and thus have no parents, they
9219 // cannot inherit this property. set up an array
9220 // and fill it with the respective values
9221 bool line_orientation[4];
9222
9223 // the middle vertex marked as m0 above is the
9224 // start vertex for lines 0 and 2 in standard
9225 // orientation, whereas m1 is the end vertex of
9226 // lines 1 and 3 in standard orientation
9227 const unsigned int middle_vertices[2] = {
9228 middle_vertex_index<dim, spacedim>(hex->line(8)),
9229 middle_vertex_index<dim, spacedim>(hex->line(11))};
9230
9231 for (unsigned int i = 0; i < 4; ++i)
9232 if (lines[i]->vertex_index(i % 2) ==
9233 middle_vertices[i % 2])
9234 line_orientation[i] = true;
9235 else
9236 {
9237 // it must be the other way round then
9238 Assert(lines[i]->vertex_index((i + 1) % 2) ==
9239 middle_vertices[i % 2],
9241 line_orientation[i] = false;
9242 }
9243
9244 // set up the new quad, line numbering is as
9245 // indicated above
9246 new_quads[0]->set_bounding_object_indices(
9247 {line_indices[0],
9248 line_indices[1],
9249 line_indices[2],
9250 line_indices[3]});
9251
9252 new_quads[0]->set_line_orientation(
9253 0, line_orientation[0]);
9254 new_quads[0]->set_line_orientation(
9255 1, line_orientation[1]);
9256 new_quads[0]->set_line_orientation(
9257 2, line_orientation[2]);
9258 new_quads[0]->set_line_orientation(
9259 3, line_orientation[3]);
9260
9261 // the quads are numbered as follows:
9262 //
9263 // planes in the interior of the old hex:
9264 //
9265 // *
9266 // /|
9267 // / | x
9268 // / | *-------* *---------*
9269 // * | | | / /
9270 // | | | | / 0 /
9271 // | * | | / /
9272 // | / *-------*y *---------*x
9273 // | /
9274 // |/
9275 // *
9276 //
9277 // children of the faces of the old hex
9278 //
9279 // *---*---* *-------*
9280 // /| 8 | / /|
9281 // / | | / 10 / |
9282 // / *-------* / / *
9283 // * 2/| | *-------* 4/|
9284 // | / | 7 | | 6 | / |
9285 // |/1 *-------* | |/3 *
9286 // * / / *-------* /
9287 // | / 9 / | | /
9288 // |/ / | 5 |/
9289 // *-------* *---*---*
9290 //
9291 // note that we have to take care of the
9292 // orientation of faces.
9293 const int quad_indices[11] = {
9294 new_quads[0]->index(), // 0
9295
9296 hex->face(0)->child_index(
9297 child_at_origin[hex->face(0)->refinement_case() -
9298 1][f_fl[0]][f_ro[0]]), // 1
9299 hex->face(0)->child_index(
9300 1 -
9301 child_at_origin[hex->face(0)->refinement_case() -
9302 1][f_fl[0]][f_ro[0]]),
9303
9304 hex->face(1)->child_index(
9305 child_at_origin[hex->face(1)->refinement_case() -
9306 1][f_fl[1]][f_ro[1]]), // 3
9307 hex->face(1)->child_index(
9308 1 -
9309 child_at_origin[hex->face(1)->refinement_case() -
9310 1][f_fl[1]][f_ro[1]]),
9311
9312 hex->face(2)->child_index(
9313 child_at_origin[hex->face(2)->refinement_case() -
9314 1][f_fl[2]][f_ro[2]]), // 5
9315 hex->face(2)->child_index(
9316 1 -
9317 child_at_origin[hex->face(2)->refinement_case() -
9318 1][f_fl[2]][f_ro[2]]),
9319
9320 hex->face(3)->child_index(
9321 child_at_origin[hex->face(3)->refinement_case() -
9322 1][f_fl[3]][f_ro[3]]), // 7
9323 hex->face(3)->child_index(
9324 1 -
9325 child_at_origin[hex->face(3)->refinement_case() -
9326 1][f_fl[3]][f_ro[3]]),
9327
9328 hex->face(4)->index(), // 9
9329
9330 hex->face(5)->index() // 10
9331 };
9332
9333 new_hexes[0]->set_bounding_object_indices(
9334 {quad_indices[1],
9335 quad_indices[3],
9336 quad_indices[5],
9337 quad_indices[7],
9338 quad_indices[9],
9339 quad_indices[0]});
9340 new_hexes[1]->set_bounding_object_indices(
9341 {quad_indices[2],
9342 quad_indices[4],
9343 quad_indices[6],
9344 quad_indices[8],
9345 quad_indices[0],
9346 quad_indices[10]});
9347 break;
9348 }
9349
9351 {
9352 //----------------------------
9353 //
9354 // RefinementCase<dim>::cut_xy
9355 //
9356 // the refined cube will look like this:
9357 //
9358 // *----*----*
9359 // / / /|
9360 // *----*----* |
9361 // / / /| |
9362 // *----*----* | |
9363 // | | | | |
9364 // | | | | *
9365 // | | | |/
9366 // | | | *
9367 // | | |/
9368 // *----*----*
9369 //
9370
9371 // first, create the new internal line
9372 new_lines[0]->set_bounding_object_indices(
9373 {middle_vertex_index<dim, spacedim>(hex->face(4)),
9374 middle_vertex_index<dim, spacedim>(hex->face(5))});
9375
9376 // again, first collect some data about the
9377 // indices of the lines, with the following
9378 // numbering:
9379
9380 // face 0: left plane
9381 // *
9382 // /|
9383 // * |
9384 // /| |
9385 // * | |
9386 // | 0 |
9387 // | | *
9388 // | |/
9389 // | *
9390 // |/
9391 // *
9392 // face 1: right plane
9393 // *
9394 // /|
9395 // * |
9396 // /| |
9397 // * | |
9398 // | 1 |
9399 // | | *
9400 // | |/
9401 // | *
9402 // |/
9403 // *
9404 // face 2: front plane
9405 // (note: x,y exchanged)
9406 // *---*---*
9407 // | | |
9408 // | 2 |
9409 // | | |
9410 // *-------*
9411 // face 3: back plane
9412 // (note: x,y exchanged)
9413 // *---*---*
9414 // | | |
9415 // | 3 |
9416 // | | |
9417 // *---*---*
9418 // face 4: bottom plane
9419 // *---*---*
9420 // / 5 /
9421 // *-6-*-7-*
9422 // / 4 /
9423 // *---*---*
9424 // face 5: top plane
9425 // *---*---*
9426 // / 9 /
9427 // *10-*-11*
9428 // / 8 /
9429 // *---*---*
9430 // middle planes
9431 // *-------* *---*---*
9432 // / / | | |
9433 // / / | 12 |
9434 // / / | | |
9435 // *-------* *---*---*
9436
9437 // set up a list of line iterators first. from
9438 // this, construct lists of line_indices and
9439 // line orientations later on
9440 const typename Triangulation<
9441 dim,
9442 spacedim>::raw_line_iterator lines[13] = {
9443 hex->face(0)->child(0)->line(
9444 (hex->face(0)->refinement_case() ==
9446 1 :
9447 3), // 0
9448 hex->face(1)->child(0)->line(
9449 (hex->face(1)->refinement_case() ==
9451 1 :
9452 3), // 1
9453 hex->face(2)->child(0)->line(
9454 (hex->face(2)->refinement_case() ==
9456 1 :
9457 3), // 2
9458 hex->face(3)->child(0)->line(
9459 (hex->face(3)->refinement_case() ==
9461 1 :
9462 3), // 3
9463
9464 hex->face(4)
9465 ->isotropic_child(
9467 0, f_or[4], f_fl[4], f_ro[4]))
9468 ->line(
9470 1, f_or[4], f_fl[4], f_ro[4])), // 4
9471 hex->face(4)
9472 ->isotropic_child(
9474 3, f_or[4], f_fl[4], f_ro[4]))
9475 ->line(
9477 0, f_or[4], f_fl[4], f_ro[4])), // 5
9478 hex->face(4)
9479 ->isotropic_child(
9481 0, f_or[4], f_fl[4], f_ro[4]))
9482 ->line(
9484 3, f_or[4], f_fl[4], f_ro[4])), // 6
9485 hex->face(4)
9486 ->isotropic_child(
9488 3, f_or[4], f_fl[4], f_ro[4]))
9489 ->line(
9491 2, f_or[4], f_fl[4], f_ro[4])), // 7
9492
9493 hex->face(5)
9494 ->isotropic_child(
9496 0, f_or[5], f_fl[5], f_ro[5]))
9497 ->line(
9499 1, f_or[5], f_fl[5], f_ro[5])), // 8
9500 hex->face(5)
9501 ->isotropic_child(
9503 3, f_or[5], f_fl[5], f_ro[5]))
9504 ->line(
9506 0, f_or[5], f_fl[5], f_ro[5])), // 9
9507 hex->face(5)
9508 ->isotropic_child(
9510 0, f_or[5], f_fl[5], f_ro[5]))
9511 ->line(
9513 3, f_or[5], f_fl[5], f_ro[5])), // 10
9514 hex->face(5)
9515 ->isotropic_child(
9517 3, f_or[5], f_fl[5], f_ro[5]))
9518 ->line(
9520 2, f_or[5], f_fl[5], f_ro[5])), // 11
9521
9522 new_lines[0] // 12
9523 };
9524
9525 unsigned int line_indices[13];
9526 for (unsigned int i = 0; i < 13; ++i)
9527 line_indices[i] = lines[i]->index();
9528
9529 // the orientation of lines for the inner quads
9530 // is quite tricky. as these lines are newly
9531 // created ones and thus have no parents, they
9532 // cannot inherit this property. set up an array
9533 // and fill it with the respective values
9534 bool line_orientation[13];
9535
9536 // the middle vertices of the lines of our
9537 // bottom face
9538 const unsigned int middle_vertices[4] = {
9539 hex->line(0)->child(0)->vertex_index(1),
9540 hex->line(1)->child(0)->vertex_index(1),
9541 hex->line(2)->child(0)->vertex_index(1),
9542 hex->line(3)->child(0)->vertex_index(1),
9543 };
9544
9545 // note: for lines 0 to 3 the orientation of the
9546 // line is 'true', if vertex 0 is on the bottom
9547 // face
9548 for (unsigned int i = 0; i < 4; ++i)
9549 if (lines[i]->vertex_index(0) == middle_vertices[i])
9550 line_orientation[i] = true;
9551 else
9552 {
9553 // it must be the other way round then
9554 Assert(lines[i]->vertex_index(1) ==
9555 middle_vertices[i],
9557 line_orientation[i] = false;
9558 }
9559
9560 // note: for lines 4 to 11 (inner lines of the
9561 // outer quads) the following holds: the second
9562 // vertex of the even lines in standard
9563 // orientation is the vertex in the middle of
9564 // the quad, whereas for odd lines the first
9565 // vertex is the same middle vertex.
9566 for (unsigned int i = 4; i < 12; ++i)
9567 if (lines[i]->vertex_index((i + 1) % 2) ==
9568 middle_vertex_index<dim, spacedim>(
9569 hex->face(3 + i / 4)))
9570 line_orientation[i] = true;
9571 else
9572 {
9573 // it must be the other way
9574 // round then
9575 Assert(lines[i]->vertex_index(i % 2) ==
9576 (middle_vertex_index<dim, spacedim>(
9577 hex->face(3 + i / 4))),
9579 line_orientation[i] = false;
9580 }
9581 // for the last line the line orientation is
9582 // always true, since it was just constructed
9583 // that way
9584 line_orientation[12] = true;
9585
9586 // set up the 4 quads, numbered as follows (left
9587 // quad numbering, right line numbering
9588 // extracted from above)
9589 //
9590 // * *
9591 // /| 9|
9592 // * | * |
9593 // y/| | 8| 3
9594 // * |1| * | |
9595 // | | |x | 12|
9596 // |0| * | | *
9597 // | |/ 2 |5
9598 // | * | *
9599 // |/ |4
9600 // * *
9601 //
9602 // x
9603 // *---*---* *10-*-11*
9604 // | | | | | |
9605 // | 2 | 3 | 0 12 1
9606 // | | | | | |
9607 // *---*---*y *-6-*-7-*
9608
9609 new_quads[0]->set_bounding_object_indices(
9610 {line_indices[2],
9611 line_indices[12],
9612 line_indices[4],
9613 line_indices[8]});
9614 new_quads[1]->set_bounding_object_indices(
9615 {line_indices[12],
9616 line_indices[3],
9617 line_indices[5],
9618 line_indices[9]});
9619 new_quads[2]->set_bounding_object_indices(
9620 {line_indices[6],
9621 line_indices[10],
9622 line_indices[0],
9623 line_indices[12]});
9624 new_quads[3]->set_bounding_object_indices(
9625 {line_indices[7],
9626 line_indices[11],
9627 line_indices[12],
9628 line_indices[1]});
9629
9630 new_quads[0]->set_line_orientation(
9631 0, line_orientation[2]);
9632 new_quads[0]->set_line_orientation(
9633 2, line_orientation[4]);
9634 new_quads[0]->set_line_orientation(
9635 3, line_orientation[8]);
9636
9637 new_quads[1]->set_line_orientation(
9638 1, line_orientation[3]);
9639 new_quads[1]->set_line_orientation(
9640 2, line_orientation[5]);
9641 new_quads[1]->set_line_orientation(
9642 3, line_orientation[9]);
9643
9644 new_quads[2]->set_line_orientation(
9645 0, line_orientation[6]);
9646 new_quads[2]->set_line_orientation(
9647 1, line_orientation[10]);
9648 new_quads[2]->set_line_orientation(
9649 2, line_orientation[0]);
9650
9651 new_quads[3]->set_line_orientation(
9652 0, line_orientation[7]);
9653 new_quads[3]->set_line_orientation(
9654 1, line_orientation[11]);
9655 new_quads[3]->set_line_orientation(
9656 3, line_orientation[1]);
9657
9658 // the quads are numbered as follows:
9659 //
9660 // planes in the interior of the old hex:
9661 //
9662 // *
9663 // /|
9664 // * | x
9665 // /| | *---*---* *---------*
9666 // * |1| | | | / /
9667 // | | | | 2 | 3 | / /
9668 // |0| * | | | / /
9669 // | |/ *---*---*y *---------*x
9670 // | *
9671 // |/
9672 // *
9673 //
9674 // children of the faces of the old hex
9675 //
9676 // *---*---* *---*---*
9677 // /| | | /18 / 19/|
9678 // * |10 | 11| /---/---* |
9679 // /| | | | /16 / 17/| |
9680 // * |5| | | *---*---* |7|
9681 // | | *---*---* | | | | *
9682 // |4|/14 / 15/ | | |6|/
9683 // | *---/---/ | 8 | 9 | *
9684 // |/12 / 13/ | | |/
9685 // *---*---* *---*---*
9686 //
9687 // note that we have to take care of the
9688 // orientation of faces.
9689 const int quad_indices[20] = {
9690 new_quads[0]->index(), // 0
9691 new_quads[1]->index(),
9692 new_quads[2]->index(),
9693 new_quads[3]->index(),
9694
9695 hex->face(0)->child_index(
9696 child_at_origin[hex->face(0)->refinement_case() -
9697 1][f_fl[0]][f_ro[0]]), // 4
9698 hex->face(0)->child_index(
9699 1 -
9700 child_at_origin[hex->face(0)->refinement_case() -
9701 1][f_fl[0]][f_ro[0]]),
9702
9703 hex->face(1)->child_index(
9704 child_at_origin[hex->face(1)->refinement_case() -
9705 1][f_fl[1]][f_ro[1]]), // 6
9706 hex->face(1)->child_index(
9707 1 -
9708 child_at_origin[hex->face(1)->refinement_case() -
9709 1][f_fl[1]][f_ro[1]]),
9710
9711 hex->face(2)->child_index(
9712 child_at_origin[hex->face(2)->refinement_case() -
9713 1][f_fl[2]][f_ro[2]]), // 8
9714 hex->face(2)->child_index(
9715 1 -
9716 child_at_origin[hex->face(2)->refinement_case() -
9717 1][f_fl[2]][f_ro[2]]),
9718
9719 hex->face(3)->child_index(
9720 child_at_origin[hex->face(3)->refinement_case() -
9721 1][f_fl[3]][f_ro[3]]), // 10
9722 hex->face(3)->child_index(
9723 1 -
9724 child_at_origin[hex->face(3)->refinement_case() -
9725 1][f_fl[3]][f_ro[3]]),
9726
9727 hex->face(4)->isotropic_child_index(
9729 0, f_or[4], f_fl[4], f_ro[4])), // 12
9730 hex->face(4)->isotropic_child_index(
9732 1, f_or[4], f_fl[4], f_ro[4])),
9733 hex->face(4)->isotropic_child_index(
9735 2, f_or[4], f_fl[4], f_ro[4])),
9736 hex->face(4)->isotropic_child_index(
9738 3, f_or[4], f_fl[4], f_ro[4])),
9739
9740 hex->face(5)->isotropic_child_index(
9742 0, f_or[5], f_fl[5], f_ro[5])), // 16
9743 hex->face(5)->isotropic_child_index(
9745 1, f_or[5], f_fl[5], f_ro[5])),
9746 hex->face(5)->isotropic_child_index(
9748 2, f_or[5], f_fl[5], f_ro[5])),
9749 hex->face(5)->isotropic_child_index(
9751 3, f_or[5], f_fl[5], f_ro[5]))};
9752
9753 new_hexes[0]->set_bounding_object_indices(
9754 {quad_indices[4],
9755 quad_indices[0],
9756 quad_indices[8],
9757 quad_indices[2],
9758 quad_indices[12],
9759 quad_indices[16]});
9760 new_hexes[1]->set_bounding_object_indices(
9761 {quad_indices[0],
9762 quad_indices[6],
9763 quad_indices[9],
9764 quad_indices[3],
9765 quad_indices[13],
9766 quad_indices[17]});
9767 new_hexes[2]->set_bounding_object_indices(
9768 {quad_indices[5],
9769 quad_indices[1],
9770 quad_indices[2],
9771 quad_indices[10],
9772 quad_indices[14],
9773 quad_indices[18]});
9774 new_hexes[3]->set_bounding_object_indices(
9775 {quad_indices[1],
9776 quad_indices[7],
9777 quad_indices[3],
9778 quad_indices[11],
9779 quad_indices[15],
9780 quad_indices[19]});
9781 break;
9782 }
9783
9785 {
9786 //----------------------------
9787 //
9788 // RefinementCase<dim>::cut_xz
9789 //
9790 // the refined cube will look like this:
9791 //
9792 // *----*----*
9793 // / / /|
9794 // / / / |
9795 // / / / *
9796 // *----*----* /|
9797 // | | | / |
9798 // | | |/ *
9799 // *----*----* /
9800 // | | | /
9801 // | | |/
9802 // *----*----*
9803 //
9804
9805 // first, create the new internal line
9806 new_lines[0]->set_bounding_object_indices(
9807 {middle_vertex_index<dim, spacedim>(hex->face(2)),
9808 middle_vertex_index<dim, spacedim>(hex->face(3))});
9809
9810 // again, first collect some data about the
9811 // indices of the lines, with the following
9812 // numbering:
9813
9814 // face 0: left plane
9815 // *
9816 // /|
9817 // / |
9818 // / *
9819 // * /|
9820 // | 0 |
9821 // |/ *
9822 // * /
9823 // | /
9824 // |/
9825 // *
9826 // face 1: right plane
9827 // *
9828 // /|
9829 // / |
9830 // / *
9831 // * /|
9832 // | 1 |
9833 // |/ *
9834 // * /
9835 // | /
9836 // |/
9837 // *
9838 // face 2: front plane
9839 // (note: x,y exchanged)
9840 // *---*---*
9841 // | 5 |
9842 // *-6-*-7-*
9843 // | 4 |
9844 // *---*---*
9845 // face 3: back plane
9846 // (note: x,y exchanged)
9847 // *---*---*
9848 // | 9 |
9849 // *10-*-11*
9850 // | 8 |
9851 // *---*---*
9852 // face 4: bottom plane
9853 // *---*---*
9854 // / / /
9855 // / 2 /
9856 // / / /
9857 // *---*---*
9858 // face 5: top plane
9859 // *---*---*
9860 // / / /
9861 // / 3 /
9862 // / / /
9863 // *---*---*
9864 // middle planes
9865 // *---*---* *-------*
9866 // / / / | |
9867 // / 12 / | |
9868 // / / / | |
9869 // *---*---* *-------*
9870
9871 // set up a list of line iterators first. from
9872 // this, construct lists of line_indices and
9873 // line orientations later on
9874 const typename Triangulation<
9875 dim,
9876 spacedim>::raw_line_iterator lines[13] = {
9877 hex->face(0)->child(0)->line(
9878 (hex->face(0)->refinement_case() ==
9880 1 :
9881 3), // 0
9882 hex->face(1)->child(0)->line(
9883 (hex->face(1)->refinement_case() ==
9885 1 :
9886 3), // 1
9887 hex->face(4)->child(0)->line(
9888 (hex->face(4)->refinement_case() ==
9890 1 :
9891 3), // 2
9892 hex->face(5)->child(0)->line(
9893 (hex->face(5)->refinement_case() ==
9895 1 :
9896 3), // 3
9897
9898 hex->face(2)
9899 ->isotropic_child(
9901 0, f_or[2], f_fl[2], f_ro[2]))
9902 ->line(
9904 3, f_or[2], f_fl[2], f_ro[2])), // 4
9905 hex->face(2)
9906 ->isotropic_child(
9908 3, f_or[2], f_fl[2], f_ro[2]))
9909 ->line(
9911 2, f_or[2], f_fl[2], f_ro[2])), // 5
9912 hex->face(2)
9913 ->isotropic_child(
9915 0, f_or[2], f_fl[2], f_ro[2]))
9916 ->line(
9918 1, f_or[2], f_fl[2], f_ro[2])), // 6
9919 hex->face(2)
9920 ->isotropic_child(
9922 3, f_or[2], f_fl[2], f_ro[2]))
9923 ->line(
9925 0, f_or[2], f_fl[2], f_ro[2])), // 7
9926
9927 hex->face(3)
9928 ->isotropic_child(
9930 0, f_or[3], f_fl[3], f_ro[3]))
9931 ->line(
9933 3, f_or[3], f_fl[3], f_ro[3])), // 8
9934 hex->face(3)
9935 ->isotropic_child(
9937 3, f_or[3], f_fl[3], f_ro[3]))
9938 ->line(
9940 2, f_or[3], f_fl[3], f_ro[3])), // 9
9941 hex->face(3)
9942 ->isotropic_child(
9944 0, f_or[3], f_fl[3], f_ro[3]))
9945 ->line(
9947 1, f_or[3], f_fl[3], f_ro[3])), // 10
9948 hex->face(3)
9949 ->isotropic_child(
9951 3, f_or[3], f_fl[3], f_ro[3]))
9952 ->line(
9954 0, f_or[3], f_fl[3], f_ro[3])), // 11
9955
9956 new_lines[0] // 12
9957 };
9958
9959 unsigned int line_indices[13];
9960 for (unsigned int i = 0; i < 13; ++i)
9961 line_indices[i] = lines[i]->index();
9962
9963 // the orientation of lines for the inner quads
9964 // is quite tricky. as these lines are newly
9965 // created ones and thus have no parents, they
9966 // cannot inherit this property. set up an array
9967 // and fill it with the respective values
9968 bool line_orientation[13];
9969
9970 // the middle vertices of the
9971 // lines of our front face
9972 const unsigned int middle_vertices[4] = {
9973 hex->line(8)->child(0)->vertex_index(1),
9974 hex->line(9)->child(0)->vertex_index(1),
9975 hex->line(2)->child(0)->vertex_index(1),
9976 hex->line(6)->child(0)->vertex_index(1),
9977 };
9978
9979 // note: for lines 0 to 3 the orientation of the
9980 // line is 'true', if vertex 0 is on the front
9981 for (unsigned int i = 0; i < 4; ++i)
9982 if (lines[i]->vertex_index(0) == middle_vertices[i])
9983 line_orientation[i] = true;
9984 else
9985 {
9986 // it must be the other way round then
9987 Assert(lines[i]->vertex_index(1) ==
9988 middle_vertices[i],
9990 line_orientation[i] = false;
9991 }
9992
9993 // note: for lines 4 to 11 (inner lines of the
9994 // outer quads) the following holds: the second
9995 // vertex of the even lines in standard
9996 // orientation is the vertex in the middle of
9997 // the quad, whereas for odd lines the first
9998 // vertex is the same middle vertex.
9999 for (unsigned int i = 4; i < 12; ++i)
10000 if (lines[i]->vertex_index((i + 1) % 2) ==
10001 middle_vertex_index<dim, spacedim>(
10002 hex->face(1 + i / 4)))
10003 line_orientation[i] = true;
10004 else
10005 {
10006 // it must be the other way
10007 // round then
10008 Assert(lines[i]->vertex_index(i % 2) ==
10009 (middle_vertex_index<dim, spacedim>(
10010 hex->face(1 + i / 4))),
10012 line_orientation[i] = false;
10013 }
10014 // for the last line the line orientation is
10015 // always true, since it was just constructed
10016 // that way
10017 line_orientation[12] = true;
10018
10019 // set up the 4 quads, numbered as follows (left
10020 // quad numbering, right line numbering
10021 // extracted from above), the drawings denote
10022 // middle planes
10023 //
10024 // * *
10025 // /| /|
10026 // / | 3 9
10027 // y/ * / *
10028 // * 3/| * /|
10029 // | / |x 5 12|8
10030 // |/ * |/ *
10031 // * 2/ * /
10032 // | / 4 2
10033 // |/ |/
10034 // * *
10035 //
10036 // y
10037 // *----*----* *-10-*-11-*
10038 // / / / / / /
10039 // / 0 / 1 / 0 12 1
10040 // / / / / / /
10041 // *----*----*x *--6-*--7-*
10042
10043 new_quads[0]->set_bounding_object_indices(
10044 {line_indices[0],
10045 line_indices[12],
10046 line_indices[6],
10047 line_indices[10]});
10048 new_quads[1]->set_bounding_object_indices(
10049 {line_indices[12],
10050 line_indices[1],
10051 line_indices[7],
10052 line_indices[11]});
10053 new_quads[2]->set_bounding_object_indices(
10054 {line_indices[4],
10055 line_indices[8],
10056 line_indices[2],
10057 line_indices[12]});
10058 new_quads[3]->set_bounding_object_indices(
10059 {line_indices[5],
10060 line_indices[9],
10061 line_indices[12],
10062 line_indices[3]});
10063
10064 new_quads[0]->set_line_orientation(
10065 0, line_orientation[0]);
10066 new_quads[0]->set_line_orientation(
10067 2, line_orientation[6]);
10068 new_quads[0]->set_line_orientation(
10069 3, line_orientation[10]);
10070
10071 new_quads[1]->set_line_orientation(
10072 1, line_orientation[1]);
10073 new_quads[1]->set_line_orientation(
10074 2, line_orientation[7]);
10075 new_quads[1]->set_line_orientation(
10076 3, line_orientation[11]);
10077
10078 new_quads[2]->set_line_orientation(
10079 0, line_orientation[4]);
10080 new_quads[2]->set_line_orientation(
10081 1, line_orientation[8]);
10082 new_quads[2]->set_line_orientation(
10083 2, line_orientation[2]);
10084
10085 new_quads[3]->set_line_orientation(
10086 0, line_orientation[5]);
10087 new_quads[3]->set_line_orientation(
10088 1, line_orientation[9]);
10089 new_quads[3]->set_line_orientation(
10090 3, line_orientation[3]);
10091
10092 // the quads are numbered as follows:
10093 //
10094 // planes in the interior of the old hex:
10095 //
10096 // *
10097 // /|
10098 // / | x
10099 // /3 * *-------* *----*----*
10100 // * /| | | / / /
10101 // | / | | | / 0 / 1 /
10102 // |/ * | | / / /
10103 // * 2/ *-------*y *----*----*x
10104 // | /
10105 // |/
10106 // *
10107 //
10108 // children of the faces
10109 // of the old hex
10110 // *---*---* *---*---*
10111 // /|13 | 15| / / /|
10112 // / | | | /18 / 19/ |
10113 // / *---*---* / / / *
10114 // * 5/| | | *---*---* 7/|
10115 // | / |12 | 14| | 9 | 11| / |
10116 // |/4 *---*---* | | |/6 *
10117 // * / / / *---*---* /
10118 // | /16 / 17/ | | | /
10119 // |/ / / | 8 | 10|/
10120 // *---*---* *---*---*
10121 //
10122 // note that we have to take care of the
10123 // orientation of faces.
10124 const int quad_indices[20] = {
10125 new_quads[0]->index(), // 0
10126 new_quads[1]->index(),
10127 new_quads[2]->index(),
10128 new_quads[3]->index(),
10129
10130 hex->face(0)->child_index(
10131 child_at_origin[hex->face(0)->refinement_case() -
10132 1][f_fl[0]][f_ro[0]]), // 4
10133 hex->face(0)->child_index(
10134 1 -
10135 child_at_origin[hex->face(0)->refinement_case() -
10136 1][f_fl[0]][f_ro[0]]),
10137
10138 hex->face(1)->child_index(
10139 child_at_origin[hex->face(1)->refinement_case() -
10140 1][f_fl[1]][f_ro[1]]), // 6
10141 hex->face(1)->child_index(
10142 1 -
10143 child_at_origin[hex->face(1)->refinement_case() -
10144 1][f_fl[1]][f_ro[1]]),
10145
10146 hex->face(2)->isotropic_child_index(
10148 0, f_or[2], f_fl[2], f_ro[2])), // 8
10149 hex->face(2)->isotropic_child_index(
10151 1, f_or[2], f_fl[2], f_ro[2])),
10152 hex->face(2)->isotropic_child_index(
10154 2, f_or[2], f_fl[2], f_ro[2])),
10155 hex->face(2)->isotropic_child_index(
10157 3, f_or[2], f_fl[2], f_ro[2])),
10158
10159 hex->face(3)->isotropic_child_index(
10161 0, f_or[3], f_fl[3], f_ro[3])), // 12
10162 hex->face(3)->isotropic_child_index(
10164 1, f_or[3], f_fl[3], f_ro[3])),
10165 hex->face(3)->isotropic_child_index(
10167 2, f_or[3], f_fl[3], f_ro[3])),
10168 hex->face(3)->isotropic_child_index(
10170 3, f_or[3], f_fl[3], f_ro[3])),
10171
10172 hex->face(4)->child_index(
10173 child_at_origin[hex->face(4)->refinement_case() -
10174 1][f_fl[4]][f_ro[4]]), // 16
10175 hex->face(4)->child_index(
10176 1 -
10177 child_at_origin[hex->face(4)->refinement_case() -
10178 1][f_fl[4]][f_ro[4]]),
10179
10180 hex->face(5)->child_index(
10181 child_at_origin[hex->face(5)->refinement_case() -
10182 1][f_fl[5]][f_ro[5]]), // 18
10183 hex->face(5)->child_index(
10184 1 -
10185 child_at_origin[hex->face(5)->refinement_case() -
10186 1][f_fl[5]][f_ro[5]])};
10187
10188 // due to the exchange of x and y for the front
10189 // and back face, we order the children
10190 // according to
10191 //
10192 // *---*---*
10193 // | 1 | 3 |
10194 // *---*---*
10195 // | 0 | 2 |
10196 // *---*---*
10197 new_hexes[0]->set_bounding_object_indices(
10198 {quad_indices[4],
10199 quad_indices[2],
10200 quad_indices[8],
10201 quad_indices[12],
10202 quad_indices[16],
10203 quad_indices[0]});
10204 new_hexes[1]->set_bounding_object_indices(
10205 {quad_indices[5],
10206 quad_indices[3],
10207 quad_indices[9],
10208 quad_indices[13],
10209 quad_indices[0],
10210 quad_indices[18]});
10211 new_hexes[2]->set_bounding_object_indices(
10212 {quad_indices[2],
10213 quad_indices[6],
10214 quad_indices[10],
10215 quad_indices[14],
10216 quad_indices[17],
10217 quad_indices[1]});
10218 new_hexes[3]->set_bounding_object_indices(
10219 {quad_indices[3],
10220 quad_indices[7],
10221 quad_indices[11],
10222 quad_indices[15],
10223 quad_indices[1],
10224 quad_indices[19]});
10225 break;
10226 }
10227
10229 {
10230 //----------------------------
10231 //
10232 // RefinementCase<dim>::cut_yz
10233 //
10234 // the refined cube will look like this:
10235 //
10236 // *---------*
10237 // / /|
10238 // *---------* |
10239 // / /| |
10240 // *---------* |/|
10241 // | | * |
10242 // | |/| *
10243 // *---------* |/
10244 // | | *
10245 // | |/
10246 // *---------*
10247 //
10248
10249 // first, create the new
10250 // internal line
10251 new_lines[0]->set_bounding_object_indices(
10252
10253 {middle_vertex_index<dim, spacedim>(hex->face(0)),
10254 middle_vertex_index<dim, spacedim>(hex->face(1))});
10255
10256 // again, first collect some data about the
10257 // indices of the lines, with the following
10258 // numbering: (note that face 0 and 1 each are
10259 // shown twice for better readability)
10260
10261 // face 0: left plane
10262 // * *
10263 // /| /|
10264 // * | * |
10265 // /| * /| *
10266 // * 5/| * |7|
10267 // | * | | * |
10268 // |/| * |6| *
10269 // * 4/ * |/
10270 // | * | *
10271 // |/ |/
10272 // * *
10273 // face 1: right plane
10274 // * *
10275 // /| /|
10276 // * | * |
10277 // /| * /| *
10278 // * 9/| * |11
10279 // | * | | * |
10280 // |/| * |10 *
10281 // * 8/ * |/
10282 // | * | *
10283 // |/ |/
10284 // * *
10285 // face 2: front plane
10286 // (note: x,y exchanged)
10287 // *-------*
10288 // | |
10289 // *---0---*
10290 // | |
10291 // *-------*
10292 // face 3: back plane
10293 // (note: x,y exchanged)
10294 // *-------*
10295 // | |
10296 // *---1---*
10297 // | |
10298 // *-------*
10299 // face 4: bottom plane
10300 // *-------*
10301 // / /
10302 // *---2---*
10303 // / /
10304 // *-------*
10305 // face 5: top plane
10306 // *-------*
10307 // / /
10308 // *---3---*
10309 // / /
10310 // *-------*
10311 // middle planes
10312 // *-------* *-------*
10313 // / / | |
10314 // *---12--* | |
10315 // / / | |
10316 // *-------* *-------*
10317
10318 // set up a list of line iterators first. from
10319 // this, construct lists of line_indices and
10320 // line orientations later on
10321 const typename Triangulation<
10322 dim,
10323 spacedim>::raw_line_iterator lines[13] = {
10324 hex->face(2)->child(0)->line(
10325 (hex->face(2)->refinement_case() ==
10327 1 :
10328 3), // 0
10329 hex->face(3)->child(0)->line(
10330 (hex->face(3)->refinement_case() ==
10332 1 :
10333 3), // 1
10334 hex->face(4)->child(0)->line(
10335 (hex->face(4)->refinement_case() ==
10337 1 :
10338 3), // 2
10339 hex->face(5)->child(0)->line(
10340 (hex->face(5)->refinement_case() ==
10342 1 :
10343 3), // 3
10344
10345 hex->face(0)
10346 ->isotropic_child(
10348 0, f_or[0], f_fl[0], f_ro[0]))
10349 ->line(
10351 1, f_or[0], f_fl[0], f_ro[0])), // 4
10352 hex->face(0)
10353 ->isotropic_child(
10355 3, f_or[0], f_fl[0], f_ro[0]))
10356 ->line(
10358 0, f_or[0], f_fl[0], f_ro[0])), // 5
10359 hex->face(0)
10360 ->isotropic_child(
10362 0, f_or[0], f_fl[0], f_ro[0]))
10363 ->line(
10365 3, f_or[0], f_fl[0], f_ro[0])), // 6
10366 hex->face(0)
10367 ->isotropic_child(
10369 3, f_or[0], f_fl[0], f_ro[0]))
10370 ->line(
10372 2, f_or[0], f_fl[0], f_ro[0])), // 7
10373
10374 hex->face(1)
10375 ->isotropic_child(
10377 0, f_or[1], f_fl[1], f_ro[1]))
10378 ->line(
10380 1, f_or[1], f_fl[1], f_ro[1])), // 8
10381 hex->face(1)
10382 ->isotropic_child(
10384 3, f_or[1], f_fl[1], f_ro[1]))
10385 ->line(
10387 0, f_or[1], f_fl[1], f_ro[1])), // 9
10388 hex->face(1)
10389 ->isotropic_child(
10391 0, f_or[1], f_fl[1], f_ro[1]))
10392 ->line(
10394 3, f_or[1], f_fl[1], f_ro[1])), // 10
10395 hex->face(1)
10396 ->isotropic_child(
10398 3, f_or[1], f_fl[1], f_ro[1]))
10399 ->line(
10401 2, f_or[1], f_fl[1], f_ro[1])), // 11
10402
10403 new_lines[0] // 12
10404 };
10405
10406 unsigned int line_indices[13];
10407
10408 for (unsigned int i = 0; i < 13; ++i)
10409 line_indices[i] = lines[i]->index();
10410
10411 // the orientation of lines for the inner quads
10412 // is quite tricky. as these lines are newly
10413 // created ones and thus have no parents, they
10414 // cannot inherit this property. set up an array
10415 // and fill it with the respective values
10416 bool line_orientation[13];
10417
10418 // the middle vertices of the lines of our front
10419 // face
10420 const unsigned int middle_vertices[4] = {
10421 hex->line(8)->child(0)->vertex_index(1),
10422 hex->line(10)->child(0)->vertex_index(1),
10423 hex->line(0)->child(0)->vertex_index(1),
10424 hex->line(4)->child(0)->vertex_index(1),
10425 };
10426
10427 // note: for lines 0 to 3 the orientation of the
10428 // line is 'true', if vertex 0 is on the front
10429 for (unsigned int i = 0; i < 4; ++i)
10430 if (lines[i]->vertex_index(0) == middle_vertices[i])
10431 line_orientation[i] = true;
10432 else
10433 {
10434 // it must be the other way round then
10435 Assert(lines[i]->vertex_index(1) ==
10436 middle_vertices[i],
10438 line_orientation[i] = false;
10439 }
10440
10441 // note: for lines 4 to 11 (inner lines of the
10442 // outer quads) the following holds: the second
10443 // vertex of the even lines in standard
10444 // orientation is the vertex in the middle of
10445 // the quad, whereas for odd lines the first
10446 // vertex is the same middle vertex.
10447 for (unsigned int i = 4; i < 12; ++i)
10448 if (lines[i]->vertex_index((i + 1) % 2) ==
10449 middle_vertex_index<dim, spacedim>(
10450 hex->face(i / 4 - 1)))
10451 line_orientation[i] = true;
10452 else
10453 {
10454 // it must be the other way
10455 // round then
10456 Assert(lines[i]->vertex_index(i % 2) ==
10457 (middle_vertex_index<dim, spacedim>(
10458 hex->face(i / 4 - 1))),
10460 line_orientation[i] = false;
10461 }
10462 // for the last line the line orientation is
10463 // always true, since it was just constructed
10464 // that way
10465 line_orientation[12] = true;
10466
10467 // set up the 4 quads, numbered as follows (left
10468 // quad numbering, right line numbering
10469 // extracted from above)
10470 //
10471 // x
10472 // *-------* *---3---*
10473 // | 3 | 5 9
10474 // *-------* *---12--*
10475 // | 2 | 4 8
10476 // *-------*y *---2---*
10477 //
10478 // y
10479 // *---------* *----1----*
10480 // / 1 / 7 11
10481 // *---------* *----12---*
10482 // / 0 / 6 10
10483 // *---------*x *----0----*
10484
10485 new_quads[0]->set_bounding_object_indices(
10486 {line_indices[6],
10487 line_indices[10],
10488 line_indices[0],
10489 line_indices[12]});
10490 new_quads[1]->set_bounding_object_indices(
10491 {line_indices[7],
10492 line_indices[11],
10493 line_indices[12],
10494 line_indices[1]});
10495 new_quads[2]->set_bounding_object_indices(
10496 {line_indices[2],
10497 line_indices[12],
10498 line_indices[4],
10499 line_indices[8]});
10500 new_quads[3]->set_bounding_object_indices(
10501 {line_indices[12],
10502 line_indices[3],
10503 line_indices[5],
10504 line_indices[9]});
10505
10506 new_quads[0]->set_line_orientation(
10507 0, line_orientation[6]);
10508 new_quads[0]->set_line_orientation(
10509 1, line_orientation[10]);
10510 new_quads[0]->set_line_orientation(
10511 2, line_orientation[0]);
10512
10513 new_quads[1]->set_line_orientation(
10514 0, line_orientation[7]);
10515 new_quads[1]->set_line_orientation(
10516 1, line_orientation[11]);
10517 new_quads[1]->set_line_orientation(
10518 3, line_orientation[1]);
10519
10520 new_quads[2]->set_line_orientation(
10521 0, line_orientation[2]);
10522 new_quads[2]->set_line_orientation(
10523 2, line_orientation[4]);
10524 new_quads[2]->set_line_orientation(
10525 3, line_orientation[8]);
10526
10527 new_quads[3]->set_line_orientation(
10528 1, line_orientation[3]);
10529 new_quads[3]->set_line_orientation(
10530 2, line_orientation[5]);
10531 new_quads[3]->set_line_orientation(
10532 3, line_orientation[9]);
10533
10534 // the quads are numbered as follows:
10535 //
10536 // planes in the interior of the old hex:
10537 //
10538 // *
10539 // /|
10540 // / | x
10541 // / | *-------* *---------*
10542 // * | | 3 | / 1 /
10543 // | | *-------* *---------*
10544 // | * | 2 | / 0 /
10545 // | / *-------*y *---------*x
10546 // | /
10547 // |/
10548 // *
10549 //
10550 // children of the faces
10551 // of the old hex
10552 // *-------* *-------*
10553 // /| | / 19 /|
10554 // * | 15 | *-------* |
10555 // /|7*-------* / 18 /|11
10556 // * |/| | *-------* |/|
10557 // |6* | 14 | | 10* |
10558 // |/|5*-------* | 13 |/|9*
10559 // * |/ 17 / *-------* |/
10560 // |4*-------* | |8*
10561 // |/ 16 / | 12 |/
10562 // *-------* *-------*
10563 //
10564 // note that we have to take care of the
10565 // orientation of faces.
10566 const int quad_indices[20] = {
10567 new_quads[0]->index(), // 0
10568 new_quads[1]->index(),
10569 new_quads[2]->index(),
10570 new_quads[3]->index(),
10571
10572 hex->face(0)->isotropic_child_index(
10574 0, f_or[0], f_fl[0], f_ro[0])), // 4
10575 hex->face(0)->isotropic_child_index(
10577 1, f_or[0], f_fl[0], f_ro[0])),
10578 hex->face(0)->isotropic_child_index(
10580 2, f_or[0], f_fl[0], f_ro[0])),
10581 hex->face(0)->isotropic_child_index(
10583 3, f_or[0], f_fl[0], f_ro[0])),
10584
10585 hex->face(1)->isotropic_child_index(
10587 0, f_or[1], f_fl[1], f_ro[1])), // 8
10588 hex->face(1)->isotropic_child_index(
10590 1, f_or[1], f_fl[1], f_ro[1])),
10591 hex->face(1)->isotropic_child_index(
10593 2, f_or[1], f_fl[1], f_ro[1])),
10594 hex->face(1)->isotropic_child_index(
10596 3, f_or[1], f_fl[1], f_ro[1])),
10597
10598 hex->face(2)->child_index(
10599 child_at_origin[hex->face(2)->refinement_case() -
10600 1][f_fl[2]][f_ro[2]]), // 12
10601 hex->face(2)->child_index(
10602 1 -
10603 child_at_origin[hex->face(2)->refinement_case() -
10604 1][f_fl[2]][f_ro[2]]),
10605
10606 hex->face(3)->child_index(
10607 child_at_origin[hex->face(3)->refinement_case() -
10608 1][f_fl[3]][f_ro[3]]), // 14
10609 hex->face(3)->child_index(
10610 1 -
10611 child_at_origin[hex->face(3)->refinement_case() -
10612 1][f_fl[3]][f_ro[3]]),
10613
10614 hex->face(4)->child_index(
10615 child_at_origin[hex->face(4)->refinement_case() -
10616 1][f_fl[4]][f_ro[4]]), // 16
10617 hex->face(4)->child_index(
10618 1 -
10619 child_at_origin[hex->face(4)->refinement_case() -
10620 1][f_fl[4]][f_ro[4]]),
10621
10622 hex->face(5)->child_index(
10623 child_at_origin[hex->face(5)->refinement_case() -
10624 1][f_fl[5]][f_ro[5]]), // 18
10625 hex->face(5)->child_index(
10626 1 -
10627 child_at_origin[hex->face(5)->refinement_case() -
10628 1][f_fl[5]][f_ro[5]])};
10629
10630 new_hexes[0]->set_bounding_object_indices(
10631 {quad_indices[4],
10632 quad_indices[8],
10633 quad_indices[12],
10634 quad_indices[2],
10635 quad_indices[16],
10636 quad_indices[0]});
10637 new_hexes[1]->set_bounding_object_indices(
10638 {quad_indices[5],
10639 quad_indices[9],
10640 quad_indices[2],
10641 quad_indices[14],
10642 quad_indices[17],
10643 quad_indices[1]});
10644 new_hexes[2]->set_bounding_object_indices(
10645 {quad_indices[6],
10646 quad_indices[10],
10647 quad_indices[13],
10648 quad_indices[3],
10649 quad_indices[0],
10650 quad_indices[18]});
10651 new_hexes[3]->set_bounding_object_indices(
10652 {quad_indices[7],
10653 quad_indices[11],
10654 quad_indices[3],
10655 quad_indices[15],
10656 quad_indices[1],
10657 quad_indices[19]});
10658 break;
10659 }
10660
10662 {
10663 //----------------------------
10664 //
10665 // RefinementCase<dim>::cut_xyz
10666 // isotropic refinement
10667 //
10668 // the refined cube will look
10669 // like this:
10670 //
10671 // *----*----*
10672 // / / /|
10673 // *----*----* |
10674 // / / /| *
10675 // *----*----* |/|
10676 // | | | * |
10677 // | | |/| *
10678 // *----*----* |/
10679 // | | | *
10680 // | | |/
10681 // *----*----*
10682 //
10683
10684 // find the next unused vertex and set it
10685 // appropriately
10686 while (
10687 triangulation.vertices_used[next_unused_vertex] ==
10688 true)
10689 ++next_unused_vertex;
10690 Assert(
10691 next_unused_vertex < triangulation.vertices.size(),
10692 ExcMessage(
10693 "Internal error: During refinement, the triangulation wants to access an element of the 'vertices' array but it turns out that the array is not large enough."));
10694 triangulation.vertices_used[next_unused_vertex] =
10695 true;
10696
10697 // the new vertex is definitely in the interior,
10698 // so we need not worry about the
10699 // boundary. However we need to worry about
10700 // Manifolds. Let the cell compute its own
10701 // center, by querying the underlying manifold
10702 // object.
10703 triangulation.vertices[next_unused_vertex] =
10704 hex->center(true, true);
10705
10706 // set the data of the six lines. first collect
10707 // the indices of the seven vertices (consider
10708 // the two planes to be crossed to form the
10709 // planes cutting the hex in two vertically and
10710 // horizontally)
10711 //
10712 // *--3--* *--5--*
10713 // / / / | | |
10714 // 0--6--1 0--6--1
10715 // / / / | | |
10716 // *--2--* *--4--*
10717 // the lines are numbered
10718 // as follows:
10719 // *--*--* *--*--*
10720 // / 1 / | 5 |
10721 // *2-*-3* *2-*-3*
10722 // / 0 / | 4 |
10723 // *--*--* *--*--*
10724 //
10725 const unsigned int vertex_indices[7] = {
10726 middle_vertex_index<dim, spacedim>(hex->face(0)),
10727 middle_vertex_index<dim, spacedim>(hex->face(1)),
10728 middle_vertex_index<dim, spacedim>(hex->face(2)),
10729 middle_vertex_index<dim, spacedim>(hex->face(3)),
10730 middle_vertex_index<dim, spacedim>(hex->face(4)),
10731 middle_vertex_index<dim, spacedim>(hex->face(5)),
10732 next_unused_vertex};
10733
10734 new_lines[0]->set_bounding_object_indices(
10736 new_lines[1]->set_bounding_object_indices(
10738 new_lines[2]->set_bounding_object_indices(
10740 new_lines[3]->set_bounding_object_indices(
10742 new_lines[4]->set_bounding_object_indices(
10744 new_lines[5]->set_bounding_object_indices(
10746
10747 // again, first collect some data about the
10748 // indices of the lines, with the following
10749 // numbering: (note that face 0 and 1 each are
10750 // shown twice for better readability)
10751
10752 // face 0: left plane
10753 // * *
10754 // /| /|
10755 // * | * |
10756 // /| * /| *
10757 // * 1/| * |3|
10758 // | * | | * |
10759 // |/| * |2| *
10760 // * 0/ * |/
10761 // | * | *
10762 // |/ |/
10763 // * *
10764 // face 1: right plane
10765 // * *
10766 // /| /|
10767 // * | * |
10768 // /| * /| *
10769 // * 5/| * |7|
10770 // | * | | * |
10771 // |/| * |6| *
10772 // * 4/ * |/
10773 // | * | *
10774 // |/ |/
10775 // * *
10776 // face 2: front plane
10777 // (note: x,y exchanged)
10778 // *---*---*
10779 // | 11 |
10780 // *-8-*-9-*
10781 // | 10 |
10782 // *---*---*
10783 // face 3: back plane
10784 // (note: x,y exchanged)
10785 // *---*---*
10786 // | 15 |
10787 // *12-*-13*
10788 // | 14 |
10789 // *---*---*
10790 // face 4: bottom plane
10791 // *---*---*
10792 // / 17 /
10793 // *18-*-19*
10794 // / 16 /
10795 // *---*---*
10796 // face 5: top plane
10797 // *---*---*
10798 // / 21 /
10799 // *22-*-23*
10800 // / 20 /
10801 // *---*---*
10802 // middle planes
10803 // *---*---* *---*---*
10804 // / 25 / | 29 |
10805 // *26-*-27* *26-*-27*
10806 // / 24 / | 28 |
10807 // *---*---* *---*---*
10808
10809 // set up a list of line iterators first. from
10810 // this, construct lists of line_indices and
10811 // line orientations later on
10812 const typename Triangulation<
10813 dim,
10814 spacedim>::raw_line_iterator lines[30] = {
10815 hex->face(0)
10816 ->isotropic_child(
10818 0, f_or[0], f_fl[0], f_ro[0]))
10819 ->line(
10821 1, f_or[0], f_fl[0], f_ro[0])), // 0
10822 hex->face(0)
10823 ->isotropic_child(
10825 3, f_or[0], f_fl[0], f_ro[0]))
10826 ->line(
10828 0, f_or[0], f_fl[0], f_ro[0])), // 1
10829 hex->face(0)
10830 ->isotropic_child(
10832 0, f_or[0], f_fl[0], f_ro[0]))
10833 ->line(
10835 3, f_or[0], f_fl[0], f_ro[0])), // 2
10836 hex->face(0)
10837 ->isotropic_child(
10839 3, f_or[0], f_fl[0], f_ro[0]))
10840 ->line(
10842 2, f_or[0], f_fl[0], f_ro[0])), // 3
10843
10844 hex->face(1)
10845 ->isotropic_child(
10847 0, f_or[1], f_fl[1], f_ro[1]))
10848 ->line(
10850 1, f_or[1], f_fl[1], f_ro[1])), // 4
10851 hex->face(1)
10852 ->isotropic_child(
10854 3, f_or[1], f_fl[1], f_ro[1]))
10855 ->line(
10857 0, f_or[1], f_fl[1], f_ro[1])), // 5
10858 hex->face(1)
10859 ->isotropic_child(
10861 0, f_or[1], f_fl[1], f_ro[1]))
10862 ->line(
10864 3, f_or[1], f_fl[1], f_ro[1])), // 6
10865 hex->face(1)
10866 ->isotropic_child(
10868 3, f_or[1], f_fl[1], f_ro[1]))
10869 ->line(
10871 2, f_or[1], f_fl[1], f_ro[1])), // 7
10872
10873 hex->face(2)
10874 ->isotropic_child(
10876 0, f_or[2], f_fl[2], f_ro[2]))
10877 ->line(
10879 1, f_or[2], f_fl[2], f_ro[2])), // 8
10880 hex->face(2)
10881 ->isotropic_child(
10883 3, f_or[2], f_fl[2], f_ro[2]))
10884 ->line(
10886 0, f_or[2], f_fl[2], f_ro[2])), // 9
10887 hex->face(2)
10888 ->isotropic_child(
10890 0, f_or[2], f_fl[2], f_ro[2]))
10891 ->line(
10893 3, f_or[2], f_fl[2], f_ro[2])), // 10
10894 hex->face(2)
10895 ->isotropic_child(
10897 3, f_or[2], f_fl[2], f_ro[2]))
10898 ->line(
10900 2, f_or[2], f_fl[2], f_ro[2])), // 11
10901
10902 hex->face(3)
10903 ->isotropic_child(
10905 0, f_or[3], f_fl[3], f_ro[3]))
10906 ->line(
10908 1, f_or[3], f_fl[3], f_ro[3])), // 12
10909 hex->face(3)
10910 ->isotropic_child(
10912 3, f_or[3], f_fl[3], f_ro[3]))
10913 ->line(
10915 0, f_or[3], f_fl[3], f_ro[3])), // 13
10916 hex->face(3)
10917 ->isotropic_child(
10919 0, f_or[3], f_fl[3], f_ro[3]))
10920 ->line(
10922 3, f_or[3], f_fl[3], f_ro[3])), // 14
10923 hex->face(3)
10924 ->isotropic_child(
10926 3, f_or[3], f_fl[3], f_ro[3]))
10927 ->line(
10929 2, f_or[3], f_fl[3], f_ro[3])), // 15
10930
10931 hex->face(4)
10932 ->isotropic_child(
10934 0, f_or[4], f_fl[4], f_ro[4]))
10935 ->line(
10937 1, f_or[4], f_fl[4], f_ro[4])), // 16
10938 hex->face(4)
10939 ->isotropic_child(
10941 3, f_or[4], f_fl[4], f_ro[4]))
10942 ->line(
10944 0, f_or[4], f_fl[4], f_ro[4])), // 17
10945 hex->face(4)
10946 ->isotropic_child(
10948 0, f_or[4], f_fl[4], f_ro[4]))
10949 ->line(
10951 3, f_or[4], f_fl[4], f_ro[4])), // 18
10952 hex->face(4)
10953 ->isotropic_child(
10955 3, f_or[4], f_fl[4], f_ro[4]))
10956 ->line(
10958 2, f_or[4], f_fl[4], f_ro[4])), // 19
10959
10960 hex->face(5)
10961 ->isotropic_child(
10963 0, f_or[5], f_fl[5], f_ro[5]))
10964 ->line(
10966 1, f_or[5], f_fl[5], f_ro[5])), // 20
10967 hex->face(5)
10968 ->isotropic_child(
10970 3, f_or[5], f_fl[5], f_ro[5]))
10971 ->line(
10973 0, f_or[5], f_fl[5], f_ro[5])), // 21
10974 hex->face(5)
10975 ->isotropic_child(
10977 0, f_or[5], f_fl[5], f_ro[5]))
10978 ->line(
10980 3, f_or[5], f_fl[5], f_ro[5])), // 22
10981 hex->face(5)
10982 ->isotropic_child(
10984 3, f_or[5], f_fl[5], f_ro[5]))
10985 ->line(
10987 2, f_or[5], f_fl[5], f_ro[5])), // 23
10988
10989 new_lines[0], // 24
10990 new_lines[1], // 25
10991 new_lines[2], // 26
10992 new_lines[3], // 27
10993 new_lines[4], // 28
10994 new_lines[5] // 29
10995 };
10996
10997 unsigned int line_indices[30];
10998 for (unsigned int i = 0; i < 30; ++i)
10999 line_indices[i] = lines[i]->index();
11000
11001 // the orientation of lines for the inner quads
11002 // is quite tricky. as these lines are newly
11003 // created ones and thus have no parents, they
11004 // cannot inherit this property. set up an array
11005 // and fill it with the respective values
11006 bool line_orientation[30];
11007
11008 // note: for the first 24 lines (inner lines of
11009 // the outer quads) the following holds: the
11010 // second vertex of the even lines in standard
11011 // orientation is the vertex in the middle of
11012 // the quad, whereas for odd lines the first
11013 // vertex is the same middle vertex.
11014 for (unsigned int i = 0; i < 24; ++i)
11015 if (lines[i]->vertex_index((i + 1) % 2) ==
11016 vertex_indices[i / 4])
11017 line_orientation[i] = true;
11018 else
11019 {
11020 // it must be the other way
11021 // round then
11022 Assert(lines[i]->vertex_index(i % 2) ==
11023 vertex_indices[i / 4],
11025 line_orientation[i] = false;
11026 }
11027 // for the last 6 lines the line orientation is
11028 // always true, since they were just constructed
11029 // that way
11030 for (unsigned int i = 24; i < 30; ++i)
11031 line_orientation[i] = true;
11032
11033 // set up the 12 quads, numbered as follows
11034 // (left quad numbering, right line numbering
11035 // extracted from above)
11036 //
11037 // * *
11038 // /| 21|
11039 // * | * 15
11040 // y/|3* 20| *
11041 // * |/| * |/|
11042 // |2* |x 11 * 14
11043 // |/|1* |/| *
11044 // * |/ * |17
11045 // |0* 10 *
11046 // |/ |16
11047 // * *
11048 //
11049 // x
11050 // *---*---* *22-*-23*
11051 // | 5 | 7 | 1 29 5
11052 // *---*---* *26-*-27*
11053 // | 4 | 6 | 0 28 4
11054 // *---*---*y *18-*-19*
11055 //
11056 // y
11057 // *----*----* *-12-*-13-*
11058 // / 10 / 11 / 3 25 7
11059 // *----*----* *-26-*-27-*
11060 // / 8 / 9 / 2 24 6
11061 // *----*----*x *--8-*--9-*
11062
11063 new_quads[0]->set_bounding_object_indices(
11064 {line_indices[10],
11065 line_indices[28],
11066 line_indices[16],
11067 line_indices[24]});
11068 new_quads[1]->set_bounding_object_indices(
11069 {line_indices[28],
11070 line_indices[14],
11071 line_indices[17],
11072 line_indices[25]});
11073 new_quads[2]->set_bounding_object_indices(
11074 {line_indices[11],
11075 line_indices[29],
11076 line_indices[24],
11077 line_indices[20]});
11078 new_quads[3]->set_bounding_object_indices(
11079 {line_indices[29],
11080 line_indices[15],
11081 line_indices[25],
11082 line_indices[21]});
11083 new_quads[4]->set_bounding_object_indices(
11084 {line_indices[18],
11085 line_indices[26],
11086 line_indices[0],
11087 line_indices[28]});
11088 new_quads[5]->set_bounding_object_indices(
11089 {line_indices[26],
11090 line_indices[22],
11091 line_indices[1],
11092 line_indices[29]});
11093 new_quads[6]->set_bounding_object_indices(
11094 {line_indices[19],
11095 line_indices[27],
11096 line_indices[28],
11097 line_indices[4]});
11098 new_quads[7]->set_bounding_object_indices(
11099 {line_indices[27],
11100 line_indices[23],
11101 line_indices[29],
11102 line_indices[5]});
11103 new_quads[8]->set_bounding_object_indices(
11104 {line_indices[2],
11105 line_indices[24],
11106 line_indices[8],
11107 line_indices[26]});
11108 new_quads[9]->set_bounding_object_indices(
11109 {line_indices[24],
11110 line_indices[6],
11111 line_indices[9],
11112 line_indices[27]});
11113 new_quads[10]->set_bounding_object_indices(
11114 {line_indices[3],
11115 line_indices[25],
11116 line_indices[26],
11117 line_indices[12]});
11118 new_quads[11]->set_bounding_object_indices(
11119 {line_indices[25],
11120 line_indices[7],
11121 line_indices[27],
11122 line_indices[13]});
11123
11124 // now reset the line_orientation flags of outer
11125 // lines as they cannot be set in a loop (at
11126 // least not easily)
11127 new_quads[0]->set_line_orientation(
11128 0, line_orientation[10]);
11129 new_quads[0]->set_line_orientation(
11130 2, line_orientation[16]);
11131
11132 new_quads[1]->set_line_orientation(
11133 1, line_orientation[14]);
11134 new_quads[1]->set_line_orientation(
11135 2, line_orientation[17]);
11136
11137 new_quads[2]->set_line_orientation(
11138 0, line_orientation[11]);
11139 new_quads[2]->set_line_orientation(
11140 3, line_orientation[20]);
11141
11142 new_quads[3]->set_line_orientation(
11143 1, line_orientation[15]);
11144 new_quads[3]->set_line_orientation(
11145 3, line_orientation[21]);
11146
11147 new_quads[4]->set_line_orientation(
11148 0, line_orientation[18]);
11149 new_quads[4]->set_line_orientation(
11150 2, line_orientation[0]);
11151
11152 new_quads[5]->set_line_orientation(
11153 1, line_orientation[22]);
11154 new_quads[5]->set_line_orientation(
11155 2, line_orientation[1]);
11156
11157 new_quads[6]->set_line_orientation(
11158 0, line_orientation[19]);
11159 new_quads[6]->set_line_orientation(
11160 3, line_orientation[4]);
11161
11162 new_quads[7]->set_line_orientation(
11163 1, line_orientation[23]);
11164 new_quads[7]->set_line_orientation(
11165 3, line_orientation[5]);
11166
11167 new_quads[8]->set_line_orientation(
11168 0, line_orientation[2]);
11169 new_quads[8]->set_line_orientation(
11170 2, line_orientation[8]);
11171
11172 new_quads[9]->set_line_orientation(
11173 1, line_orientation[6]);
11174 new_quads[9]->set_line_orientation(
11175 2, line_orientation[9]);
11176
11177 new_quads[10]->set_line_orientation(
11178 0, line_orientation[3]);
11179 new_quads[10]->set_line_orientation(
11180 3, line_orientation[12]);
11181
11182 new_quads[11]->set_line_orientation(
11183 1, line_orientation[7]);
11184 new_quads[11]->set_line_orientation(
11185 3, line_orientation[13]);
11186
11187 //-------------------------------
11188 // create the eight new hexes
11189 //
11190 // again first collect some data. here, we need
11191 // the indices of a whole lotta quads.
11192
11193 // the quads are numbered as follows:
11194 //
11195 // planes in the interior of the old hex:
11196 //
11197 // *
11198 // /|
11199 // * |
11200 // /|3* *---*---* *----*----*
11201 // * |/| | 5 | 7 | / 10 / 11 /
11202 // |2* | *---*---* *----*----*
11203 // |/|1* | 4 | 6 | / 8 / 9 /
11204 // * |/ *---*---*y *----*----*x
11205 // |0*
11206 // |/
11207 // *
11208 //
11209 // children of the faces
11210 // of the old hex
11211 // *-------* *-------*
11212 // /|25 27| /34 35/|
11213 // 15| | / /19
11214 // / | | /32 33/ |
11215 // * |24 26| *-------*18 |
11216 // 1413*-------* |21 23| 17*
11217 // | /30 31/ | | /
11218 // 12/ / | |16
11219 // |/28 29/ |20 22|/
11220 // *-------* *-------*
11221 //
11222 // note that we have to
11223 // take care of the
11224 // orientation of
11225 // faces.
11226 const int quad_indices[36] = {
11227 new_quads[0]->index(), // 0
11228 new_quads[1]->index(),
11229 new_quads[2]->index(),
11230 new_quads[3]->index(),
11231 new_quads[4]->index(),
11232 new_quads[5]->index(),
11233 new_quads[6]->index(),
11234 new_quads[7]->index(),
11235 new_quads[8]->index(),
11236 new_quads[9]->index(),
11237 new_quads[10]->index(),
11238 new_quads[11]->index(), // 11
11239
11240 hex->face(0)->isotropic_child_index(
11242 0, f_or[0], f_fl[0], f_ro[0])), // 12
11243 hex->face(0)->isotropic_child_index(
11245 1, f_or[0], f_fl[0], f_ro[0])),
11246 hex->face(0)->isotropic_child_index(
11248 2, f_or[0], f_fl[0], f_ro[0])),
11249 hex->face(0)->isotropic_child_index(
11251 3, f_or[0], f_fl[0], f_ro[0])),
11252
11253 hex->face(1)->isotropic_child_index(
11255 0, f_or[1], f_fl[1], f_ro[1])), // 16
11256 hex->face(1)->isotropic_child_index(
11258 1, f_or[1], f_fl[1], f_ro[1])),
11259 hex->face(1)->isotropic_child_index(
11261 2, f_or[1], f_fl[1], f_ro[1])),
11262 hex->face(1)->isotropic_child_index(
11264 3, f_or[1], f_fl[1], f_ro[1])),
11265
11266 hex->face(2)->isotropic_child_index(
11268 0, f_or[2], f_fl[2], f_ro[2])), // 20
11269 hex->face(2)->isotropic_child_index(
11271 1, f_or[2], f_fl[2], f_ro[2])),
11272 hex->face(2)->isotropic_child_index(
11274 2, f_or[2], f_fl[2], f_ro[2])),
11275 hex->face(2)->isotropic_child_index(
11277 3, f_or[2], f_fl[2], f_ro[2])),
11278
11279 hex->face(3)->isotropic_child_index(
11281 0, f_or[3], f_fl[3], f_ro[3])), // 24
11282 hex->face(3)->isotropic_child_index(
11284 1, f_or[3], f_fl[3], f_ro[3])),
11285 hex->face(3)->isotropic_child_index(
11287 2, f_or[3], f_fl[3], f_ro[3])),
11288 hex->face(3)->isotropic_child_index(
11290 3, f_or[3], f_fl[3], f_ro[3])),
11291
11292 hex->face(4)->isotropic_child_index(
11294 0, f_or[4], f_fl[4], f_ro[4])), // 28
11295 hex->face(4)->isotropic_child_index(
11297 1, f_or[4], f_fl[4], f_ro[4])),
11298 hex->face(4)->isotropic_child_index(
11300 2, f_or[4], f_fl[4], f_ro[4])),
11301 hex->face(4)->isotropic_child_index(
11303 3, f_or[4], f_fl[4], f_ro[4])),
11304
11305 hex->face(5)->isotropic_child_index(
11307 0, f_or[5], f_fl[5], f_ro[5])), // 32
11308 hex->face(5)->isotropic_child_index(
11310 1, f_or[5], f_fl[5], f_ro[5])),
11311 hex->face(5)->isotropic_child_index(
11313 2, f_or[5], f_fl[5], f_ro[5])),
11314 hex->face(5)->isotropic_child_index(
11316 3, f_or[5], f_fl[5], f_ro[5]))};
11317
11318 // bottom children
11319 new_hexes[0]->set_bounding_object_indices(
11320 {quad_indices[12],
11321 quad_indices[0],
11322 quad_indices[20],
11323 quad_indices[4],
11324 quad_indices[28],
11325 quad_indices[8]});
11326 new_hexes[1]->set_bounding_object_indices(
11327 {quad_indices[0],
11328 quad_indices[16],
11329 quad_indices[22],
11330 quad_indices[6],
11331 quad_indices[29],
11332 quad_indices[9]});
11333 new_hexes[2]->set_bounding_object_indices(
11334 {quad_indices[13],
11335 quad_indices[1],
11336 quad_indices[4],
11337 quad_indices[24],
11338 quad_indices[30],
11339 quad_indices[10]});
11340 new_hexes[3]->set_bounding_object_indices(
11341 {quad_indices[1],
11342 quad_indices[17],
11343 quad_indices[6],
11344 quad_indices[26],
11345 quad_indices[31],
11346 quad_indices[11]});
11347
11348 // top children
11349 new_hexes[4]->set_bounding_object_indices(
11350 {quad_indices[14],
11351 quad_indices[2],
11352 quad_indices[21],
11353 quad_indices[5],
11354 quad_indices[8],
11355 quad_indices[32]});
11356 new_hexes[5]->set_bounding_object_indices(
11357 {quad_indices[2],
11358 quad_indices[18],
11359 quad_indices[23],
11360 quad_indices[7],
11361 quad_indices[9],
11362 quad_indices[33]});
11363 new_hexes[6]->set_bounding_object_indices(
11364 {quad_indices[15],
11365 quad_indices[3],
11366 quad_indices[5],
11367 quad_indices[25],
11368 quad_indices[10],
11369 quad_indices[34]});
11370 new_hexes[7]->set_bounding_object_indices(
11371 {quad_indices[3],
11372 quad_indices[19],
11373 quad_indices[7],
11374 quad_indices[27],
11375 quad_indices[11],
11376 quad_indices[35]});
11377 break;
11378 }
11379 default:
11380 // all refinement cases have been treated, there
11381 // only remains
11382 // RefinementCase<dim>::no_refinement as
11383 // untreated enumeration value. However, in that
11384 // case we should have aborted much
11385 // earlier. thus we should never get here
11387 break;
11388 } // switch (ref_case)
11389
11390 // and set face orientation flags. note that new
11391 // faces in the interior of the mother cell always
11392 // have a correctly oriented face, but the ones on
11393 // the outer faces will inherit this flag
11394 //
11395 // the flag have been set to true for all faces
11396 // initially, now go the other way round and reset
11397 // faces that are at the boundary of the mother cube
11398 //
11399 // the same is true for the face_flip and
11400 // face_rotation flags. however, the latter two are
11401 // set to false by default as this is the standard
11402 // value
11403
11404 // loop over all faces and all (relevant) subfaces
11405 // of that in order to set the correct values for
11406 // face_orientation, face_flip and face_rotation,
11407 // which are inherited from the corresponding face
11408 // of the mother cube
11409 for (const unsigned int f : GeometryInfo<dim>::face_indices())
11410 for (unsigned int s = 0;
11413 ref_case, f)),
11414 1U);
11415 ++s)
11416 {
11417 const unsigned int current_child =
11419 ref_case,
11420 f,
11421 s,
11422 f_or[f],
11423 f_fl[f],
11424 f_ro[f],
11426 ref_case, f, f_or[f], f_fl[f], f_ro[f]));
11427 new_hexes[current_child]->set_combined_face_orientation(
11428 f, f_co[f]);
11429 }
11430
11431 // now see if we have created cells that are
11432 // distorted and if so add them to our list
11433 if (check_for_distorted_cells &&
11434 has_distorted_children<dim, spacedim>(hex))
11435 cells_with_distorted_children.distorted_cells.push_back(
11436 hex);
11437
11438 // note that the refinement flag was already cleared
11439 // at the beginning of this loop
11440
11441 // inform all listeners that cell refinement is done
11442 triangulation.signals.post_refinement_on_cell(hex);
11443 }
11444 }
11445
11446 // clear user data on quads. we used some of this data to
11447 // indicate anisotropic refinemnt cases on faces. all data
11448 // should be cleared by now, but the information whether we
11449 // used indices or pointers is still present. reset it now to
11450 // enable the user to use whichever they like later on.
11451 triangulation.faces->quads.clear_user_data();
11452
11453 // return the list with distorted children
11454 return cells_with_distorted_children;
11455 }
11456
11457
11470 template <int spacedim>
11471 static void
11474
11475
11476
11477 template <int dim, int spacedim>
11478 static void
11481 {
11482 // If the codimension is one, we cannot perform this check
11483 // yet.
11484 if (spacedim > dim)
11485 return;
11486
11487 for (const auto &cell : triangulation.cell_iterators())
11488 if (cell->at_boundary() && cell->refine_flag_set() &&
11489 cell->refine_flag_set() !=
11491 {
11492 // The cell is at the boundary and it is flagged for
11493 // anisotropic refinement. Therefore, we have a closer
11494 // look
11495 const RefinementCase<dim> ref_case = cell->refine_flag_set();
11496 for (const unsigned int face_no :
11498 if (cell->face(face_no)->at_boundary())
11499 {
11500 // this is the critical face at the boundary.
11502 face_no) !=
11504 {
11505 // up to now, we do not want to refine this
11506 // cell along the face under consideration
11507 // here.
11508 const typename Triangulation<dim,
11509 spacedim>::face_iterator
11510 face = cell->face(face_no);
11511 // the new point on the boundary would be this
11512 // one.
11513 const Point<spacedim> new_bound = face->center(true);
11514 // to check it, transform to the unit cell
11515 // with a linear mapping
11516 const Point<dim> new_unit =
11517 cell->reference_cell()
11518 .template get_default_linear_mapping<dim,
11519 spacedim>()
11520 .transform_real_to_unit_cell(cell, new_bound);
11521
11522 // Now, we have to calculate the distance from
11523 // the face in the unit cell.
11524
11525 // take the correct coordinate direction (0
11526 // for faces 0 and 1, 1 for faces 2 and 3, 2
11527 // for faces 4 and 5) and subtract the correct
11528 // boundary value of the face (0 for faces 0,
11529 // 2, and 4; 1 for faces 1, 3 and 5)
11530 const double dist =
11531 std::fabs(new_unit[face_no / 2] - face_no % 2);
11532
11533 // compare this with the empirical value
11534 // allowed. if it is too big, flag the face
11535 // for isotropic refinement
11536 const double allowed = 0.25;
11537
11538 if (dist > allowed)
11539 cell->flag_for_face_refinement(face_no);
11540 } // if flagged for anistropic refinement
11541 } // if (cell->face(face)->at_boundary())
11542 } // for all cells
11543 }
11544
11545
11558 template <int dim, int spacedim>
11559 static void
11561 {
11562 Assert(dim < 3,
11563 ExcMessage("Wrong function called -- there should "
11564 "be a specialization."));
11565 }
11566
11567
11568 template <int spacedim>
11569 static void
11572 {
11573 const unsigned int dim = 3;
11574 using raw_line_iterator =
11576
11577 // variable to store whether the mesh was changed in the
11578 // present loop and in the whole process
11579 bool mesh_changed = false;
11580
11581 do
11582 {
11583 mesh_changed = false;
11584
11585 // for this following, we need to know which cells are
11586 // going to be coarsened, if we had to make a
11587 // decision. the following function sets these flags:
11588 triangulation.fix_coarsen_flags();
11589
11590 // first clear flags on lines, since we need them to determine
11591 // which lines will be refined
11592 triangulation.clear_user_flags_line();
11593
11594 // flag those lines that are refined and will not be
11595 // coarsened and those that will be refined
11596 for (const auto &cell : triangulation.cell_iterators())
11597 if (cell->refine_flag_set())
11598 {
11599 const std::array<unsigned int, 12> line_indices =
11600 TriaAccessorImplementation::Implementation::
11601 get_line_indices_of_cell(*cell);
11602 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11604 cell->refine_flag_set(), l) ==
11606 {
11607 raw_line_iterator line(&triangulation,
11608 0,
11609 line_indices[l]);
11610 // flag a line, that will be refined
11611 line->set_user_flag();
11612 }
11613 }
11614 else if (cell->has_children() &&
11615 !cell->child(0)->coarsen_flag_set())
11616 {
11617 const std::array<unsigned int, 12> line_indices =
11618 TriaAccessorImplementation::Implementation::
11619 get_line_indices_of_cell(*cell);
11620 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11622 cell->refinement_case(), l) ==
11624 {
11625 raw_line_iterator line(&triangulation,
11626 0,
11627 line_indices[l]);
11628 // flag a line, that is refined and will stay so
11629 line->set_user_flag();
11630 }
11631 }
11632 else if (cell->has_children() &&
11633 cell->child(0)->coarsen_flag_set())
11634 cell->set_user_flag();
11635
11636
11637 // now check whether there are cells with lines that are
11638 // more than once refined or that will be more than once
11639 // refined. The first thing should never be the case, in
11640 // the second case we flag the cell for refinement
11642 cell = triangulation.last_active();
11643 cell != triangulation.end();
11644 --cell)
11645 {
11646 const std::array<unsigned int, 12> line_indices =
11647 TriaAccessorImplementation::Implementation::
11648 get_line_indices_of_cell(*cell);
11649 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11650 {
11651 raw_line_iterator line(&triangulation, 0, line_indices[l]);
11652 if (line->has_children())
11653 {
11654 // if this line is refined, its children should
11655 // not have further children
11656 //
11657 // however, if any of the children is flagged
11658 // for further refinement, we need to refine
11659 // this cell also (at least, if the cell is not
11660 // already flagged)
11661 bool offending_line_found = false;
11662
11663 for (unsigned int c = 0; c < 2; ++c)
11664 {
11665 Assert(line->child(c)->has_children() == false,
11667
11668 if (line->child(c)->user_flag_set() &&
11670 cell->refine_flag_set(), l) ==
11672 {
11673 // tag this cell for refinement
11674 cell->clear_coarsen_flag();
11675 // if anisotropic coarsening is allowed:
11676 // extend the refine_flag in the needed
11677 // direction, else set refine_flag
11678 // (isotropic)
11679 if (triangulation.smooth_grid &
11681 allow_anisotropic_smoothing)
11682 cell->flag_for_line_refinement(l);
11683 else
11684 cell->set_refine_flag();
11685
11686 for (unsigned int k = 0; k < cell->n_lines();
11687 ++k)
11689 cell->refine_flag_set(), l) ==
11691 // flag a line, that will be refined
11692 raw_line_iterator(&triangulation,
11693 0,
11694 line_indices[k])
11695 ->set_user_flag();
11696
11697 // note that we have changed the grid
11698 offending_line_found = true;
11699
11700 // it may save us several loop
11701 // iterations if we flag all lines of
11702 // this cell now (and not at the outset
11703 // of the next iteration) for refinement
11704 for (unsigned int k = 0; k < cell->n_lines();
11705 ++k)
11706 {
11707 const auto line =
11708 raw_line_iterator(&triangulation,
11709 0,
11710 line_indices[k]);
11711 if (!line->has_children() &&
11713 line_refinement_case(
11714 cell->refine_flag_set(), k) !=
11716 line->set_user_flag();
11717 }
11718
11719 break;
11720 }
11721 }
11722
11723 if (offending_line_found)
11724 {
11725 mesh_changed = true;
11726 break;
11727 }
11728 }
11729 }
11730 }
11731
11732
11733 // there is another thing here: if any of the lines will
11734 // be refined, then we may not coarsen the present cell
11735 // similarly, if any of the lines *is* already refined, we
11736 // may not coarsen the current cell. however, there's a
11737 // catch: if the line is refined, but the cell behind it
11738 // is going to be coarsened, then the situation
11739 // changes. if we forget this second condition, the
11740 // refine_and_coarsen_3d test will start to fail. note
11741 // that to know which cells are going to be coarsened, the
11742 // call for fix_coarsen_flags above is necessary
11744 triangulation.last();
11745 cell != triangulation.end();
11746 --cell)
11747 if (cell->user_flag_set())
11748 {
11749 const std::array<unsigned int, 12> line_indices =
11750 TriaAccessorImplementation::Implementation::
11751 get_line_indices_of_cell(*cell);
11752 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11753 {
11754 raw_line_iterator line(&triangulation,
11755 0,
11756 line_indices[l]);
11757 if (line->has_children() &&
11758 (line->child(0)->user_flag_set() ||
11759 line->child(1)->user_flag_set()))
11760 {
11761 for (unsigned int c = 0; c < cell->n_children(); ++c)
11762 cell->child(c)->clear_coarsen_flag();
11763 cell->clear_user_flag();
11764 for (unsigned int k = 0; k < cell->n_lines(); ++k)
11766 cell->refinement_case(), k) ==
11768 // flag a line, that is refined and will
11769 // stay so
11770 raw_line_iterator(&triangulation,
11771 0,
11772 line_indices[k])
11773 ->set_user_flag();
11774 mesh_changed = true;
11775 break;
11776 }
11777 }
11778 }
11779 }
11780 while (mesh_changed == true);
11781 }
11782
11783
11784
11791 template <int dim, int spacedim>
11792 static bool
11795 {
11796 // in 1d, coarsening is always allowed since we don't enforce
11797 // the 2:1 constraint there
11798 if (dim == 1)
11799 return true;
11800
11801 const RefinementCase<dim> ref_case = cell->refinement_case();
11802 for (const unsigned int n : GeometryInfo<dim>::face_indices())
11803 {
11804 // if the cell is not refined along that face, coarsening
11805 // will not change anything, so do nothing. the same
11806 // applies, if the face is at the boundary
11807 const RefinementCase<dim - 1> face_ref_case =
11808 GeometryInfo<dim>::face_refinement_case(cell->refinement_case(),
11809 n);
11810
11811 const unsigned int n_subfaces =
11812 GeometryInfo<dim - 1>::n_children(face_ref_case);
11813
11814 if (n_subfaces == 0 || cell->at_boundary(n))
11815 continue;
11816 for (unsigned int c = 0; c < n_subfaces; ++c)
11817 {
11819 child = cell->child(
11821
11823 child_neighbor = child->neighbor(n);
11824 if (!child->neighbor_is_coarser(n))
11825 {
11826 // in 2d, if the child's neighbor is coarser, then it has
11827 // no children. however, in 3d it might be
11828 // otherwise. consider for example, that our face might be
11829 // refined with cut_x, but the neighbor is refined with
11830 // cut_xy at that face. then the neighbor pointers of the
11831 // children of our cell will point to the common neighbor
11832 // cell, not to its children. what we really want to know
11833 // in the following is, whether the neighbor cell is
11834 // refined twice with reference to our cell. that only
11835 // has to be asked, if the child's neighbor is not a
11836 // coarser one. we check whether some of the children on
11837 // the neighbor are not flagged for coarsening, in that
11838 // case we may not coarsen. it is enough to check the
11839 // first child because we have already fixed the coarsen
11840 // flags on finer levels
11841 if (child_neighbor->has_children() &&
11842 !(child_neighbor->child(0)->is_active() &&
11843 child_neighbor->child(0)->coarsen_flag_set()))
11844 return false;
11845
11846 // the same applies, if the neighbors children are not
11847 // refined but will be after refinement
11848 if (child_neighbor->refine_flag_set())
11849 return false;
11850 }
11851 }
11852 }
11853 return true;
11854 }
11855 };
11856
11857
11862 {
11863 template <int spacedim>
11864 static void
11867
11868 template <int dim, int spacedim>
11870 {
11871 std::vector<std::pair<unsigned int, unsigned int>> adjacent_cells(
11872 2 * triangulation.n_raw_faces(),
11873 {numbers::invalid_unsigned_int, numbers::invalid_unsigned_int});
11874
11875 const auto set_entry = [&](const auto &face_index, const auto &cell) {
11876 const std::pair<unsigned int, unsigned int> cell_pair = {
11877 cell->level(), cell->index()};
11878 unsigned int index;
11879
11880 if (adjacent_cells[2 * face_index].first ==
11882 adjacent_cells[2 * face_index].second ==
11884 {
11885 index = 2 * face_index + 0;
11886 }
11887 else
11888 {
11889 Assert(((adjacent_cells[2 * face_index + 1].first ==
11891 (adjacent_cells[2 * face_index + 1].second ==
11894 index = 2 * face_index + 1;
11895 }
11896
11897 adjacent_cells[index] = cell_pair;
11898 };
11899
11900 const auto get_entry =
11901 [&](const auto &face_index,
11902 const auto &cell) -> TriaIterator<CellAccessor<dim, spacedim>> {
11903 auto test = adjacent_cells[2 * face_index];
11904
11905 if (test == std::pair<unsigned int, unsigned int>(cell->level(),
11906 cell->index()))
11907 test = adjacent_cells[2 * face_index + 1];
11908
11909 if ((test.first != numbers::invalid_unsigned_int) &&
11910 (test.second != numbers::invalid_unsigned_int))
11912 test.first,
11913 test.second);
11914 else
11916 };
11917
11918 for (const auto &cell : triangulation.cell_iterators())
11919 for (const auto &face : cell->face_iterators())
11920 {
11921 set_entry(face->index(), cell);
11922
11923 if (cell->is_active() && face->has_children())
11924 for (unsigned int c = 0; c < face->n_children(); ++c)
11925 set_entry(face->child(c)->index(), cell);
11926 }
11927
11928 for (const auto &cell : triangulation.cell_iterators())
11929 for (auto f : cell->face_indices())
11930 cell->set_neighbor(f, get_entry(cell->face(f)->index(), cell));
11931 }
11932
11933 template <int dim, int spacedim>
11934 static void
11936 Triangulation<dim, spacedim> & /*triangulation*/,
11938 std::vector<unsigned int> & /*line_cell_count*/,
11939 std::vector<unsigned int> & /*quad_cell_count*/)
11940 {
11942 }
11943
11944 template <int dim, int spacedim>
11947 const bool check_for_distorted_cells)
11948 {
11949 return Implementation::execute_refinement_isotropic(
11950 triangulation, check_for_distorted_cells);
11951 }
11952
11953 template <int dim, int spacedim>
11954 static void
11956 Triangulation<dim, spacedim> & /*triangulation*/)
11957 {
11958 // nothing to do since anisotropy is not supported
11959 }
11960
11961 template <int dim, int spacedim>
11962 static void
11965 {
11966 Implementation::prepare_refinement_dim_dependent(triangulation);
11967 }
11968
11969 template <int dim, int spacedim>
11970 static bool
11973 {
11975
11976 return false;
11977 }
11978 };
11979
11980
11981 template <int dim, int spacedim>
11984 {
11985 static const FlatManifold<dim, spacedim> flat_manifold;
11986 return flat_manifold;
11987 }
11988 } // namespace TriangulationImplementation
11989} // namespace internal
11990
11991#ifndef DOXYGEN
11992
11993template <int dim, int spacedim>
11996
11997
11998
11999template <int dim, int spacedim>
12002 const MeshSmoothing smooth_grid,
12003 const bool check_for_distorted_cells)
12004 : cell_attached_data({0, 0, {}, {}})
12005 , smooth_grid(smooth_grid)
12006 , anisotropic_refinement(false)
12007 , check_for_distorted_cells(check_for_distorted_cells)
12008{
12009 if (dim == 1)
12010 {
12011 vertex_to_boundary_id_map_1d =
12012 std::make_unique<std::map<unsigned int, types::boundary_id>>();
12013 vertex_to_manifold_id_map_1d =
12014 std::make_unique<std::map<unsigned int, types::manifold_id>>();
12015 }
12016
12017 // connect the any_change signal to the other top level signals
12018 signals.create.connect(signals.any_change);
12019 signals.post_refinement.connect(signals.any_change);
12020 signals.clear.connect(signals.any_change);
12021 signals.mesh_movement.connect(signals.any_change);
12022}
12023
12024
12025
12026template <int dim, int spacedim>
12029 Triangulation<dim, spacedim> &&tria) noexcept
12030 : EnableObserverPointer(std::move(tria))
12031 , smooth_grid(tria.smooth_grid)
12032 , reference_cells(std::move(tria.reference_cells))
12033 , periodic_face_pairs_level_0(std::move(tria.periodic_face_pairs_level_0))
12034 , periodic_face_map(std::move(tria.periodic_face_map))
12035 , levels(std::move(tria.levels))
12036 , faces(std::move(tria.faces))
12037 , vertices(std::move(tria.vertices))
12038 , vertices_used(std::move(tria.vertices_used))
12039 , manifolds(std::move(tria.manifolds))
12040 , anisotropic_refinement(tria.anisotropic_refinement)
12041 , check_for_distorted_cells(tria.check_for_distorted_cells)
12042 , number_cache(std::move(tria.number_cache))
12043 , vertex_to_boundary_id_map_1d(std::move(tria.vertex_to_boundary_id_map_1d))
12044 , vertex_to_manifold_id_map_1d(std::move(tria.vertex_to_manifold_id_map_1d))
12045{
12047
12048 if (tria.policy)
12049 this->policy = tria.policy->clone();
12050}
12051
12052
12053template <int dim, int spacedim>
12056 Triangulation<dim, spacedim> &&tria) noexcept
12057{
12058 EnableObserverPointer::operator=(std::move(tria));
12059
12060 smooth_grid = tria.smooth_grid;
12061 reference_cells = std::move(tria.reference_cells);
12062 periodic_face_pairs_level_0 = std::move(tria.periodic_face_pairs_level_0);
12063 periodic_face_map = std::move(tria.periodic_face_map);
12064 levels = std::move(tria.levels);
12065 faces = std::move(tria.faces);
12066 vertices = std::move(tria.vertices);
12067 vertices_used = std::move(tria.vertices_used);
12068 manifolds = std::move(tria.manifolds);
12069 anisotropic_refinement = tria.anisotropic_refinement;
12070 number_cache = tria.number_cache;
12071 vertex_to_boundary_id_map_1d = std::move(tria.vertex_to_boundary_id_map_1d);
12072 vertex_to_manifold_id_map_1d = std::move(tria.vertex_to_manifold_id_map_1d);
12073
12075
12076 if (tria.policy)
12077 this->policy = tria.policy->clone();
12078
12079 return *this;
12080}
12081
12082
12083
12084template <int dim, int spacedim>
12087{
12088 // notify listeners that the triangulation is going down...
12089 try
12090 {
12091 signals.clear();
12092 }
12093 catch (...)
12094 {}
12095
12096 levels.clear();
12097
12098 // the vertex_to_boundary_id_map_1d field should be unused except in
12099 // 1d. double check this here, as destruction is a good place to
12100 // ensure that what we've done over the course of the lifetime of
12101 // this object makes sense
12102 AssertNothrow((dim == 1) || (vertex_to_boundary_id_map_1d == nullptr),
12104
12105 // the vertex_to_manifold_id_map_1d field should be also unused
12106 // except in 1d. check this as well
12107 AssertNothrow((dim == 1) || (vertex_to_manifold_id_map_1d == nullptr),
12109}
12110
12111
12112
12113template <int dim, int spacedim>
12116{
12117 // notify listeners that the triangulation is going down...
12118 signals.clear();
12119
12120 // ...and then actually clear all content of it
12121 clear_despite_subscriptions();
12122 periodic_face_pairs_level_0.clear();
12123 periodic_face_map.clear();
12124 reference_cells.clear();
12125
12126 cell_attached_data = {0, 0, {}, {}};
12127 data_serializer.clear();
12128}
12129
12130template <int dim, int spacedim>
12133{
12134 return MPI_COMM_SELF;
12135}
12136
12137
12138
12139template <int dim, int spacedim>
12142{
12143 return get_mpi_communicator();
12144}
12145
12146
12147
12148template <int dim, int spacedim>
12150std::weak_ptr<const Utilities::MPI::Partitioner> Triangulation<dim, spacedim>::
12152{
12153 return number_cache.active_cell_index_partitioner;
12154}
12155
12156
12157
12158template <int dim, int spacedim>
12160std::weak_ptr<const Utilities::MPI::Partitioner> Triangulation<dim, spacedim>::
12161 global_level_cell_index_partitioner(const unsigned int level) const
12162{
12163 AssertIndexRange(level, this->n_levels());
12164
12165 return number_cache.level_cell_index_partitioners[level];
12166}
12167
12168
12169
12170template <int dim, int spacedim>
12173 const MeshSmoothing mesh_smoothing)
12174{
12175 smooth_grid = mesh_smoothing;
12176}
12177
12178
12179
12180template <int dim, int spacedim>
12184{
12185 return smooth_grid;
12186}
12187
12188
12189
12190template <int dim, int spacedim>
12193 const types::manifold_id m_number,
12194 const Manifold<dim, spacedim> &manifold_object)
12195{
12197
12198 manifolds[m_number] = manifold_object.clone();
12199}
12200
12201
12202
12203template <int dim, int spacedim>
12206 const types::manifold_id m_number)
12207{
12209
12210 // delete the entry located at number.
12211 manifolds[m_number] =
12213 spacedim>()
12214 .clone();
12215}
12216
12217
12218template <int dim, int spacedim>
12221{
12222 for (auto &m : manifolds)
12223 m.second = internal::TriangulationImplementation::
12224 get_default_flat_manifold<dim, spacedim>()
12225 .clone();
12226}
12227
12228
12229template <int dim, int spacedim>
12232 const types::manifold_id m_number)
12233{
12234 Assert(
12235 n_cells() > 0,
12236 ExcMessage(
12237 "Error: set_all_manifold_ids() can not be called on an empty Triangulation."));
12238
12239 for (const auto &cell : this->active_cell_iterators())
12240 cell->set_all_manifold_ids(m_number);
12241}
12242
12243
12244template <int dim, int spacedim>
12247 const types::manifold_id m_number)
12248{
12249 Assert(
12250 n_cells() > 0,
12251 ExcMessage(
12252 "Error: set_all_manifold_ids_on_boundary() can not be called on an empty Triangulation."));
12253
12254 for (const auto &cell : this->active_cell_iterators())
12255 for (auto f : GeometryInfo<dim>::face_indices())
12256 if (cell->face(f)->at_boundary())
12257 cell->face(f)->set_all_manifold_ids(m_number);
12258}
12259
12260
12261template <int dim, int spacedim>
12264 const types::boundary_id b_id,
12265 const types::manifold_id m_number)
12266{
12267 Assert(
12268 n_cells() > 0,
12269 ExcMessage(
12270 "Error: set_all_manifold_ids_on_boundary() can not be called on an empty Triangulation."));
12271
12272 [[maybe_unused]] bool boundary_found = false;
12273
12274 for (const auto &cell : this->active_cell_iterators())
12275 {
12276 // loop on faces
12277 for (auto f : GeometryInfo<dim>::face_indices())
12278 if (cell->face(f)->at_boundary() &&
12279 cell->face(f)->boundary_id() == b_id)
12280 {
12281 boundary_found = true;
12282 cell->face(f)->set_manifold_id(m_number);
12283 }
12284
12285 // loop on edges if dim >= 3
12286 if (dim >= 3)
12287 for (unsigned int e = 0; e < GeometryInfo<dim>::lines_per_cell; ++e)
12288 if (cell->line(e)->at_boundary() &&
12289 cell->line(e)->boundary_id() == b_id)
12290 {
12291 boundary_found = true;
12292 cell->line(e)->set_manifold_id(m_number);
12293 }
12294 }
12295
12296 Assert(boundary_found, ExcBoundaryIdNotFound(b_id));
12297}
12298
12299
12300
12301template <int dim, int spacedim>
12304 const types::manifold_id m_number) const
12305{
12306 // check if flat manifold has been queried
12307 if (m_number == numbers::flat_manifold_id)
12308 return internal::TriangulationImplementation::
12309 get_default_flat_manifold<dim, spacedim>();
12310
12311 // look, if there is a manifold stored at
12312 // manifold_id number.
12313 const auto it = manifolds.find(m_number);
12314
12315 if (it != manifolds.end())
12316 {
12317 // if we have found an entry, return it
12318 return *(it->second);
12319 }
12320
12321 Assert(
12322 false,
12323 ExcMessage(
12324 "No manifold of the manifold id " + std::to_string(m_number) +
12325 " has been attached to the triangulation. "
12326 "Please attach the right manifold with Triangulation::set_manifold()."));
12327
12328 return internal::TriangulationImplementation::
12329 get_default_flat_manifold<dim, spacedim>(); // never reached
12330}
12331
12332
12333
12334template <int dim, int spacedim>
12336std::vector<types::boundary_id> Triangulation<dim, spacedim>::get_boundary_ids()
12337 const
12338{
12339 std::set<types::boundary_id> boundary_ids;
12340 for (const auto &cell : active_cell_iterators())
12341 if (cell->is_locally_owned())
12342 for (const auto &face : cell->face_indices())
12343 if (cell->at_boundary(face))
12344 boundary_ids.insert(cell->face(face)->boundary_id());
12345
12346 return {boundary_ids.begin(), boundary_ids.end()};
12347}
12348
12349
12350
12351template <int dim, int spacedim>
12353std::vector<types::manifold_id> Triangulation<dim, spacedim>::get_manifold_ids()
12354 const
12355{
12356 std::set<types::manifold_id> m_ids;
12357 for (const auto &cell : active_cell_iterators())
12358 if (cell->is_locally_owned())
12359 {
12360 m_ids.insert(cell->manifold_id());
12361 for (const auto &face : cell->face_iterators())
12362 m_ids.insert(face->manifold_id());
12363 if (dim == 3)
12364 {
12365 const auto line_indices = internal::TriaAccessorImplementation::
12366 Implementation::get_line_indices_of_cell(*cell);
12367 for (unsigned int l = 0; l < cell->n_lines(); ++l)
12368 {
12369 raw_line_iterator line(this, 0, line_indices[l]);
12370 m_ids.insert(line->manifold_id());
12371 }
12372 }
12373 }
12374 return {m_ids.begin(), m_ids.end()};
12375}
12376
12377#endif
12378/*-----------------------------------------------------------------*/
12379
12380#ifndef DOXYGEN
12381
12382template <int dim, int spacedim>
12385 const Triangulation<dim, spacedim> &other_tria)
12386{
12387 Assert((vertices.empty()) && (levels.empty()) && (faces == nullptr),
12388 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
12389 Assert((other_tria.levels.size() != 0) && (other_tria.vertices.size() != 0) &&
12390 (dim == 1 || other_tria.faces != nullptr),
12391 ExcMessage(
12392 "When calling Triangulation::copy_triangulation(), "
12393 "the target triangulation must be empty but the source "
12394 "triangulation (the argument to this function) must contain "
12395 "something. Here, it seems like the source does not "
12396 "contain anything at all."));
12397
12398
12399 // copy normal elements
12400 vertices = other_tria.vertices;
12401 vertices_used = other_tria.vertices_used;
12402 anisotropic_refinement = other_tria.anisotropic_refinement;
12403 smooth_grid = other_tria.smooth_grid;
12404 reference_cells = other_tria.reference_cells;
12405
12406 if (dim > 1)
12407 faces = std::make_unique<internal::TriangulationImplementation::TriaFaces>(
12408 *other_tria.faces);
12409
12410 for (const auto &p : other_tria.manifolds)
12411 set_manifold(p.first, *p.second);
12412
12413
12414 levels.reserve(other_tria.levels.size());
12415 for (unsigned int level = 0; level < other_tria.levels.size(); ++level)
12416 levels.push_back(
12417 std::make_unique<internal::TriangulationImplementation::TriaLevel>(
12418 *other_tria.levels[level]));
12419
12420 number_cache = other_tria.number_cache;
12421
12422 if (dim == 1)
12423 {
12424 vertex_to_boundary_id_map_1d =
12425 std::make_unique<std::map<unsigned int, types::boundary_id>>(
12426 *other_tria.vertex_to_boundary_id_map_1d);
12427
12428 vertex_to_manifold_id_map_1d =
12429 std::make_unique<std::map<unsigned int, types::manifold_id>>(
12430 *other_tria.vertex_to_manifold_id_map_1d);
12431 }
12432
12433 if (other_tria.policy)
12434 this->policy = other_tria.policy->clone();
12435
12436 // periodic faces
12437 this->periodic_face_pairs_level_0.reserve(
12438 other_tria.periodic_face_pairs_level_0.size());
12439
12440 for (const auto &other_entry : other_tria.periodic_face_pairs_level_0)
12441 {
12442 auto entry = other_entry;
12443 entry.cell[0] =
12444 cell_iterator(this, entry.cell[0]->level(), entry.cell[0]->index());
12445 entry.cell[1] =
12446 cell_iterator(this, entry.cell[1]->level(), entry.cell[1]->index());
12447 periodic_face_pairs_level_0.emplace_back(entry);
12448 }
12449
12450 for (auto [first_cell_, second_cell_and_orientation] :
12451 other_tria.periodic_face_map)
12452 {
12453 auto first_cell = first_cell_; // make copy since key is const
12454 first_cell.first = cell_iterator(this,
12455 first_cell.first->level(),
12456 first_cell.first->index());
12457 second_cell_and_orientation.first.first =
12458 cell_iterator(this,
12459 second_cell_and_orientation.first.first->level(),
12460 second_cell_and_orientation.first.first->index());
12461
12462 this->periodic_face_map[first_cell] = second_cell_and_orientation;
12463 }
12464
12465 // inform those who are listening on other_tria of the copy operation
12466 other_tria.signals.copy(*this);
12467 // also inform all listeners of the current triangulation that the
12468 // triangulation has been created
12469 signals.create();
12470
12471 // note that we need not copy the
12472 // subscriptor!
12473}
12474
12475
12476
12477template <int dim, int spacedim>
12480{
12481 this->update_reference_cells();
12482
12483 if (this->all_reference_cells_are_hyper_cube())
12484 {
12485 this->policy =
12487 dim,
12488 spacedim,
12490 }
12491 else
12492 {
12493 this->policy =
12495 dim,
12496 spacedim,
12498 }
12499}
12500
12501
12502
12503template <int dim, int spacedim>
12506 const std::vector<Point<spacedim>> &v,
12507 const std::vector<CellData<dim>> &cells,
12508 const SubCellData &subcelldata)
12509{
12510 Assert((vertices.empty()) && (levels.empty()) && (faces == nullptr),
12511 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
12512 // check that no forbidden arrays
12513 // are used
12514 Assert(subcelldata.check_consistency(dim), ExcInternalError());
12515
12516 // try to create a triangulation; if this fails, we still want to
12517 // throw an exception but if we just do so we'll get into trouble
12518 // because sometimes other objects are already attached to it:
12519 try
12520 {
12522 create_triangulation(v, cells, subcelldata, *this);
12523 }
12524 catch (...)
12525 {
12526 clear_despite_subscriptions();
12527 throw;
12528 }
12529
12530 reset_policy();
12531
12532 // update our counts of the various elements of a triangulation, and set
12533 // active_cell_indices of all cells
12534 reset_cell_vertex_indices_cache();
12536 *this, levels.size(), number_cache);
12537 reset_active_cell_indices();
12538 reset_global_cell_indices();
12539
12540 // now verify that there are indeed no distorted cells. as per the
12541 // documentation of this class, we first collect all distorted cells
12542 // and then throw an exception if there are any
12543 if (check_for_distorted_cells)
12544 {
12545 DistortedCellList distorted_cells = collect_distorted_coarse_cells(*this);
12546 // throw the array (and fill the various location fields) if
12547 // there are distorted cells. otherwise, just fall off the end
12548 // of the function
12549 AssertThrow(distorted_cells.distorted_cells.empty(), distorted_cells);
12550 }
12551
12552
12553 /*
12554 When the triangulation is a manifold (dim < spacedim) and made of
12555 quadrilaterals, the normal field provided from the map class depends on
12556 the order of the vertices. It may happen that this normal field is
12557 discontinuous. The following code takes care that this is not the case by
12558 setting the cell direction flag on those cell that produce the wrong
12559 orientation.
12560
12561 To determine if 2 neighbors have the same or opposite orientation we use
12562 a truth table. Its entries are indexed by the local indices of the
12563 common face. For example if two elements share a face, and this face is
12564 face 0 for element 0 and face 1 for element 1, then table(0,1) will tell
12565 whether the orientation are the same (true) or opposite (false).
12566
12567 Even though there may be a combinatorial/graph theory argument to get this
12568 table in any dimension, I tested by hand all the different possible cases
12569 in 1D and 2D to generate the table.
12570
12571 Assuming that a surface respects the standard orientation for 2d meshes,
12572 the truth tables are symmetric and their true values are the following
12573
12574 - 1D curves: (0,1)
12575 - 2D surface: (0,1),(0,2),(1,3),(2,3)
12576
12577 We store this data using an n_faces x n_faces full matrix, which is
12578 actually much bigger than the minimal data required, but it makes the code
12579 more readable.
12580
12581 */
12582 if ((dim == spacedim - 1) && all_reference_cells_are_hyper_cube())
12583 {
12586 switch (dim)
12587 {
12588 case 1:
12589 {
12590 const bool values[][2] = {{false, true}, {true, false}};
12591 for (const unsigned int i : GeometryInfo<dim>::face_indices())
12592 for (const unsigned int j : GeometryInfo<dim>::face_indices())
12593 correct(i, j) = values[i][j];
12594 break;
12595 }
12596 case 2:
12597 {
12598 const bool values[][4] = {{false, true, true, false},
12599 {true, false, false, true},
12600 {true, false, false, true},
12601 {false, true, true, false}};
12602 for (const unsigned int i : GeometryInfo<dim>::face_indices())
12603 for (const unsigned int j : GeometryInfo<dim>::face_indices())
12604 correct(i, j) = (values[i][j]);
12605 break;
12606 }
12607 default:
12609 }
12610
12611
12612 std::list<active_cell_iterator> this_round, next_round;
12613 active_cell_iterator neighbor;
12614
12615 // Start with the first cell and (arbitrarily) decide that its
12616 // direction flag should be 'true':
12617 this_round.push_back(begin_active());
12618 begin_active()->set_direction_flag(true);
12619 begin_active()->set_user_flag();
12620
12621 while (this_round.size() > 0)
12622 {
12623 for (const auto &cell : this_round)
12624 {
12625 for (const unsigned int i : cell->face_indices())
12626 {
12627 if (cell->face(i)->at_boundary() == false)
12628 {
12629 // Consider the i'th neighbor of a cell for
12630 // which we have already set the direction:
12631 neighbor = cell->neighbor(i);
12632
12633 const unsigned int nb_of_nb =
12634 cell->neighbor_of_neighbor(i);
12635
12636 // If we already saw this neighboring cell,
12637 // check that everything is fine:
12638 if (neighbor->user_flag_set())
12639 {
12640 Assert(
12641 !(correct(i, nb_of_nb) ^
12642 (neighbor->direction_flag() ==
12643 cell->direction_flag())),
12644 ExcMessage(
12645 "The triangulation you are trying to create is not orientable."));
12646 }
12647 else
12648 {
12649 // We had not seen this cell yet. Set its
12650 // orientation flag (if necessary), mark it
12651 // as treated via the user flag, and push it
12652 // onto the list of cells to start work from
12653 // the next time around:
12654 if (correct(i, nb_of_nb) ^
12655 (neighbor->direction_flag() ==
12656 cell->direction_flag()))
12657 neighbor->set_direction_flag(
12658 !neighbor->direction_flag());
12659 neighbor->set_user_flag();
12660 next_round.push_back(neighbor);
12661 }
12662 }
12663 }
12664 }
12665
12666 // Before we quit let's check that if the triangulation is
12667 // disconnected that we still get all cells by starting
12668 // again from the first cell we haven't treated yet -- that
12669 // is, the first cell of the next disconnected component we
12670 // had not yet touched.
12671 if (next_round.empty())
12672 for (const auto &cell : this->active_cell_iterators())
12673 if (cell->user_flag_set() == false)
12674 {
12675 next_round.push_back(cell);
12676 cell->set_direction_flag(true);
12677 cell->set_user_flag();
12678 break;
12679 }
12680
12681 // Go on to the next round:
12682 next_round.swap(this_round);
12683 next_round.clear();
12684 }
12685 clear_user_flags();
12686 }
12687
12688 this->update_cell_relations();
12689
12690 // inform all listeners that the triangulation has been created
12691 signals.create();
12692}
12693
12694
12695
12696template <int dim, int spacedim>
12700{
12701 // 1) create coarse grid
12703 construction_data.coarse_cells,
12704 SubCellData());
12705
12706 // create a copy of cell_infos such that we can sort them
12707 auto cell_infos = construction_data.cell_infos;
12708
12709 // sort cell_infos on each level separately
12710 for (auto &cell_info : cell_infos)
12711 std::sort(
12712 cell_info.begin(),
12713 cell_info.end(),
12716 const CellId a_id(a.id);
12717 const CellId b_id(b.id);
12718
12719 const auto a_coarse_cell_index =
12720 this->coarse_cell_id_to_coarse_cell_index(a_id.get_coarse_cell_id());
12721 const auto b_coarse_cell_index =
12722 this->coarse_cell_id_to_coarse_cell_index(b_id.get_coarse_cell_id());
12723
12724 // according to their coarse-cell index and if that is
12725 // same according to their cell id (the result is that
12726 // cells on each level are sorted according to their
12727 // index on that level - what we need in the following
12728 // operations)
12729 if (a_coarse_cell_index != b_coarse_cell_index)
12730 return a_coarse_cell_index < b_coarse_cell_index;
12731 else
12732 return a_id < b_id;
12733 });
12734
12735 // 2) create all levels via a sequence of refinements. note that
12736 // we must make sure that we actually have cells on this level,
12737 // which is not clear in a parallel context for some processes
12738 for (unsigned int level = 0;
12739 level < cell_infos.size() && !cell_infos[level].empty();
12740 ++level)
12741 {
12742 // a) set manifold ids here (because new vertices have to be
12743 // positioned correctly during each refinement step)
12744 {
12745 auto cell = this->begin(level);
12746 auto cell_info = cell_infos[level].begin();
12747 for (; cell_info != cell_infos[level].end(); ++cell_info)
12748 {
12749 while (cell_info->id != cell->id().template to_binary<dim>())
12750 ++cell;
12751 if (dim == 2)
12752 for (const auto face : cell->face_indices())
12753 cell->face(face)->set_manifold_id(
12754 cell_info->manifold_line_ids[face]);
12755 else if (dim == 3)
12756 {
12757 for (const auto face : cell->face_indices())
12758 cell->face(face)->set_manifold_id(
12759 cell_info->manifold_quad_ids[face]);
12760
12761 const auto line_indices = internal::TriaAccessorImplementation::
12762 Implementation::get_line_indices_of_cell(*cell);
12763 for (unsigned int l = 0; l < cell->n_lines(); ++l)
12764 {
12765 raw_line_iterator line(this, 0, line_indices[l]);
12766 line->set_manifold_id(cell_info->manifold_line_ids[l]);
12767 }
12768 }
12769
12770 cell->set_manifold_id(cell_info->manifold_id);
12771 }
12772 }
12773
12774 // b) perform refinement on all levels but on the finest
12775 if (level + 1 != cell_infos.size())
12776 {
12777 // find cells that should have children and mark them for
12778 // refinement
12779 auto coarse_cell = this->begin(level);
12780 auto fine_cell_info = cell_infos[level + 1].begin();
12781
12782 // loop over all cells on the next level
12783 for (; fine_cell_info != cell_infos[level + 1].end();
12784 ++fine_cell_info)
12785 {
12786 // find the parent of that cell
12787 while (
12788 !coarse_cell->id().is_parent_of(CellId(fine_cell_info->id)))
12789 ++coarse_cell;
12790
12791 // set parent for refinement
12792 coarse_cell->set_refine_flag();
12793 }
12794
12795 // execute refinement
12796 ::Triangulation<dim,
12797 spacedim>::execute_coarsening_and_refinement();
12798 }
12799 }
12800
12801 // 3) set boundary ids
12802 for (unsigned int level = 0;
12803 level < cell_infos.size() && !cell_infos[level].empty();
12804 ++level)
12805 {
12806 auto cell = this->begin(level);
12807 auto cell_info = cell_infos[level].begin();
12808 for (; cell_info != cell_infos[level].end(); ++cell_info)
12809 {
12810 // find cell that has the correct cell
12811 while (cell_info->id != cell->id().template to_binary<dim>())
12812 ++cell;
12813
12814 // boundary ids
12815 for (auto pair : cell_info->boundary_ids)
12816 if (cell->face(pair.first)->at_boundary())
12817 cell->face(pair.first)->set_boundary_id(pair.second);
12818 }
12819 }
12820
12821 // inform all listeners that the triangulation has been created
12822 signals.create();
12823}
12824
12825
12826template <int dim, int spacedim>
12829{
12830 AssertThrow(dim + 1 == spacedim,
12831 ExcMessage(
12832 "This function can only be called if dim == spacedim-1."));
12833 for (const auto &cell : this->active_cell_iterators())
12834 cell->set_direction_flag(!cell->direction_flag());
12835}
12836
12837
12838
12839template <int dim, int spacedim>
12842{
12843 Assert(n_cells() > 0,
12844 ExcMessage("Error: An empty Triangulation can not be refined."));
12845
12846 for (const auto &cell : this->active_cell_iterators())
12847 {
12848 cell->clear_coarsen_flag();
12849 cell->set_refine_flag();
12850 cell->set_refine_choice();
12851 }
12852}
12853
12854
12855
12856template <int dim, int spacedim>
12858void Triangulation<dim, spacedim>::refine_global(const unsigned int times)
12859{
12860 for (unsigned int i = 0; i < times; ++i)
12861 {
12862 set_all_refine_flags();
12863 execute_coarsening_and_refinement();
12864 }
12865}
12866
12867
12868
12869template <int dim, int spacedim>
12871void Triangulation<dim, spacedim>::coarsen_global(const unsigned int times)
12872{
12873 for (unsigned int i = 0; i < times; ++i)
12874 {
12875 for (const auto &cell : this->active_cell_iterators())
12876 {
12877 cell->clear_refine_flag();
12878 cell->set_coarsen_flag();
12879 }
12880 execute_coarsening_and_refinement();
12881 }
12882}
12883
12884
12885#endif
12886/*-------------------- refine/coarsen flags -------------------------*/
12887
12888#ifndef DOXYGEN
12889
12890template <int dim, int spacedim>
12892void Triangulation<dim, spacedim>::save_refine_flags(std::vector<bool> &v) const
12893{
12894 v.resize(dim * n_active_cells(), false);
12895 std::vector<bool>::iterator i = v.begin();
12896
12897 for (const auto &cell : this->active_cell_iterators())
12898 for (unsigned int j = 0; j < dim; ++j, ++i)
12899 if (cell->refine_flag_set() & (1 << j))
12900 *i = true;
12901
12902 Assert(i == v.end(), ExcInternalError());
12903}
12904
12905
12906
12907template <int dim, int spacedim>
12909void Triangulation<dim, spacedim>::save_refine_flags(std::ostream &out) const
12910{
12911 std::vector<bool> v;
12912 save_refine_flags(v);
12913 write_bool_vector(mn_tria_refine_flags_begin,
12914 v,
12916 out);
12917}
12918
12919
12920
12921template <int dim, int spacedim>
12924{
12925 std::vector<bool> v;
12926 read_bool_vector(mn_tria_refine_flags_begin, v, mn_tria_refine_flags_end, in);
12927 load_refine_flags(v);
12928}
12929
12930
12931
12932template <int dim, int spacedim>
12934void Triangulation<dim, spacedim>::load_refine_flags(const std::vector<bool> &v)
12935{
12936 AssertThrow(v.size() == dim * n_active_cells(), ExcGridReadError());
12937
12938 std::vector<bool>::const_iterator i = v.begin();
12939 for (const auto &cell : this->active_cell_iterators())
12940 {
12941 unsigned int ref_case = 0;
12942
12943 for (unsigned int j = 0; j < dim; ++j, ++i)
12944 if (*i == true)
12945 ref_case += 1 << j;
12947 ExcGridReadError());
12948 if (ref_case > 0)
12949 cell->set_refine_flag(RefinementCase<dim>(ref_case));
12950 else
12951 cell->clear_refine_flag();
12952 }
12953
12954 Assert(i == v.end(), ExcInternalError());
12955}
12956
12957
12958
12959template <int dim, int spacedim>
12962 std::vector<bool> &v) const
12963{
12964 v.resize(n_active_cells(), false);
12965 std::vector<bool>::iterator i = v.begin();
12966 for (const auto &cell : this->active_cell_iterators())
12967 {
12968 *i = cell->coarsen_flag_set();
12969 ++i;
12970 }
12971
12972 Assert(i == v.end(), ExcInternalError());
12973}
12974
12975
12976
12977template <int dim, int spacedim>
12979void Triangulation<dim, spacedim>::save_coarsen_flags(std::ostream &out) const
12980{
12981 std::vector<bool> v;
12982 save_coarsen_flags(v);
12983 write_bool_vector(mn_tria_coarsen_flags_begin,
12984 v,
12986 out);
12987}
12988
12989
12990
12991template <int dim, int spacedim>
12994{
12995 std::vector<bool> v;
12996 read_bool_vector(mn_tria_coarsen_flags_begin,
12997 v,
12999 in);
13000 load_coarsen_flags(v);
13001}
13002
13003
13004
13005template <int dim, int spacedim>
13008 const std::vector<bool> &v)
13009{
13010 Assert(v.size() == n_active_cells(), ExcGridReadError());
13011
13012 std::vector<bool>::const_iterator i = v.begin();
13013 for (const auto &cell : this->active_cell_iterators())
13014 {
13015 if (*i == true)
13016 cell->set_coarsen_flag();
13017 else
13018 cell->clear_coarsen_flag();
13019 ++i;
13020 }
13021
13022 Assert(i == v.end(), ExcInternalError());
13023}
13024
13025
13026template <int dim, int spacedim>
13029{
13030 return anisotropic_refinement;
13031}
13032
13033
13034#endif
13035
13036namespace internal
13037{
13038 namespace
13039 {
13040 std::vector<std::vector<bool>>
13041 extract_raw_coarsen_flags(
13042 const std::vector<std::unique_ptr<
13044 {
13045 std::vector<std::vector<bool>> coarsen_flags(levels.size());
13046 for (unsigned int level = 0; level < levels.size(); ++level)
13047 coarsen_flags[level] = levels[level]->coarsen_flags;
13048 return coarsen_flags;
13049 }
13050
13051 std::vector<std::vector<std::uint8_t>>
13052 extract_raw_refine_flags(
13053 const std::vector<std::unique_ptr<
13055 {
13056 std::vector<std::vector<std::uint8_t>> refine_flags(levels.size());
13057 for (unsigned int level = 0; level < levels.size(); ++level)
13058 refine_flags[level] = levels[level]->refine_flags;
13059 return refine_flags;
13060 }
13061 } // namespace
13062} // namespace internal
13063
13064
13065/*-------------------- user data/flags -------------------------*/
13066
13067
13068namespace
13069{
13070 // clear user data of cells
13071 void
13072 clear_user_data(std::vector<std::unique_ptr<
13074 {
13075 for (auto &level : levels)
13076 level->cells.clear_user_data();
13077 }
13078
13079
13080 // clear user data of faces
13081 void
13083 {
13084 if (faces->dim == 2)
13085 {
13086 faces->lines.clear_user_data();
13087 }
13088
13089
13090 if (faces->dim == 3)
13091 {
13092 faces->lines.clear_user_data();
13093 faces->quads.clear_user_data();
13094 }
13095 }
13096} // namespace
13097
13098#ifndef DOXYGEN
13099
13100template <int dim, int spacedim>
13103{
13104 // let functions in anonymous namespace do their work
13105 ::clear_user_data(levels);
13106 if (dim > 1)
13107 ::clear_user_data(faces.get());
13108}
13109
13110
13111
13112namespace
13113{
13114 void
13115 clear_user_flags_line(
13116 unsigned int dim,
13117 std::vector<
13118 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
13119 &levels,
13121 {
13122 if (dim == 1)
13123 {
13124 for (const auto &level : levels)
13125 level->cells.clear_user_flags();
13126 }
13127 else if (dim == 2 || dim == 3)
13128 {
13129 faces->lines.clear_user_flags();
13130 }
13131 else
13132 {
13134 }
13135 }
13136} // namespace
13137
13138
13139template <int dim, int spacedim>
13142{
13143 ::clear_user_flags_line(dim, levels, faces.get());
13144}
13145
13146
13147
13148namespace
13149{
13150 void
13151 clear_user_flags_quad(
13152 unsigned int dim,
13153 std::vector<
13154 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
13155 &levels,
13157 {
13158 if (dim == 1)
13159 {
13160 // nothing to do in 1d
13161 }
13162 else if (dim == 2)
13163 {
13164 for (const auto &level : levels)
13165 level->cells.clear_user_flags();
13166 }
13167 else if (dim == 3)
13168 {
13169 faces->quads.clear_user_flags();
13170 }
13171 else
13172 {
13174 }
13175 }
13176} // namespace
13177
13178
13179template <int dim, int spacedim>
13182{
13183 ::clear_user_flags_quad(dim, levels, faces.get());
13184}
13185
13186
13187
13188namespace
13189{
13190 void
13191 clear_user_flags_hex(
13192 unsigned int dim,
13193 std::vector<
13194 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
13195 &levels,
13197 {
13198 if (dim == 1)
13199 {
13200 // nothing to do in 1d
13201 }
13202 else if (dim == 2)
13203 {
13204 // nothing to do in 2d
13205 }
13206 else if (dim == 3)
13207 {
13208 for (const auto &level : levels)
13209 level->cells.clear_user_flags();
13210 }
13211 else
13212 {
13214 }
13215 }
13216} // namespace
13217
13218
13219template <int dim, int spacedim>
13222{
13223 ::clear_user_flags_hex(dim, levels, faces.get());
13224}
13225
13226
13227
13228template <int dim, int spacedim>
13231{
13232 clear_user_flags_line();
13233 clear_user_flags_quad();
13234 clear_user_flags_hex();
13235}
13236
13237
13238
13239template <int dim, int spacedim>
13241void Triangulation<dim, spacedim>::save_user_flags(std::ostream &out) const
13242{
13243 save_user_flags_line(out);
13244
13245 if (dim >= 2)
13246 save_user_flags_quad(out);
13247
13248 if (dim >= 3)
13249 save_user_flags_hex(out);
13250
13251 if (dim >= 4)
13253}
13254
13255
13256
13257template <int dim, int spacedim>
13259void Triangulation<dim, spacedim>::save_user_flags(std::vector<bool> &v) const
13260{
13261 // clear vector and append
13262 // all the stuff later on
13263 v.clear();
13264
13265 std::vector<bool> tmp;
13266
13267 save_user_flags_line(tmp);
13268 v.insert(v.end(), tmp.begin(), tmp.end());
13269
13270 if (dim >= 2)
13271 {
13272 save_user_flags_quad(tmp);
13273 v.insert(v.end(), tmp.begin(), tmp.end());
13274 }
13275
13276 if (dim >= 3)
13277 {
13278 save_user_flags_hex(tmp);
13279 v.insert(v.end(), tmp.begin(), tmp.end());
13280 }
13281
13282 if (dim >= 4)
13284}
13285
13286
13287
13288template <int dim, int spacedim>
13291{
13292 load_user_flags_line(in);
13293
13294 if (dim >= 2)
13295 load_user_flags_quad(in);
13296
13297 if (dim >= 3)
13298 load_user_flags_hex(in);
13299
13300 if (dim >= 4)
13302}
13303
13304
13305
13306template <int dim, int spacedim>
13308void Triangulation<dim, spacedim>::load_user_flags(const std::vector<bool> &v)
13309{
13310 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
13311 std::vector<bool> tmp;
13312
13313 // first extract the flags
13314 // belonging to lines
13315 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
13316 // and set the lines
13317 load_user_flags_line(tmp);
13318
13319 if (dim >= 2)
13320 {
13321 tmp.clear();
13322 tmp.insert(tmp.end(),
13323 v.begin() + n_lines(),
13324 v.begin() + n_lines() + n_quads());
13325 load_user_flags_quad(tmp);
13326 }
13327
13328 if (dim >= 3)
13329 {
13330 tmp.clear();
13331 tmp.insert(tmp.end(),
13332 v.begin() + n_lines() + n_quads(),
13333 v.begin() + n_lines() + n_quads() + n_hexs());
13334 load_user_flags_hex(tmp);
13335 }
13336
13337 if (dim >= 4)
13339}
13340
13341
13342
13343template <int dim, int spacedim>
13346 std::vector<bool> &v) const
13347{
13348 v.resize(n_lines(), false);
13349 std::vector<bool>::iterator i = v.begin();
13350 line_iterator line = begin_line(), endl = end_line();
13351 for (; line != endl; ++line, ++i)
13352 *i = line->user_flag_set();
13353
13354 Assert(i == v.end(), ExcInternalError());
13355}
13356
13357
13358
13359template <int dim, int spacedim>
13361void Triangulation<dim, spacedim>::save_user_flags_line(std::ostream &out) const
13362{
13363 std::vector<bool> v;
13364 save_user_flags_line(v);
13365 write_bool_vector(mn_tria_line_user_flags_begin,
13366 v,
13368 out);
13369}
13370
13371
13372
13373template <int dim, int spacedim>
13376{
13377 std::vector<bool> v;
13378 read_bool_vector(mn_tria_line_user_flags_begin,
13379 v,
13381 in);
13382 load_user_flags_line(v);
13383}
13384
13385
13386
13387template <int dim, int spacedim>
13390 const std::vector<bool> &v)
13391{
13392 Assert(v.size() == n_lines(), ExcGridReadError());
13393
13394 line_iterator line = begin_line(), endl = end_line();
13395 std::vector<bool>::const_iterator i = v.begin();
13396 for (; line != endl; ++line, ++i)
13397 if (*i == true)
13398 line->set_user_flag();
13399 else
13400 line->clear_user_flag();
13401
13402 Assert(i == v.end(), ExcInternalError());
13403}
13404
13405#endif
13406
13407namespace
13408{
13409 template <typename Iterator>
13410 bool
13411 get_user_flag(const Iterator &i)
13412 {
13413 return i->user_flag_set();
13414 }
13415
13416
13417
13418 template <int structdim, int dim, int spacedim>
13419 bool
13421 {
13423 return false;
13424 }
13425
13426
13427
13428 template <typename Iterator>
13429 void
13430 set_user_flag(const Iterator &i)
13431 {
13432 i->set_user_flag();
13433 }
13434
13435
13436
13437 template <int structdim, int dim, int spacedim>
13438 void
13440 {
13442 }
13443
13444
13445
13446 template <typename Iterator>
13447 void
13448 clear_user_flag(const Iterator &i)
13449 {
13450 i->clear_user_flag();
13451 }
13452
13453
13454
13455 template <int structdim, int dim, int spacedim>
13456 void
13457 clear_user_flag(
13459 {
13461 }
13462} // namespace
13463
13464#ifndef DOXYGEN
13465
13466template <int dim, int spacedim>
13469 std::vector<bool> &v) const
13470{
13471 v.resize(n_quads(), false);
13472
13473 if (dim >= 2)
13474 {
13475 std::vector<bool>::iterator i = v.begin();
13476 quad_iterator quad = begin_quad(), endq = end_quad();
13477 for (; quad != endq; ++quad, ++i)
13478 *i = get_user_flag(quad);
13479
13480 Assert(i == v.end(), ExcInternalError());
13481 }
13482}
13483
13484
13485
13486template <int dim, int spacedim>
13488void Triangulation<dim, spacedim>::save_user_flags_quad(std::ostream &out) const
13489{
13490 std::vector<bool> v;
13491 save_user_flags_quad(v);
13492 write_bool_vector(mn_tria_quad_user_flags_begin,
13493 v,
13495 out);
13496}
13497
13498
13499
13500template <int dim, int spacedim>
13503{
13504 std::vector<bool> v;
13505 read_bool_vector(mn_tria_quad_user_flags_begin,
13506 v,
13508 in);
13509 load_user_flags_quad(v);
13510}
13511
13512
13513
13514template <int dim, int spacedim>
13517 const std::vector<bool> &v)
13518{
13519 Assert(v.size() == n_quads(), ExcGridReadError());
13520
13521 if (dim >= 2)
13522 {
13523 quad_iterator quad = begin_quad(), endq = end_quad();
13524 std::vector<bool>::const_iterator i = v.begin();
13525 for (; quad != endq; ++quad, ++i)
13526 if (*i == true)
13527 set_user_flag(quad);
13528 else
13529 clear_user_flag(quad);
13530
13531 Assert(i == v.end(), ExcInternalError());
13532 }
13533}
13534
13535
13536
13537template <int dim, int spacedim>
13540 std::vector<bool> &v) const
13541{
13542 v.resize(n_hexs(), false);
13543
13544 if (dim >= 3)
13545 {
13546 std::vector<bool>::iterator i = v.begin();
13547 hex_iterator hex = begin_hex(), endh = end_hex();
13548 for (; hex != endh; ++hex, ++i)
13549 *i = get_user_flag(hex);
13550
13551 Assert(i == v.end(), ExcInternalError());
13552 }
13553}
13554
13555
13556
13557template <int dim, int spacedim>
13559void Triangulation<dim, spacedim>::save_user_flags_hex(std::ostream &out) const
13560{
13561 std::vector<bool> v;
13562 save_user_flags_hex(v);
13563 write_bool_vector(mn_tria_hex_user_flags_begin,
13564 v,
13566 out);
13567}
13568
13569
13570
13571template <int dim, int spacedim>
13574{
13575 std::vector<bool> v;
13576 read_bool_vector(mn_tria_hex_user_flags_begin,
13577 v,
13579 in);
13580 load_user_flags_hex(v);
13581}
13582
13583
13584
13585template <int dim, int spacedim>
13588 const std::vector<bool> &v)
13589{
13590 Assert(v.size() == n_hexs(), ExcGridReadError());
13591
13592 if (dim >= 3)
13593 {
13594 hex_iterator hex = begin_hex(), endh = end_hex();
13595 std::vector<bool>::const_iterator i = v.begin();
13596 for (; hex != endh; ++hex, ++i)
13597 if (*i == true)
13598 set_user_flag(hex);
13599 else
13600 clear_user_flag(hex);
13601
13602 Assert(i == v.end(), ExcInternalError());
13603 }
13604}
13605
13606
13607
13608template <int dim, int spacedim>
13611 std::vector<unsigned int> &v) const
13612{
13613 // clear vector and append all the
13614 // stuff later on
13615 v.clear();
13616
13617 std::vector<unsigned int> tmp;
13618
13619 save_user_indices_line(tmp);
13620 v.insert(v.end(), tmp.begin(), tmp.end());
13621
13622 if (dim >= 2)
13623 {
13624 save_user_indices_quad(tmp);
13625 v.insert(v.end(), tmp.begin(), tmp.end());
13626 }
13627
13628 if (dim >= 3)
13629 {
13630 save_user_indices_hex(tmp);
13631 v.insert(v.end(), tmp.begin(), tmp.end());
13632 }
13633
13634 if (dim >= 4)
13636}
13637
13638
13639
13640template <int dim, int spacedim>
13643 const std::vector<unsigned int> &v)
13644{
13645 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
13646 std::vector<unsigned int> tmp;
13647
13648 // first extract the indices
13649 // belonging to lines
13650 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
13651 // and set the lines
13652 load_user_indices_line(tmp);
13653
13654 if (dim >= 2)
13655 {
13656 tmp.clear();
13657 tmp.insert(tmp.end(),
13658 v.begin() + n_lines(),
13659 v.begin() + n_lines() + n_quads());
13660 load_user_indices_quad(tmp);
13661 }
13662
13663 if (dim >= 3)
13664 {
13665 tmp.clear();
13666 tmp.insert(tmp.end(),
13667 v.begin() + n_lines() + n_quads(),
13668 v.begin() + n_lines() + n_quads() + n_hexs());
13669 load_user_indices_hex(tmp);
13670 }
13671
13672 if (dim >= 4)
13674}
13675
13676
13677
13678template <int dim, int spacedim>
13680void Triangulation<dim, spacedim>::save(const std::string &file_basename) const
13681{
13682 // Save triangulation information.
13683 {
13684 std::ofstream ofs_tria(file_basename + "_triangulation.data");
13685 AssertThrow(ofs_tria.fail() == false, ExcIO());
13686
13687 boost::archive::text_oarchive oa(ofs_tria, boost::archive::no_header);
13688 save(oa,
13690 }
13691
13692 // Save attached data.
13693 {
13694 std::ofstream ofs_info(file_basename + ".info");
13695 ofs_info
13696 << "version nproc n_attached_fixed_size_objs n_attached_variable_size_objs n_active_cells"
13697 << std::endl
13699 << " " << 1 << " " << this->cell_attached_data.pack_callbacks_fixed.size()
13700 << " " << this->cell_attached_data.pack_callbacks_variable.size() << " "
13701 << this->n_global_active_cells() << std::endl;
13702 }
13703
13704 this->save_attached_data(0, this->n_global_active_cells(), file_basename);
13705}
13706
13707
13708
13709template <int dim, int spacedim>
13711void Triangulation<dim, spacedim>::load(const std::string &file_basename)
13712{
13713 // Load triangulation information.
13714 {
13715 std::ifstream ifs_tria(file_basename + "_triangulation.data");
13716 AssertThrow(ifs_tria.fail() == false, ExcIO());
13717
13718 boost::archive::text_iarchive ia(ifs_tria, boost::archive::no_header);
13719 load(ia,
13721 }
13722
13723 // Load attached data.
13724 unsigned int version, numcpus, attached_count_fixed, attached_count_variable,
13725 n_global_active_cells;
13726 {
13727 std::ifstream ifs_info(std::string(file_basename) + ".info");
13728 AssertThrow(ifs_info.fail() == false, ExcIO());
13729 std::string firstline;
13730 std::getline(ifs_info, firstline);
13731 ifs_info >> version >> numcpus >> attached_count_fixed >>
13732 attached_count_variable >> n_global_active_cells;
13733 }
13734
13735 AssertThrow(numcpus == 1,
13736 ExcMessage("Incompatible number of CPUs found in .info file."));
13737
13738 const auto expected_version =
13740 spacedim>::version_number;
13741 AssertThrow(version == expected_version,
13742 ExcMessage(
13743 "The information saved in the file you are trying "
13744 "to read the triangulation from was written with an "
13745 "incompatible file format version and cannot be read."));
13746 Assert(this->n_global_active_cells() == n_global_active_cells,
13747 ExcMessage("The number of cells of the triangulation differs "
13748 "from the number of cells written into the .info file."));
13749
13750 // Clear all of the callback data, as explained in the documentation of
13751 // register_data_attach().
13752 this->cell_attached_data.n_attached_data_sets = 0;
13753 this->cell_attached_data.n_attached_deserialize =
13754 attached_count_fixed + attached_count_variable;
13755
13756 this->load_attached_data(0,
13757 this->n_global_active_cells(),
13758 this->n_active_cells(),
13759 file_basename,
13760 attached_count_fixed,
13761 attached_count_variable);
13762
13763 this->update_cell_relations();
13764}
13765
13766#endif
13767namespace
13768{
13769 template <typename Iterator>
13770 unsigned int
13771 get_user_index(const Iterator &i)
13772 {
13773 return i->user_index();
13774 }
13775
13776
13777
13778 template <int structdim, int dim, int spacedim>
13779 unsigned int
13780 get_user_index(
13782 {
13785 }
13786
13787
13788
13789 template <typename Iterator>
13790 void
13791 set_user_index(const Iterator &i, const unsigned int x)
13792 {
13793 i->set_user_index(x);
13794 }
13795
13796
13797
13798 template <int structdim, int dim, int spacedim>
13799 void
13800 set_user_index(
13802 const unsigned int)
13803 {
13805 }
13806} // namespace
13807
13808#ifndef DOXYGEN
13809
13810template <int dim, int spacedim>
13813 std::vector<unsigned int> &v) const
13814{
13815 v.resize(n_lines(), 0);
13816 std::vector<unsigned int>::iterator i = v.begin();
13817 line_iterator line = begin_line(), endl = end_line();
13818 for (; line != endl; ++line, ++i)
13819 *i = line->user_index();
13820}
13821
13822
13823
13824template <int dim, int spacedim>
13827 const std::vector<unsigned int> &v)
13828{
13829 Assert(v.size() == n_lines(), ExcGridReadError());
13830
13831 line_iterator line = begin_line(), endl = end_line();
13832 std::vector<unsigned int>::const_iterator i = v.begin();
13833 for (; line != endl; ++line, ++i)
13834 line->set_user_index(*i);
13835}
13836
13837
13838template <int dim, int spacedim>
13841 std::vector<unsigned int> &v) const
13842{
13843 v.resize(n_quads(), 0);
13844
13845 if (dim >= 2)
13846 {
13847 std::vector<unsigned int>::iterator i = v.begin();
13848 quad_iterator quad = begin_quad(), endq = end_quad();
13849 for (; quad != endq; ++quad, ++i)
13850 *i = get_user_index(quad);
13851 }
13852}
13853
13854
13855
13856template <int dim, int spacedim>
13859 const std::vector<unsigned int> &v)
13860{
13861 Assert(v.size() == n_quads(), ExcGridReadError());
13862
13863 if (dim >= 2)
13864 {
13865 quad_iterator quad = begin_quad(), endq = end_quad();
13866 std::vector<unsigned int>::const_iterator i = v.begin();
13867 for (; quad != endq; ++quad, ++i)
13868 set_user_index(quad, *i);
13869 }
13870}
13871
13872
13873template <int dim, int spacedim>
13876 std::vector<unsigned int> &v) const
13877{
13878 v.resize(n_hexs(), 0);
13879
13880 if (dim >= 3)
13881 {
13882 std::vector<unsigned int>::iterator i = v.begin();
13883 hex_iterator hex = begin_hex(), endh = end_hex();
13884 for (; hex != endh; ++hex, ++i)
13885 *i = get_user_index(hex);
13886 }
13887}
13888
13889
13890
13891template <int dim, int spacedim>
13894 const std::vector<unsigned int> &v)
13895{
13896 Assert(v.size() == n_hexs(), ExcGridReadError());
13897
13898 if (dim >= 3)
13899 {
13900 hex_iterator hex = begin_hex(), endh = end_hex();
13901 std::vector<unsigned int>::const_iterator i = v.begin();
13902 for (; hex != endh; ++hex, ++i)
13903 set_user_index(hex, *i);
13904 }
13905}
13906
13907#endif
13908
13909
13910//---------------- user pointers ----------------------------------------//
13911
13912
13913namespace
13914{
13915 template <typename Iterator>
13916 void *
13917 get_user_pointer(const Iterator &i)
13918 {
13919 return i->user_pointer();
13920 }
13921
13922
13923
13924 template <int structdim, int dim, int spacedim>
13925 void *
13926 get_user_pointer(
13928 {
13930 return nullptr;
13931 }
13932
13933
13934
13935 template <typename Iterator>
13936 void
13937 set_user_pointer(const Iterator &i, void *x)
13938 {
13939 i->set_user_pointer(x);
13940 }
13941
13942
13943
13944 template <int structdim, int dim, int spacedim>
13945 void
13946 set_user_pointer(
13948 void *)
13949 {
13951 }
13952} // namespace
13953
13954#ifndef DOXYGEN
13955
13956template <int dim, int spacedim>
13959 std::vector<void *> &v) const
13960{
13961 // clear vector and append all the
13962 // stuff later on
13963 v.clear();
13964
13965 std::vector<void *> tmp;
13966
13967 save_user_pointers_line(tmp);
13968 v.insert(v.end(), tmp.begin(), tmp.end());
13969
13970 if (dim >= 2)
13971 {
13972 save_user_pointers_quad(tmp);
13973 v.insert(v.end(), tmp.begin(), tmp.end());
13974 }
13975
13976 if (dim >= 3)
13977 {
13978 save_user_pointers_hex(tmp);
13979 v.insert(v.end(), tmp.begin(), tmp.end());
13980 }
13981
13982 if (dim >= 4)
13984}
13985
13986
13987
13988template <int dim, int spacedim>
13991 const std::vector<void *> &v)
13992{
13993 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
13994 std::vector<void *> tmp;
13995
13996 // first extract the pointers
13997 // belonging to lines
13998 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
13999 // and set the lines
14000 load_user_pointers_line(tmp);
14001
14002 if (dim >= 2)
14003 {
14004 tmp.clear();
14005 tmp.insert(tmp.end(),
14006 v.begin() + n_lines(),
14007 v.begin() + n_lines() + n_quads());
14008 load_user_pointers_quad(tmp);
14009 }
14010
14011 if (dim >= 3)
14012 {
14013 tmp.clear();
14014 tmp.insert(tmp.end(),
14015 v.begin() + n_lines() + n_quads(),
14016 v.begin() + n_lines() + n_quads() + n_hexs());
14017 load_user_pointers_hex(tmp);
14018 }
14019
14020 if (dim >= 4)
14022}
14023
14024
14025
14026template <int dim, int spacedim>
14029 std::vector<void *> &v) const
14030{
14031 v.resize(n_lines(), nullptr);
14032 std::vector<void *>::iterator i = v.begin();
14033 line_iterator line = begin_line(), endl = end_line();
14034 for (; line != endl; ++line, ++i)
14035 *i = line->user_pointer();
14036}
14037
14038
14039
14040template <int dim, int spacedim>
14043 const std::vector<void *> &v)
14044{
14045 Assert(v.size() == n_lines(), ExcGridReadError());
14046
14047 line_iterator line = begin_line(), endl = end_line();
14048 std::vector<void *>::const_iterator i = v.begin();
14049 for (; line != endl; ++line, ++i)
14050 line->set_user_pointer(*i);
14051}
14052
14053
14054
14055template <int dim, int spacedim>
14058 std::vector<void *> &v) const
14059{
14060 v.resize(n_quads(), nullptr);
14061
14062 if (dim >= 2)
14063 {
14064 std::vector<void *>::iterator i = v.begin();
14065 quad_iterator quad = begin_quad(), endq = end_quad();
14066 for (; quad != endq; ++quad, ++i)
14067 *i = get_user_pointer(quad);
14068 }
14069}
14070
14071
14072
14073template <int dim, int spacedim>
14076 const std::vector<void *> &v)
14077{
14078 Assert(v.size() == n_quads(), ExcGridReadError());
14079
14080 if (dim >= 2)
14081 {
14082 quad_iterator quad = begin_quad(), endq = end_quad();
14083 std::vector<void *>::const_iterator i = v.begin();
14084 for (; quad != endq; ++quad, ++i)
14085 set_user_pointer(quad, *i);
14086 }
14087}
14088
14089
14090template <int dim, int spacedim>
14093 std::vector<void *> &v) const
14094{
14095 v.resize(n_hexs(), nullptr);
14096
14097 if (dim >= 3)
14098 {
14099 std::vector<void *>::iterator i = v.begin();
14100 hex_iterator hex = begin_hex(), endh = end_hex();
14101 for (; hex != endh; ++hex, ++i)
14102 *i = get_user_pointer(hex);
14103 }
14104}
14105
14106
14107
14108template <int dim, int spacedim>
14111 const std::vector<void *> &v)
14112{
14113 Assert(v.size() == n_hexs(), ExcGridReadError());
14114
14115 if (dim >= 3)
14116 {
14117 hex_iterator hex = begin_hex(), endh = end_hex();
14118 std::vector<void *>::const_iterator i = v.begin();
14119 for (; hex != endh; ++hex, ++i)
14120 set_user_pointer(hex, *i);
14121 }
14122}
14123
14124#endif
14125
14126/*------------------------ Cell iterator functions ------------------------*/
14127
14128#ifndef DOXYGEN
14129
14130template <int dim, int spacedim>
14133 Triangulation<dim, spacedim>::begin_raw(const unsigned int level) const
14134{
14135 switch (dim)
14136 {
14137 case 1:
14138 return begin_raw_line(level);
14139 case 2:
14140 return begin_raw_quad(level);
14141 case 3:
14142 return begin_raw_hex(level);
14143 default:
14145 return raw_cell_iterator();
14146 }
14147}
14148
14149
14150
14151template <int dim, int spacedim>
14154 Triangulation<dim, spacedim>::begin(const unsigned int level) const
14155{
14156 switch (dim)
14157 {
14158 case 1:
14159 return begin_line(level);
14160 case 2:
14161 return begin_quad(level);
14162 case 3:
14163 return begin_hex(level);
14164 default:
14165 Assert(false, ExcImpossibleInDim(dim));
14166 return cell_iterator();
14167 }
14168}
14169
14170
14171
14172template <int dim, int spacedim>
14175 Triangulation<dim, spacedim>::begin_active(const unsigned int level) const
14176{
14177 switch (dim)
14178 {
14179 case 1:
14180 return begin_active_line(level);
14181 case 2:
14182 return begin_active_quad(level);
14183 case 3:
14184 return begin_active_hex(level);
14185 default:
14187 return active_cell_iterator();
14188 }
14189}
14190
14191
14192
14193template <int dim, int spacedim>
14197{
14198 const unsigned int level = levels.size() - 1;
14199 if (levels[level]->cells.n_objects() == 0)
14200 return end(level);
14201
14202 // find the last raw iterator on
14203 // this level
14204 raw_cell_iterator ri(const_cast<Triangulation<dim, spacedim> *>(this),
14205 level,
14206 levels[level]->cells.n_objects() - 1);
14207
14208 // then move to the last used one
14209 if (ri->used() == true)
14210 return ri;
14211 while ((--ri).state() == IteratorState::valid)
14212 if (ri->used() == true)
14213 return ri;
14214 return ri;
14215}
14216
14217
14218
14219template <int dim, int spacedim>
14223{
14224 // get the last used cell
14225 cell_iterator cell = last();
14226
14227 if (cell != end())
14228 {
14229 // then move to the last active one
14230 if (cell->is_active() == true)
14231 return cell;
14232 while ((--cell).state() == IteratorState::valid)
14233 if (cell->is_active() == true)
14234 return cell;
14235 }
14236 return cell;
14237}
14238
14239
14240
14241template <int dim, int spacedim>
14245 const CellId &cell_id) const
14246{
14247 Assert(
14248 this->contains_cell(cell_id),
14249 ExcMessage(
14250 "CellId is invalid for this triangulation.\n"
14251 "Either the provided CellId does not correspond to a cell in this "
14252 "triangulation object, or, in case you are using a parallel "
14253 "triangulation, may correspond to an artificial cell that is less "
14254 "refined on this processor. In the case of "
14255 "parallel::fullydistributed::Triangulation, the corresponding coarse "
14256 "cell might not be accessible by the current process."));
14257
14258 cell_iterator cell(
14259 this, 0, coarse_cell_id_to_coarse_cell_index(cell_id.get_coarse_cell_id()));
14260
14261 for (const auto &child_index : cell_id.get_child_indices())
14262 cell = cell->child(static_cast<unsigned int>(child_index));
14263
14264 return cell;
14265}
14266
14267
14268
14269template <int dim, int spacedim>
14271bool Triangulation<dim, spacedim>::contains_cell(const CellId &cell_id) const
14272{
14273 const auto coarse_cell_index =
14274 coarse_cell_id_to_coarse_cell_index(cell_id.get_coarse_cell_id());
14275
14276 if (coarse_cell_index == numbers::invalid_unsigned_int)
14277 return false;
14278
14279 cell_iterator cell(this, 0, coarse_cell_index);
14280
14281 for (const auto &child_index : cell_id.get_child_indices())
14282 {
14283 if (cell->has_children() == false)
14284 return false;
14285 cell = cell->child(static_cast<unsigned int>(child_index));
14286 }
14287
14288 return true;
14289}
14290
14291
14292
14293template <int dim, int spacedim>
14297{
14298 return cell_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14299 -1,
14300 -1);
14301}
14302
14303
14304
14305template <int dim, int spacedim>
14308 Triangulation<dim, spacedim>::end_raw(const unsigned int level) const
14309{
14310 // This function may be called on parallel triangulations on levels
14311 // that exist globally, but not on the local portion of the
14312 // triangulation. In that case, just return the end iterator.
14313 //
14314 // We need to use levels.size() instead of n_levels() because the
14315 // latter function uses the cache, but we need to be able to call
14316 // this function at a time when the cache is not currently up to
14317 // date.
14318 if (level >= levels.size())
14319 {
14320 Assert(level < n_global_levels(),
14321 ExcInvalidLevel(level, n_global_levels()));
14322 return end();
14323 }
14324
14325 // Query whether the given level is valid for the local portion of the
14326 // triangulation.
14327 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14328 if (level < levels.size() - 1)
14329 return begin_raw(level + 1);
14330 else
14331 return end();
14332}
14333
14334
14335template <int dim, int spacedim>
14338 Triangulation<dim, spacedim>::end(const unsigned int level) const
14339{
14340 // This function may be called on parallel triangulations on levels
14341 // that exist globally, but not on the local portion of the
14342 // triangulation. In that case, just return the end iterator.
14343 //
14344 // We need to use levels.size() instead of n_levels() because the
14345 // latter function uses the cache, but we need to be able to call
14346 // this function at a time when the cache is not currently up to
14347 // date.
14348 if (level >= levels.size())
14349 {
14350 Assert(level < n_global_levels(),
14351 ExcInvalidLevel(level, n_global_levels()));
14352 return end();
14353 }
14354
14355 // Query whether the given level is valid for the local portion of the
14356 // triangulation.
14357 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14358 if (level < levels.size() - 1)
14359 return begin(level + 1);
14360 else
14361 return end();
14362}
14363
14364
14365template <int dim, int spacedim>
14368 Triangulation<dim, spacedim>::end_active(const unsigned int level) const
14369{
14370 // This function may be called on parallel triangulations on levels
14371 // that exist globally, but not on the local portion of the
14372 // triangulation. In that case, just return the end iterator.
14373 //
14374 // We need to use levels.size() instead of n_levels() because the
14375 // latter function uses the cache, but we need to be able to call
14376 // this function at a time when the cache is not currently up to
14377 // date.
14378 if (level >= levels.size())
14379 {
14380 Assert(level < n_global_levels(),
14381 ExcInvalidLevel(level, n_global_levels()));
14382 return end();
14383 }
14384
14385 // Query whether the given level is valid for the local portion of the
14386 // triangulation.
14387 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14388 return (level >= levels.size() - 1 ? active_cell_iterator(end()) :
14389 begin_active(level + 1));
14390}
14391
14392
14393
14394template <int dim, int spacedim>
14398 const
14399{
14401 begin(), end());
14402}
14403
14404
14405template <int dim, int spacedim>
14408 active_cell_iterator> Triangulation<dim, spacedim>::
14410{
14411 return IteratorRange<
14413 end());
14414}
14415
14416
14417
14418template <int dim, int spacedim>
14421 cell_iterator> Triangulation<dim, spacedim>::
14422 cell_iterators_on_level(const unsigned int level) const
14423{
14425 begin(level), end(level));
14426}
14427
14428
14429
14430template <int dim, int spacedim>
14433 active_cell_iterator> Triangulation<dim, spacedim>::
14434 active_cell_iterators_on_level(const unsigned int level) const
14435{
14436 return IteratorRange<
14438 begin_active(level), end_active(level));
14439}
14440#endif
14441
14442/*------------------------ Face iterator functions ------------------------*/
14443
14444#ifndef DOXYGEN
14445
14446template <int dim, int spacedim>
14450{
14451 switch (dim)
14452 {
14453 case 1:
14454 Assert(false, ExcImpossibleInDim(1));
14455 return raw_face_iterator();
14456 case 2:
14457 return begin_line();
14458 case 3:
14459 return begin_quad();
14460 default:
14462 return face_iterator();
14463 }
14464}
14465
14466
14467
14468template <int dim, int spacedim>
14472{
14473 switch (dim)
14474 {
14475 case 1:
14476 Assert(false, ExcImpossibleInDim(1));
14477 return raw_face_iterator();
14478 case 2:
14479 return begin_active_line();
14480 case 3:
14481 return begin_active_quad();
14482 default:
14484 return active_face_iterator();
14485 }
14486}
14487
14488
14489
14490template <int dim, int spacedim>
14494{
14495 switch (dim)
14496 {
14497 case 1:
14498 Assert(false, ExcImpossibleInDim(1));
14499 return raw_face_iterator();
14500 case 2:
14501 return end_line();
14502 case 3:
14503 return end_quad();
14504 default:
14506 return raw_face_iterator();
14507 }
14508}
14509
14510
14511
14512template <int dim, int spacedim>
14515 active_face_iterator> Triangulation<dim, spacedim>::
14517{
14518 return IteratorRange<
14520 begin_active_face(), end_face());
14521}
14522
14523/*------------------------ Vertex iterator functions ------------------------*/
14524
14525
14526template <int dim, int spacedim>
14530{
14531 vertex_iterator i =
14532 raw_vertex_iterator(const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
14533 if (i.state() != IteratorState::valid)
14534 return i;
14535 // This loop will end because every triangulation has used vertices.
14536 while (i->used() == false)
14537 if ((++i).state() != IteratorState::valid)
14538 return i;
14539 return i;
14540}
14541
14542
14543
14544template <int dim, int spacedim>
14548{
14549 // every vertex is active
14550 return begin_vertex();
14551}
14552
14553
14554
14555template <int dim, int spacedim>
14559{
14560 return raw_vertex_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14561 -1,
14563}
14564
14565#endif
14566
14567
14568/*------------------------ Line iterator functions ------------------------*/
14569
14570#ifndef DOXYGEN
14571
14572template <int dim, int spacedim>
14575 Triangulation<dim, spacedim>::begin_raw_line(const unsigned int level) const
14576{
14577 // This function may be called on parallel triangulations on levels
14578 // that exist globally, but not on the local portion of the
14579 // triangulation. In that case, just return the end iterator.
14580 //
14581 // We need to use levels.size() instead of n_levels() because the
14582 // latter function uses the cache, but we need to be able to call
14583 // this function at a time when the cache is not currently up to
14584 // date.
14585 if (level >= levels.size())
14586 {
14587 Assert(level < n_global_levels(),
14588 ExcInvalidLevel(level, n_global_levels()));
14589 return end_line();
14590 }
14591
14592 switch (dim)
14593 {
14594 case 1:
14595 // Query whether the given level is valid for the local portion of the
14596 // triangulation.
14597 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14598
14599 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
14600 return end_line();
14601
14602 return raw_line_iterator(
14603 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
14604
14605 default:
14606 Assert(level == 0, ExcFacesHaveNoLevel());
14607 return raw_line_iterator(
14608 const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
14609 }
14610}
14611
14612
14613template <int dim, int spacedim>
14616 Triangulation<dim, spacedim>::begin_line(const unsigned int level) const
14617{
14618 // level is checked in begin_raw
14619 raw_line_iterator ri = begin_raw_line(level);
14620 if (ri.state() != IteratorState::valid)
14621 return ri;
14622 while (ri->used() == false)
14623 if ((++ri).state() != IteratorState::valid)
14624 return ri;
14625 return ri;
14626}
14627
14628
14629
14630template <int dim, int spacedim>
14634 const unsigned int level) const
14635{
14636 // level is checked in begin_raw
14637 line_iterator i = begin_line(level);
14638 if (i.state() != IteratorState::valid)
14639 return i;
14640 while (i->has_children())
14641 if ((++i).state() != IteratorState::valid)
14642 return i;
14643 return i;
14644}
14645
14646
14647
14648template <int dim, int spacedim>
14652{
14653 return raw_line_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14654 -1,
14655 -1);
14656}
14657
14658#endif
14659
14660/*------------------------ Quad iterator functions ------------------------*/
14661
14662#ifndef DOXYGEN
14663
14664template <int dim, int spacedim>
14667 Triangulation<dim, spacedim>::begin_raw_quad(const unsigned int level) const
14668{
14669 // This function may be called on parallel triangulations on levels
14670 // that exist globally, but not on the local portion of the
14671 // triangulation. In that case, just return the end iterator.
14672 //
14673 // We need to use levels.size() instead of n_levels() because the
14674 // latter function uses the cache, but we need to be able to call
14675 // this function at a time when the cache is not currently up to
14676 // date.
14677 if (level >= levels.size())
14678 {
14679 Assert(level < n_global_levels(),
14680 ExcInvalidLevel(level, n_global_levels()));
14681 return end_quad();
14682 }
14683
14684 switch (dim)
14685 {
14686 case 1:
14687 Assert(false, ExcImpossibleInDim(1));
14688 return raw_hex_iterator();
14689 case 2:
14690 {
14691 // Query whether the given level is valid for the local portion of the
14692 // triangulation.
14693 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14694
14695 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
14696 return end_quad();
14697
14698 return raw_quad_iterator(
14699 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
14700 }
14701
14702 case 3:
14703 {
14704 Assert(level == 0, ExcFacesHaveNoLevel());
14705
14706 return raw_quad_iterator(
14707 const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
14708 }
14709
14710
14711 default:
14713 return raw_hex_iterator();
14714 }
14715}
14716
14717
14718
14719template <int dim, int spacedim>
14722 Triangulation<dim, spacedim>::begin_quad(const unsigned int level) const
14723{
14724 // level is checked in begin_raw
14725 raw_quad_iterator ri = begin_raw_quad(level);
14726 if (ri.state() != IteratorState::valid)
14727 return ri;
14728 while (ri->used() == false)
14729 if ((++ri).state() != IteratorState::valid)
14730 return ri;
14731 return ri;
14732}
14733
14734
14735
14736template <int dim, int spacedim>
14740 const unsigned int level) const
14741{
14742 // level is checked in begin_raw
14743 quad_iterator i = begin_quad(level);
14744 if (i.state() != IteratorState::valid)
14745 return i;
14746 while (i->has_children())
14747 if ((++i).state() != IteratorState::valid)
14748 return i;
14749 return i;
14750}
14751
14752
14753
14754template <int dim, int spacedim>
14758{
14759 return raw_quad_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14760 -1,
14761 -1);
14762}
14763
14764#endif
14765
14766/*------------------------ Hex iterator functions ------------------------*/
14767
14768#ifndef DOXYGEN
14769
14770template <int dim, int spacedim>
14773 Triangulation<dim, spacedim>::begin_raw_hex(const unsigned int level) const
14774{
14775 // This function may be called on parallel triangulations on levels
14776 // that exist globally, but not on the local portion of the
14777 // triangulation. In that case, just return the end iterator.
14778 //
14779 // We need to use levels.size() instead of n_levels() because the
14780 // latter function uses the cache, but we need to be able to call
14781 // this function at a time when the cache is not currently up to
14782 // date.
14783 if (level >= levels.size())
14784 {
14785 Assert(level < n_global_levels(),
14786 ExcInvalidLevel(level, n_global_levels()));
14787 return end_hex();
14788 }
14789
14790 switch (dim)
14791 {
14792 case 1:
14793 case 2:
14794 Assert(false, ExcImpossibleInDim(1));
14795 return raw_hex_iterator();
14796 case 3:
14797 {
14798 // Query whether the given level is valid for the local portion of the
14799 // triangulation.
14800 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14801
14802 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
14803 return end_hex();
14804
14805 return raw_hex_iterator(
14806 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
14807 }
14808
14809 default:
14811 return raw_hex_iterator();
14812 }
14813}
14814
14815
14816
14817template <int dim, int spacedim>
14820 Triangulation<dim, spacedim>::begin_hex(const unsigned int level) const
14821{
14822 // level is checked in begin_raw
14823 raw_hex_iterator ri = begin_raw_hex(level);
14824 if (ri.state() != IteratorState::valid)
14825 return ri;
14826 while (ri->used() == false)
14827 if ((++ri).state() != IteratorState::valid)
14828 return ri;
14829 return ri;
14830}
14831
14832
14833
14834template <int dim, int spacedim>
14838{
14839 // level is checked in begin_raw
14840 hex_iterator i = begin_hex(level);
14841 if (i.state() != IteratorState::valid)
14842 return i;
14843 while (i->has_children())
14844 if ((++i).state() != IteratorState::valid)
14845 return i;
14846 return i;
14847}
14848
14849
14850
14851template <int dim, int spacedim>
14855{
14856 return raw_hex_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14857 -1,
14858 -1);
14859}
14860
14861#endif
14862
14863// -------------------------------- number of cells etc ---------------
14864
14865
14866namespace internal
14867{
14868 namespace TriangulationImplementation
14869 {
14870 inline unsigned int
14872 {
14873 return c.n_lines;
14874 }
14875
14876
14877 inline unsigned int
14880 {
14881 return c.n_active_lines;
14882 }
14883
14884
14885 inline unsigned int
14887 {
14888 return c.n_quads;
14889 }
14890
14891
14892 inline unsigned int
14895 {
14896 return c.n_active_quads;
14897 }
14898
14899
14900 inline unsigned int
14902 {
14903 return c.n_hexes;
14904 }
14905
14906
14907 inline unsigned int
14910 {
14911 return c.n_active_hexes;
14912 }
14913 } // namespace TriangulationImplementation
14914} // namespace internal
14915
14916#ifndef DOXYGEN
14917
14918template <int dim, int spacedim>
14920unsigned int Triangulation<dim, spacedim>::n_cells() const
14921{
14923}
14924
14925
14926template <int dim, int spacedim>
14929{
14931}
14932
14933template <int dim, int spacedim>
14937{
14938 return n_active_cells();
14939}
14940
14941template <int dim, int spacedim>
14945{
14946 return n_cells(0);
14947}
14948
14949template <int dim, int spacedim>
14951unsigned int Triangulation<dim, spacedim>::n_faces() const
14952{
14953 switch (dim)
14954 {
14955 case 1:
14956 return n_used_vertices();
14957 case 2:
14958 return n_lines();
14959 case 3:
14960 return n_quads();
14961 default:
14963 }
14964 return 0;
14965}
14966
14967
14968template <int dim, int spacedim>
14971{
14972 switch (dim)
14973 {
14974 case 1:
14975 return n_vertices();
14976 case 2:
14977 return n_raw_lines();
14978 case 3:
14979 return n_raw_quads();
14980 default:
14982 }
14983 return 0;
14984}
14985
14986
14987template <int dim, int spacedim>
14990{
14991 switch (dim)
14992 {
14993 case 1:
14994 return n_used_vertices();
14995 case 2:
14996 return n_active_lines();
14997 case 3:
14998 return n_active_quads();
14999 default:
15001 }
15002 return 0;
15003}
15004
15005
15006template <int dim, int spacedim>
15009 const unsigned int level) const
15010{
15011 switch (dim)
15012 {
15013 case 1:
15014 return n_raw_lines(level);
15015 case 2:
15016 return n_raw_quads(level);
15017 case 3:
15018 return n_raw_hexs(level);
15019 default:
15021 }
15022 return 0;
15023}
15024
15025
15026
15027template <int dim, int spacedim>
15030 const unsigned int level) const
15031{
15032 switch (dim)
15033 {
15034 case 1:
15035 return n_lines(level);
15036 case 2:
15037 return n_quads(level);
15038 case 3:
15039 return n_hexs(level);
15040 default:
15042 }
15043 return 0;
15044}
15045
15046
15047
15048template <int dim, int spacedim>
15051 const unsigned int level) const
15052{
15053 switch (dim)
15054 {
15055 case 1:
15056 return n_active_lines(level);
15057 case 2:
15058 return n_active_quads(level);
15059 case 3:
15060 return n_active_hexs(level);
15061 default:
15063 }
15064 return 0;
15065}
15066
15067
15068template <int dim, int spacedim>
15071{
15072 if (anisotropic_refinement == false)
15073 {
15074 for (unsigned int lvl = 0; lvl < n_global_levels() - 1; ++lvl)
15075 if (n_active_cells(lvl) != 0)
15076 return true;
15077 }
15078 else
15079 {
15080 for (const auto &cell : active_cell_iterators())
15081 for (const auto &i : cell->face_indices())
15082 if (cell->face(i)->has_children())
15083 return true;
15084 }
15085 return false;
15086}
15087
15088
15089template <int dim, int spacedim>
15091unsigned int Triangulation<dim, spacedim>::n_lines() const
15092{
15093 return number_cache.n_lines;
15094}
15095
15096
15097
15098template <int dim, int spacedim>
15101 const unsigned int level) const
15102{
15103 if (dim == 1)
15104 {
15105 AssertIndexRange(level, n_levels());
15106 return levels[level]->cells.n_objects();
15107 }
15108
15109 Assert(false, ExcFacesHaveNoLevel());
15110 return 0;
15111}
15112
15113
15114template <int dim, int spacedim>
15117{
15118 if (dim == 1)
15119 {
15121 return 0;
15122 }
15123
15124 return faces->lines.n_objects();
15125}
15126
15127
15128template <int dim, int spacedim>
15131 const unsigned int level) const
15132{
15133 AssertIndexRange(level, number_cache.n_lines_level.size());
15134 Assert(dim == 1, ExcFacesHaveNoLevel());
15135 return number_cache.n_lines_level[level];
15136}
15137
15138
15139template <int dim, int spacedim>
15142{
15143 return number_cache.n_active_lines;
15144}
15145
15146
15147template <int dim, int spacedim>
15150 const unsigned int level) const
15151{
15152 AssertIndexRange(level, number_cache.n_lines_level.size());
15153 Assert(dim == 1, ExcFacesHaveNoLevel());
15154
15155 return number_cache.n_active_lines_level[level];
15156}
15157#endif
15158
15159template <>
15160unsigned int
15162{
15163 return 0;
15164}
15165
15166
15167template <>
15168unsigned int
15169Triangulation<1, 1>::n_quads(const unsigned int) const
15170{
15171 return 0;
15172}
15173
15174
15175template <>
15176unsigned int
15177Triangulation<1, 1>::n_raw_quads(const unsigned int) const
15178{
15179 return 0;
15180}
15181
15182
15183template <>
15184unsigned int
15185Triangulation<1, 1>::n_raw_hexs(const unsigned int) const
15186{
15187 return 0;
15188}
15189
15190
15191template <>
15192unsigned int
15194{
15195 return 0;
15196}
15197
15198
15199template <>
15200unsigned int
15202{
15203 return 0;
15204}
15205
15206
15207
15208template <>
15209unsigned int
15211{
15212 return 0;
15213}
15214
15215
15216template <>
15217unsigned int
15218Triangulation<1, 2>::n_quads(const unsigned int) const
15219{
15220 return 0;
15221}
15222
15223
15224template <>
15225unsigned int
15226Triangulation<1, 2>::n_raw_quads(const unsigned int) const
15227{
15228 return 0;
15229}
15230
15231
15232template <>
15233unsigned int
15234Triangulation<1, 2>::n_raw_hexs(const unsigned int) const
15235{
15236 return 0;
15237}
15238
15239
15240template <>
15241unsigned int
15243{
15244 return 0;
15245}
15246
15247
15248template <>
15249unsigned int
15251{
15252 return 0;
15253}
15254
15255
15256template <>
15257unsigned int
15259{
15260 return 0;
15261}
15262
15263
15264template <>
15265unsigned int
15266Triangulation<1, 3>::n_quads(const unsigned int) const
15267{
15268 return 0;
15269}
15270
15271
15272template <>
15273unsigned int
15274Triangulation<1, 3>::n_raw_quads(const unsigned int) const
15275{
15276 return 0;
15277}
15278
15279
15280template <>
15281unsigned int
15282Triangulation<1, 3>::n_raw_hexs(const unsigned int) const
15283{
15284 return 0;
15285}
15286
15287
15288template <>
15289unsigned int
15291{
15292 return 0;
15293}
15294
15295
15296template <>
15297unsigned int
15299{
15300 return 0;
15301}
15302
15303#ifndef DOXYGEN
15304
15305template <int dim, int spacedim>
15307unsigned int Triangulation<dim, spacedim>::n_quads() const
15308{
15309 return number_cache.n_quads;
15310}
15311
15312
15313template <int dim, int spacedim>
15316 const unsigned int level) const
15317{
15318 Assert(dim == 2, ExcFacesHaveNoLevel());
15319 AssertIndexRange(level, number_cache.n_quads_level.size());
15320 return number_cache.n_quads_level[level];
15321}
15322
15323#endif
15324
15325template <>
15326unsigned int
15328{
15329 AssertIndexRange(level, n_levels());
15330 return levels[level]->cells.n_objects();
15331}
15332
15333
15334
15335template <>
15336unsigned int
15338{
15339 AssertIndexRange(level, n_levels());
15340 return levels[level]->cells.n_objects();
15341}
15342
15343
15344template <>
15345unsigned int
15346Triangulation<3, 3>::n_raw_quads(const unsigned int) const
15347{
15348 Assert(false, ExcFacesHaveNoLevel());
15349 return 0;
15350}
15351
15352#ifndef DOXYGEN
15353
15354template <int dim, int spacedim>
15357{
15359 return 0;
15360}
15361
15362#endif
15363
15364template <>
15365unsigned int
15367{
15368 return faces->quads.n_objects();
15369}
15370
15371#ifndef DOXYGEN
15372
15373template <int dim, int spacedim>
15376{
15377 return number_cache.n_active_quads;
15378}
15379
15380
15381template <int dim, int spacedim>
15384 const unsigned int level) const
15385{
15386 AssertIndexRange(level, number_cache.n_quads_level.size());
15387 Assert(dim == 2, ExcFacesHaveNoLevel());
15388
15389 return number_cache.n_active_quads_level[level];
15390}
15391
15392
15393template <int dim, int spacedim>
15395unsigned int Triangulation<dim, spacedim>::n_hexs() const
15396{
15397 return 0;
15398}
15399
15400
15401
15402template <int dim, int spacedim>
15404unsigned int Triangulation<dim, spacedim>::n_hexs(const unsigned int) const
15405{
15406 return 0;
15407}
15408
15409
15410
15411template <int dim, int spacedim>
15413unsigned int Triangulation<dim, spacedim>::n_raw_hexs(const unsigned int) const
15414{
15415 return 0;
15416}
15417
15418
15419template <int dim, int spacedim>
15422{
15423 return 0;
15424}
15425
15426
15427
15428template <int dim, int spacedim>
15431 const unsigned int) const
15432{
15433 return 0;
15434}
15435
15436#endif
15437
15438template <>
15439unsigned int
15441{
15442 return number_cache.n_hexes;
15443}
15444
15445
15446
15447template <>
15448unsigned int
15449Triangulation<3, 3>::n_hexs(const unsigned int level) const
15450{
15451 AssertIndexRange(level, number_cache.n_hexes_level.size());
15452
15453 return number_cache.n_hexes_level[level];
15454}
15455
15456
15457
15458template <>
15459unsigned int
15461{
15462 AssertIndexRange(level, n_levels());
15463 return levels[level]->cells.n_objects();
15464}
15465
15466
15467template <>
15468unsigned int
15470{
15471 return number_cache.n_active_hexes;
15472}
15473
15474
15475
15476template <>
15477unsigned int
15479{
15480 AssertIndexRange(level, number_cache.n_hexes_level.size());
15481
15482 return number_cache.n_active_hexes_level[level];
15483}
15484
15485#ifndef DOXYGEN
15486
15487template <int dim, int spacedim>
15490{
15491 return std::count(vertices_used.begin(), vertices_used.end(), true);
15492}
15493
15494
15495
15496template <int dim, int spacedim>
15498const std::vector<bool> &Triangulation<dim, spacedim>::get_used_vertices() const
15499{
15500 return vertices_used;
15501}
15502
15503#endif
15504
15505template <>
15506unsigned int
15508{
15509 return 2;
15510}
15511
15512
15513
15514template <>
15515unsigned int
15517{
15518 return 2;
15519}
15520
15521
15522template <>
15523unsigned int
15525{
15526 return 2;
15527}
15528
15529#ifndef DOXYGEN
15530
15531template <int dim, int spacedim>
15534{
15535 cell_iterator cell = begin(0),
15536 endc = (n_levels() > 1 ? begin(1) : cell_iterator(end()));
15537 // store the largest index of the
15538 // vertices used on level 0
15539 unsigned int max_vertex_index = 0;
15540 for (; cell != endc; ++cell)
15541 for (const unsigned int vertex : GeometryInfo<dim>::vertex_indices())
15542 if (cell->vertex_index(vertex) > max_vertex_index)
15543 max_vertex_index = cell->vertex_index(vertex);
15544
15545 // store the number of times a cell
15546 // touches a vertex. An unsigned
15547 // int should suffice, even for
15548 // larger dimensions
15549 std::vector<unsigned short int> usage_count(max_vertex_index + 1, 0);
15550 // touch a vertex's usage count
15551 // every time we find an adjacent
15552 // element
15553 for (cell = begin(); cell != endc; ++cell)
15554 for (const unsigned int vertex : GeometryInfo<dim>::vertex_indices())
15555 ++usage_count[cell->vertex_index(vertex)];
15556
15558 static_cast<unsigned int>(
15559 *std::max_element(usage_count.begin(), usage_count.end())));
15560}
15561
15562
15563
15564template <int dim, int spacedim>
15568{
15570}
15571
15572
15573
15574template <int dim, int spacedim>
15577{
15578 return *this;
15579}
15580
15581
15582
15583template <int dim, int spacedim>
15587{
15588 return *this;
15589}
15590
15591
15592
15593template <int dim, int spacedim>
15597 &periodicity_vector)
15598{
15599 periodic_face_pairs_level_0.insert(periodic_face_pairs_level_0.end(),
15600 periodicity_vector.begin(),
15601 periodicity_vector.end());
15602
15603 // Now initialize periodic_face_map
15604 update_periodic_face_map();
15605}
15606
15607
15608
15609template <int dim, int spacedim>
15611const typename std::map<
15612 std::pair<typename Triangulation<dim, spacedim>::cell_iterator, unsigned int>,
15613 std::pair<std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
15614 unsigned int>,
15615 unsigned char>>
15617{
15618 return periodic_face_map;
15619}
15620
15621
15622template <int dim, int spacedim>
15625{
15626 // We only update the cell relations here for serial triangulations.
15627 // For other triangulations, this is done at other stages of
15628 // mesh creation and mesh refinement.
15630 this))
15631 return;
15632
15633 this->local_cell_relations.clear();
15634 this->local_cell_relations.reserve(this->n_active_cells());
15635
15636 for (const auto &cell : this->active_cell_iterators())
15637 this->local_cell_relations.emplace_back(
15638 cell, ::CellStatus::cell_will_persist);
15639}
15640
15641
15642
15643template <int dim, int spacedim>
15646{
15648 this))
15649 return;
15650
15651 std::vector<CellId> active_cell_old;
15652
15653 // pack data before triangulation gets updated
15654 if (this->cell_attached_data.n_attached_data_sets > 0)
15655 {
15656 // store old active cells to determine cell status after
15657 // coarsening/refinement
15658 active_cell_old.reserve(this->n_active_cells());
15659
15660 for (const auto &cell : this->active_cell_iterators())
15661 {
15662 const bool children_will_be_coarsened =
15663 (cell->level() > 0) && (cell->coarsen_flag_set());
15664
15665 if (children_will_be_coarsened == false)
15666 active_cell_old.emplace_back(cell->id());
15667 else
15668 {
15669 if (cell->parent()->child(0) == cell)
15670 active_cell_old.emplace_back(cell->parent()->id());
15671 }
15672 }
15673
15674 // update cell relations
15675 this->local_cell_relations.clear();
15676 this->local_cell_relations.reserve(this->n_global_active_cells());
15677
15678 std::vector<
15679 std::pair<unsigned int,
15681 cell_relation_t>>
15682 local_cell_relations_tmp;
15683
15684 for (const auto &cell : this->active_cell_iterators())
15685 {
15686 if (std::find(active_cell_old.begin(),
15687 active_cell_old.end(),
15688 cell->id()) != active_cell_old.end())
15689 {
15690 const unsigned int index =
15691 std::distance(active_cell_old.begin(),
15692 std::find(active_cell_old.begin(),
15693 active_cell_old.end(),
15694 cell->id()));
15695
15696 ::CellStatus status =
15697 cell->refine_flag_set() ?
15700
15701 local_cell_relations_tmp.emplace_back(
15702 index,
15704 cell_relation_t{cell, status});
15705 }
15706 else if (cell->level() > 0 &&
15707 std::find(active_cell_old.begin(),
15708 active_cell_old.end(),
15709 cell->parent()->id()) != active_cell_old.end())
15710 {
15711 const unsigned int index =
15712 std::distance(active_cell_old.begin(),
15713 std::find(active_cell_old.begin(),
15714 active_cell_old.end(),
15715 cell->parent()->id()));
15716
15717 ::CellStatus status;
15718
15719 if (cell->parent()->child_iterator_to_index(cell) == 0)
15721 else
15723
15724 local_cell_relations_tmp.emplace_back(
15725 index,
15727 cell_relation_t{cell->parent(), status});
15728 }
15729 else
15730 {
15732 }
15733 }
15734
15735 std::stable_sort(local_cell_relations_tmp.begin(),
15736 local_cell_relations_tmp.end(),
15737 [](const auto &a, const auto &b) {
15738 return a.first < b.first;
15739 });
15740
15741 for (const auto &tmp : local_cell_relations_tmp)
15742 this->local_cell_relations.emplace_back(tmp.second);
15743
15744 // pack data
15745 this->data_serializer.pack_data(
15746 this->local_cell_relations,
15747 this->cell_attached_data.pack_callbacks_fixed,
15748 this->cell_attached_data.pack_callbacks_variable,
15749 this->get_mpi_communicator());
15750
15751 // dummy copy of data
15752 this->data_serializer.dest_data_fixed =
15753 this->data_serializer.src_data_fixed;
15754 this->data_serializer.dest_data_variable =
15755 this->data_serializer.src_data_variable;
15756 this->data_serializer.dest_sizes_variable =
15757 this->data_serializer.src_sizes_variable;
15758 }
15759}
15760
15761
15762
15763template <int dim, int spacedim>
15766{
15768 this))
15769 return;
15770
15771 // transfer data after triangulation got updated
15772 if (this->cell_attached_data.n_attached_data_sets > 0)
15773 {
15774 std::vector<typename internal::CellAttachedDataSerializer<dim, spacedim>::
15775 cell_relation_t>
15776 temp;
15777
15778 for (const auto &cell : local_cell_relations)
15779 {
15780 if (cell.first->has_children())
15781 {
15784
15785 temp.emplace_back(cell.first->child(0),
15787 }
15788 else
15789 temp.push_back(cell);
15790 }
15791
15792 this->local_cell_relations = temp;
15793 }
15794}
15795
15796
15797
15798template <int dim, int spacedim>
15801{
15802 // Call our version of prepare_coarsening_and_refinement() even if a derived
15803 // class like parallel::distributed::Triangulation overrides it. Their
15804 // function will be called in their execute_coarsening_and_refinement()
15805 // function. Even in a distributed computation our job here is to reconstruct
15806 // the local part of the mesh and as such checking our flags is enough.
15808
15809 // verify a case with which we have had
15810 // some difficulty in the past (see the
15811 // deal.II/coarsening_* tests)
15812 if (smooth_grid & limit_level_difference_at_vertices)
15813 Assert(satisfies_level1_at_vertex_rule(*this) == true, ExcInternalError());
15814
15815 // Inform all listeners about beginning of refinement.
15816 signals.pre_refinement();
15817
15818 this->pack_data_serial();
15819
15820 execute_coarsening();
15821
15822 const DistortedCellList cells_with_distorted_children = execute_refinement();
15823
15824 // We need to update the cell relations in order to be able to
15825 // deserialize data. Later on, update_cell_relations is called to mark all
15826 // active cells with the cell_will_persist status.
15827 this->unpack_data_serial();
15828
15829 reset_cell_vertex_indices_cache();
15830
15831 // verify a case with which we have had
15832 // some difficulty in the past (see the
15833 // deal.II/coarsening_* tests)
15834 if (smooth_grid & limit_level_difference_at_vertices)
15835 Assert(satisfies_level1_at_vertex_rule(*this) == true, ExcInternalError());
15836
15837 // finally build up neighbor connectivity information, and set
15838 // active cell indices
15839 this->policy->update_neighbors(*this);
15840 reset_active_cell_indices();
15841
15842 reset_global_cell_indices(); // TODO: better place?
15843
15844 // Inform all listeners about end of refinement.
15845 signals.post_refinement();
15846
15847 AssertThrow(cells_with_distorted_children.distorted_cells.empty(),
15848 cells_with_distorted_children);
15849
15850 update_periodic_face_map();
15851
15852 if (this->cell_attached_data.n_attached_data_sets == 0)
15853 this->update_cell_relations();
15854
15855# ifdef DEBUG
15856
15857 // In debug mode, we want to check for some consistency of the
15858 // result of this function. Because there are multiple exit
15859 // paths, put this check into a ScopeExit object that is
15860 // executed on each of the exit paths.
15861 //
15862 // Specifically, check on exit of this function that if a quad
15863 // cell has been refined, all of its children have neighbors
15864 // in all directions in which the parent cell has neighbors as
15865 // well. The children's neighbors are either the parent
15866 // neighbor or the parent neighbor's children, or simply one of
15867 // the other children of the current cell. This check is
15868 // useful because if one creates a triangulation with an
15869 // inconsistently ordered set of cells (e.g., because one has
15870 // forgotten to call GridTools::consistently_order_cells()),
15871 // then this relatively simple invariant is violated -- so the
15872 // check here can be used to catch that case, at least
15873 // sometimes.
15874 //
15875 // In 1d, this situation cannot happen. In 3d, we have explicit
15876 // orientation flags to ensure that it is not necessary to re-orient
15877 // cells at the beginning. But in both cases, the invariant should
15878 // still hold as long as the cell is a hypercube.
15879 for (const auto &cell : cell_iterators())
15880 {
15881 if (cell->has_children() && cell->reference_cell().is_hyper_cube())
15882 for (const unsigned int f : cell->face_indices())
15883 if (cell->at_boundary(f) == false)
15884 {
15885 for (const auto &child : cell->child_iterators())
15886 {
15887 Assert(
15888 child->at_boundary(f) == false,
15889 ExcMessage(
15890 "We ended up with a triangulation whose child cells "
15891 "are not connected to their neighbors as expected. "
15892 "When you created the triangulation, did you forget "
15893 "to call GridTools::consistently_order_cells() "
15894 "before calling Triangulation::create_triangulation()?"));
15895 }
15896 }
15897 }
15898# endif
15899}
15900
15901
15902
15903template <int dim, int spacedim>
15906{
15907 unsigned int active_cell_index = 0;
15908 for (raw_cell_iterator cell = begin_raw(); cell != end(); ++cell)
15909 if ((cell->used() == false) || cell->has_children())
15910 cell->set_active_cell_index(numbers::invalid_unsigned_int);
15911 else
15912 {
15913 cell->set_active_cell_index(active_cell_index);
15914 ++active_cell_index;
15915 }
15916
15917 Assert(active_cell_index == n_active_cells(), ExcInternalError());
15918}
15919
15920
15921
15922template <int dim, int spacedim>
15925{
15926 {
15928 for (const auto &cell : active_cell_iterators())
15929 cell->set_global_active_cell_index(cell_index++);
15930 }
15931
15932 for (unsigned int l = 0; l < levels.size(); ++l)
15933 {
15935 for (const auto &cell : cell_iterators_on_level(l))
15936 cell->set_global_level_cell_index(cell_index++);
15937 }
15938}
15939
15940
15941
15942template <int dim, int spacedim>
15945{
15946 for (unsigned int l = 0; l < levels.size(); ++l)
15947 {
15948 constexpr unsigned int max_vertices_per_cell = 1 << dim;
15949 std::vector<unsigned int> &cache = levels[l]->cell_vertex_indices_cache;
15950 cache.clear();
15951 cache.resize(levels[l]->refine_flags.size() * max_vertices_per_cell,
15953 for (const auto &cell : cell_iterators_on_level(l))
15954 {
15955 const unsigned int my_index = cell->index() * max_vertices_per_cell;
15956
15957 // to reduce the cost of this function when passing down into quads,
15958 // then lines, then vertices, we use a more low-level access method
15959 // for hexahedral cells, where we can streamline most of the logic
15960 const ReferenceCell ref_cell = cell->reference_cell();
15961 if (ref_cell == ReferenceCells::Hexahedron)
15962 for (unsigned int face = 4; face < 6; ++face)
15963 {
15964 const auto face_iter = cell->face(face);
15965 const std::array<bool, 2> line_orientations{
15966 {face_iter->line_orientation(0),
15967 face_iter->line_orientation(1)}};
15968 std::array<unsigned int, 4> raw_vertex_indices{
15969 {face_iter->line(0)->vertex_index(1 - line_orientations[0]),
15970 face_iter->line(1)->vertex_index(1 - line_orientations[1]),
15971 face_iter->line(0)->vertex_index(line_orientations[0]),
15972 face_iter->line(1)->vertex_index(line_orientations[1])}};
15973
15974 const unsigned char combined_orientation =
15975 levels[l]->face_orientations.get_combined_orientation(
15976 cell->index() * GeometryInfo<3>::faces_per_cell + face);
15977 std::array<unsigned int, 4> vertex_order{
15978 {ref_cell.standard_to_real_face_vertex(0,
15979 face,
15980 combined_orientation),
15982 face,
15983 combined_orientation),
15985 face,
15986 combined_orientation),
15988 3, face, combined_orientation)}};
15989
15990 const unsigned int index = my_index + 4 * (face - 4);
15991 for (unsigned int i = 0; i < 4; ++i)
15992 cache[index + i] = raw_vertex_indices[vertex_order[i]];
15993 }
15994 else if (ref_cell == ReferenceCells::Quadrilateral)
15995 {
15996 const std::array<bool, 2> line_orientations{
15997 {cell->line_orientation(0), cell->line_orientation(1)}};
15998 std::array<unsigned int, 4> raw_vertex_indices{
15999 {cell->line(0)->vertex_index(1 - line_orientations[0]),
16000 cell->line(1)->vertex_index(1 - line_orientations[1]),
16001 cell->line(0)->vertex_index(line_orientations[0]),
16002 cell->line(1)->vertex_index(line_orientations[1])}};
16003 for (unsigned int i = 0; i < 4; ++i)
16004 cache[my_index + i] = raw_vertex_indices[i];
16005 }
16006 else
16007 for (const unsigned int i : cell->vertex_indices())
16008 cache[my_index + i] = internal::TriaAccessorImplementation::
16009 Implementation::vertex_index(*cell, i);
16010 }
16011 }
16012}
16013
16014
16015
16016template <int dim, int spacedim>
16019{
16020 // first empty the currently stored objects
16021 periodic_face_map.clear();
16022
16023 typename std::vector<
16025 for (it = periodic_face_pairs_level_0.begin();
16026 it != periodic_face_pairs_level_0.end();
16027 ++it)
16028 {
16029 update_periodic_face_map_recursively<dim, spacedim>(it->cell[0],
16030 it->cell[1],
16031 it->face_idx[0],
16032 it->face_idx[1],
16033 it->orientation,
16034 periodic_face_map);
16035
16036 const auto face_reference_cell =
16037 it->cell[0]->reference_cell().face_reference_cell(it->face_idx[0]);
16038 // for the other way, we need to invert the orientation
16039 update_periodic_face_map_recursively<dim, spacedim>(
16040 it->cell[1],
16041 it->cell[0],
16042 it->face_idx[1],
16043 it->face_idx[0],
16044 face_reference_cell.get_inverse_combined_orientation(it->orientation),
16045 periodic_face_map);
16046 }
16047
16048 // check consistency
16049 typename std::map<std::pair<cell_iterator, unsigned int>,
16050 std::pair<std::pair<cell_iterator, unsigned int>,
16051 unsigned char>>::const_iterator it_test;
16052 for (it_test = periodic_face_map.begin(); it_test != periodic_face_map.end();
16053 ++it_test)
16054 {
16056 it_test->first.first;
16058 it_test->second.first.first;
16059 if (cell_1->level() == cell_2->level())
16060 {
16061 // if both cells have the same neighbor, then the same pair
16062 // order swapped has to be in the map
16063 Assert(periodic_face_map[it_test->second.first].first ==
16064 it_test->first,
16066 }
16067 }
16068}
16069
16070
16071
16072template <int dim, int spacedim>
16075{
16076 std::set<ReferenceCell> reference_cells_set;
16077 for (auto cell : active_cell_iterators())
16078 if (cell->is_locally_owned())
16079 reference_cells_set.insert(cell->reference_cell());
16080
16081 this->reference_cells =
16082 std::vector<ReferenceCell>(reference_cells_set.begin(),
16083 reference_cells_set.end());
16084}
16085
16086
16087
16088template <int dim, int spacedim>
16090const std::vector<ReferenceCell>
16092{
16093 return this->reference_cells;
16094}
16095
16096
16097
16098template <int dim, int spacedim>
16101{
16102 Assert(this->reference_cells.size() > 0,
16103 ExcMessage("You can't ask about the kinds of reference "
16104 "cells used by this triangulation if the "
16105 "triangulation doesn't yet have any cells in it."));
16106 return (this->reference_cells.size() == 1 &&
16107 this->reference_cells[0].is_hyper_cube());
16108}
16109
16110
16111
16112template <int dim, int spacedim>
16115{
16116 Assert(this->reference_cells.size() > 0,
16117 ExcMessage("You can't ask about the kinds of reference "
16118 "cells used by this triangulation if the "
16119 "triangulation doesn't yet have any cells in it."));
16120 return (this->reference_cells.size() == 1 &&
16121 this->reference_cells[0].is_simplex());
16122}
16123
16124
16125
16126template <int dim, int spacedim>
16129{
16130 Assert(this->reference_cells.size() > 0,
16131 ExcMessage("You can't ask about the kinds of reference "
16132 "cells used by this triangulation if the "
16133 "triangulation doesn't yet have any cells in it."));
16134 return reference_cells.size() > 1 ||
16135 ((reference_cells[0].is_hyper_cube() == false) &&
16136 (reference_cells[0].is_simplex() == false));
16137}
16138
16139
16140
16141template <int dim, int spacedim>
16144 const std::function<std::vector<char>(const cell_iterator &,
16145 const ::CellStatus)>
16146 &pack_callback,
16147 const bool returns_variable_size_data)
16148{
16149 unsigned int handle = numbers::invalid_unsigned_int;
16150
16151 // Add new callback function to the corresponding register.
16152 // Encode handles according to returns_variable_size_data.
16153 if (returns_variable_size_data)
16154 {
16155 handle = 2 * this->cell_attached_data.pack_callbacks_variable.size();
16156 this->cell_attached_data.pack_callbacks_variable.push_back(pack_callback);
16157 }
16158 else
16159 {
16160 handle = 2 * this->cell_attached_data.pack_callbacks_fixed.size() + 1;
16161 this->cell_attached_data.pack_callbacks_fixed.push_back(pack_callback);
16162 }
16163
16164 // Increase overall counter.
16165 ++this->cell_attached_data.n_attached_data_sets;
16166
16167 return handle;
16168}
16169
16170
16171
16172template <int dim, int spacedim>
16175 const unsigned int handle,
16176 const std::function<
16177 void(const cell_iterator &,
16178 const ::CellStatus,
16179 const boost::iterator_range<std::vector<char>::const_iterator> &)>
16180 &unpack_callback)
16181{
16182 // perform unpacking
16183 this->data_serializer.unpack_data(this->local_cell_relations,
16184 handle,
16185 unpack_callback);
16186
16187 // decrease counters
16188 --this->cell_attached_data.n_attached_data_sets;
16189 if (this->cell_attached_data.n_attached_deserialize > 0)
16190 --this->cell_attached_data.n_attached_deserialize;
16191
16192 // important: only remove data if we are not in the deserialization
16193 // process. There, each SolutionTransfer registers and unpacks before
16194 // the next one does this, so n_attached_data_sets is only 1 here. This
16195 // would destroy the saved data before the second SolutionTransfer can
16196 // get it. This created a bug that is documented in
16197 // tests/mpi/p4est_save_03 with more than one SolutionTransfer.
16198
16199 if (this->cell_attached_data.n_attached_data_sets == 0 &&
16200 this->cell_attached_data.n_attached_deserialize == 0)
16201 {
16202 // everybody got their data, time for cleanup!
16203 this->cell_attached_data.pack_callbacks_fixed.clear();
16204 this->cell_attached_data.pack_callbacks_variable.clear();
16205 this->data_serializer.clear();
16206
16207 // reset all cell_status entries after coarsening/refinement
16208 for (auto &cell_rel : this->local_cell_relations)
16209 cell_rel.second = ::CellStatus::cell_will_persist;
16210 }
16211}
16212
16213
16214
16215template <int dim, int spacedim>
16218 const unsigned int global_first_cell,
16219 const unsigned int global_num_cells,
16220 const std::string &file_basename) const
16221{
16222 // cast away constness
16223 auto tria = const_cast<Triangulation<dim, spacedim> *>(this);
16224
16225 // each cell should have been flagged `CellStatus::cell_will_persist`
16226 for (const auto &cell_rel : this->local_cell_relations)
16227 {
16228 (void)cell_rel;
16229 Assert((cell_rel.second == // cell_status
16232 }
16233
16234 if (this->cell_attached_data.n_attached_data_sets > 0)
16235 {
16236 // pack attached data first
16237 tria->data_serializer.pack_data(
16238 tria->local_cell_relations,
16239 tria->cell_attached_data.pack_callbacks_fixed,
16240 tria->cell_attached_data.pack_callbacks_variable,
16241 this->get_mpi_communicator());
16242
16243 // then store buffers in file
16244 tria->data_serializer.save(global_first_cell,
16245 global_num_cells,
16246 file_basename,
16247 this->get_mpi_communicator());
16248
16249 // and release the memory afterwards
16250 tria->data_serializer.clear();
16251 }
16252
16253 // clear all of the callback data, as explained in the documentation of
16254 // register_data_attach()
16255 {
16256 tria->cell_attached_data.n_attached_data_sets = 0;
16257 tria->cell_attached_data.pack_callbacks_fixed.clear();
16258 tria->cell_attached_data.pack_callbacks_variable.clear();
16259 }
16260}
16261
16262
16263template <int dim, int spacedim>
16266 const unsigned int global_first_cell,
16267 const unsigned int global_num_cells,
16268 const unsigned int local_num_cells,
16269 const std::string &file_basename,
16270 const unsigned int n_attached_deserialize_fixed,
16271 const unsigned int n_attached_deserialize_variable)
16272{
16273 // load saved data, if any was stored
16274 if (this->cell_attached_data.n_attached_deserialize > 0)
16275 {
16276 this->data_serializer.load(global_first_cell,
16277 global_num_cells,
16278 local_num_cells,
16279 file_basename,
16280 n_attached_deserialize_fixed,
16281 n_attached_deserialize_variable,
16282 this->get_mpi_communicator());
16283
16284 this->data_serializer.unpack_cell_status(this->local_cell_relations);
16285
16286# ifdef DEBUG
16287 // the CellStatus of all stored cells should always be
16288 // CellStatus::cell_will_persist.
16289 for (const auto &cell_rel : this->local_cell_relations)
16290 {
16291 Assert((cell_rel.second == // cell_status
16294 }
16295# endif
16296 }
16297}
16298
16299
16300template <int dim, int spacedim>
16303{
16304 levels.clear();
16305 faces.reset();
16306
16307 vertices.clear();
16308 vertices_used.clear();
16309
16310 manifolds.clear();
16311
16312 // In 1d, also reset vertex-to-(boundary|manifold) maps to empty maps
16313 if (dim == 1)
16314 {
16315 Assert(vertex_to_boundary_id_map_1d != nullptr, ExcInternalError());
16316 vertex_to_boundary_id_map_1d->clear();
16317
16318 Assert(vertex_to_manifold_id_map_1d != nullptr, ExcInternalError());
16319 vertex_to_manifold_id_map_1d->clear();
16320 }
16321 else
16322 {
16323 // For dim>1, these maps should simply not exist.
16324 Assert(vertex_to_boundary_id_map_1d == nullptr, ExcInternalError());
16325 Assert(vertex_to_manifold_id_map_1d == nullptr, ExcInternalError());
16326 }
16327
16328
16330}
16331
16332
16333
16334template <int dim, int spacedim>
16338{
16339 const DistortedCellList cells_with_distorted_children =
16340 this->policy->execute_refinement(*this, check_for_distorted_cells);
16341
16342
16343
16344 // re-compute number of lines
16346 *this, levels.size(), number_cache);
16347
16348# ifdef DEBUG
16349 for (const auto &level : levels)
16350 monitor_memory(level->cells, dim);
16351
16352 // check whether really all refinement flags are reset (also of
16353 // previously non-active cells which we may not have touched. If the
16354 // refinement flag of a non-active cell is set, something went wrong
16355 // since the cell-accessors should have caught this)
16356 for (const auto &cell : this->cell_iterators())
16357 Assert(!cell->refine_flag_set(), ExcInternalError());
16358# endif
16359
16360 return cells_with_distorted_children;
16361}
16362
16363
16364
16365template <int dim, int spacedim>
16368{
16369 // first find out if there are any cells at all to be coarsened in the
16370 // loop below
16371 const cell_iterator endc = end();
16372 bool do_coarsen = false;
16373 if (levels.size() >= 2)
16374 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
16375 if (!cell->is_active() && cell->child(0)->coarsen_flag_set())
16376 {
16377 do_coarsen = true;
16378 break;
16379 }
16380
16381 if (!do_coarsen)
16382 return;
16383
16384 // create a vector counting for each line and quads how many cells contain
16385 // the respective object. this is used later to decide which lines can be
16386 // deleted after coarsening a cell.
16387 std::vector<unsigned int> line_cell_count(dim > 1 ? this->n_raw_lines() : 0);
16388 std::vector<unsigned int> quad_cell_count(dim > 2 ? this->n_raw_quads() : 0);
16389 if (dim > 1)
16390 for (const auto &cell : this->cell_iterators())
16391 {
16392 if (dim > 2)
16393 {
16394 const auto line_indices = internal::TriaAccessorImplementation::
16395 Implementation::get_line_indices_of_cell(*cell);
16396 // avoid a compiler warning by fixing the max number of
16397 // loop iterations to 12
16398 const unsigned int n_lines = std::min(cell->n_lines(), 12u);
16399 for (unsigned int l = 0; l < n_lines; ++l)
16400 ++line_cell_count[line_indices[l]];
16401 for (const unsigned int q : cell->face_indices())
16402 ++quad_cell_count[cell->face_index(q)];
16403 }
16404 else
16405 for (unsigned int l = 0; l < cell->n_lines(); ++l)
16406 ++line_cell_count[cell->line(l)->index()];
16407 }
16408
16409 // Since the loop goes over used cells we only need not worry about
16410 // deleting some cells since the ++operator will then just hop over them
16411 // if we should hit one. Do the loop in the reverse way since we may
16412 // only delete some cells if their neighbors have already been deleted
16413 // (if the latter are on a higher level for example). In effect, only
16414 // those cells are deleted of which originally all children were flagged
16415 // and for which all children are on the same refinement level. Note
16416 // that because of the effects of
16417 // @p{fix_coarsen_flags}, of a cell either all or no children must be
16418 // flagged for coarsening, so it is ok to only check the first child
16419 //
16420 // since we delete the *children* of cells, we can ignore cells on the
16421 // highest level, i.e., level must be less than or equal to
16422 // n_levels()-2.
16423 if (levels.size() >= 2)
16424 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
16425 if (!cell->is_active() && cell->child(0)->coarsen_flag_set())
16426 {
16427 for (unsigned int child = 0; child < cell->n_children(); ++child)
16428 {
16429 Assert(cell->child(child)->coarsen_flag_set(),
16431 cell->child(child)->clear_coarsen_flag();
16432 }
16433 // inform all listeners that cell coarsening is going to happen
16434 signals.pre_coarsening_on_cell(cell);
16435 // use a separate function, since this is dimension specific
16436 this->policy->delete_children(*this,
16437 cell,
16438 line_cell_count,
16439 quad_cell_count);
16440 }
16441
16442 // re-compute number of lines and quads
16444 *this, levels.size(), number_cache);
16445}
16446
16447
16448
16449template <int dim, int spacedim>
16452{
16453 // copy a piece of code from prepare_coarsening_and_refinement that
16454 // ensures that the level difference at vertices is limited if so
16455 // desired. we need this code here since at least in 1d we don't
16456 // call the dimension-independent version of
16457 // prepare_coarsening_and_refinement function. in 2d and 3d, having
16458 // this hunk here makes our lives a bit easier as well as it takes
16459 // care of these cases earlier than it would otherwise happen.
16460 //
16461 // the main difference to the code in p_c_and_r is that here we
16462 // absolutely have to make sure that we get things right, i.e. that
16463 // in particular we set flags right if
16464 // limit_level_difference_at_vertices is set. to do so we iterate
16465 // until the flags don't change any more
16466 auto previous_coarsen_flags = internal::extract_raw_coarsen_flags(levels);
16467
16468 bool continue_iterating = true;
16469
16470 do
16471 {
16472 if (smooth_grid & limit_level_difference_at_vertices)
16473 {
16474 Assert(!anisotropic_refinement,
16475 ExcMessage("In case of anisotropic refinement the "
16476 "limit_level_difference_at_vertices flag for "
16477 "mesh smoothing must not be set!"));
16478
16479 // store highest level one of the cells adjacent to a vertex
16480 // belongs to
16481 std::vector<int> vertex_level(vertices.size(), 0);
16482 for (const auto &cell : this->active_cell_iterators())
16483 {
16484 if (cell->refine_flag_set())
16485 for (const unsigned int vertex : cell->vertex_indices())
16486 vertex_level[cell->vertex_index(vertex)] =
16487 std::max(vertex_level[cell->vertex_index(vertex)],
16488 cell->level() + 1);
16489 else if (!cell->coarsen_flag_set())
16490 for (const unsigned int vertex : cell->vertex_indices())
16491 vertex_level[cell->vertex_index(vertex)] =
16492 std::max(vertex_level[cell->vertex_index(vertex)],
16493 cell->level());
16494 else
16495 {
16496 // if coarsen flag is set then tentatively assume
16497 // that the cell will be coarsened. this isn't
16498 // always true (the coarsen flag could be removed
16499 // again) and so we may make an error here. we try
16500 // to correct this by iterating over the entire
16501 // process until we are converged
16502 Assert(cell->coarsen_flag_set(), ExcInternalError());
16503 for (const unsigned int vertex : cell->vertex_indices())
16504 vertex_level[cell->vertex_index(vertex)] =
16505 std::max(vertex_level[cell->vertex_index(vertex)],
16506 cell->level() - 1);
16507 }
16508 }
16509
16510
16511 // loop over all cells in reverse order. do so because we
16512 // can then update the vertex levels on the adjacent
16513 // vertices and maybe already flag additional cells in this
16514 // loop
16515 //
16516 // note that not only may we have to add additional
16517 // refinement flags, but we will also have to remove
16518 // coarsening flags on cells adjacent to vertices that will
16519 // see refinement
16520 active_cell_iterator endc = end();
16521 for (active_cell_iterator cell = last_active(); cell != endc; --cell)
16522 if (cell->refine_flag_set() == false)
16523 {
16524 for (const unsigned int vertex : cell->vertex_indices())
16525 if (vertex_level[cell->vertex_index(vertex)] >=
16526 cell->level() + 1)
16527 {
16528 // remove coarsen flag...
16529 cell->clear_coarsen_flag();
16530
16531 // ...and if necessary also refine the current
16532 // cell, at the same time updating the level
16533 // information about vertices
16534 if (vertex_level[cell->vertex_index(vertex)] >
16535 cell->level() + 1)
16536 {
16537 cell->set_refine_flag();
16538
16539 for (const unsigned int v : cell->vertex_indices())
16540 vertex_level[cell->vertex_index(v)] =
16541 std::max(vertex_level[cell->vertex_index(v)],
16542 cell->level() + 1);
16543 }
16544
16545 // continue and see whether we may, for example,
16546 // go into the inner 'if' above based on a
16547 // different vertex
16548 }
16549 }
16550 }
16551
16552 // loop over all cells and remove the coarsen flags for those cells that
16553 // have sister cells not marked for coarsening, or where some neighbors
16554 // are more refined.
16555
16556 // Coarsen flags of cells with no mother cell, i.e. on the
16557 // coarsest level, are deleted explicitly.
16558 for (const auto &acell : this->active_cell_iterators_on_level(0))
16559 acell->clear_coarsen_flag();
16560
16561 const cell_iterator endc = end();
16562 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
16563 {
16564 // nothing to do if we are already on the finest level
16565 if (cell->is_active())
16566 continue;
16567
16568 const unsigned int n_children = cell->n_children();
16569 unsigned int flagged_children = 0;
16570 for (unsigned int child = 0; child < n_children; ++child)
16571 {
16572 const auto child_cell = cell->child(child);
16573 if (child_cell->is_active() && child_cell->coarsen_flag_set())
16574 {
16575 ++flagged_children;
16576 // clear flag since we don't need it anymore
16577 child_cell->clear_coarsen_flag();
16578 }
16579 }
16580
16581 // flag the children for coarsening again if all children were
16582 // flagged and if the policy allows it
16583 if (flagged_children == n_children &&
16584 this->policy->coarsening_allowed(cell))
16585 for (unsigned int c = 0; c < n_children; ++c)
16586 {
16587 Assert(cell->child(c)->refine_flag_set() == false,
16589
16590 cell->child(c)->set_coarsen_flag();
16591 }
16592 }
16593
16594 // now see if anything has changed in the last iteration of this
16595 // function
16596 auto current_coarsen_flags = internal::extract_raw_coarsen_flags(levels);
16597
16598 continue_iterating = (current_coarsen_flags != previous_coarsen_flags);
16599 previous_coarsen_flags.swap(current_coarsen_flags);
16600 }
16601 while (continue_iterating == true);
16602}
16603
16604#endif
16605
16606// TODO: merge the following 3 functions since they are the same
16607template <>
16608bool
16610{
16611 // save the flags to determine whether something was changed in the
16612 // course of this function
16613 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
16614
16615 // do nothing in 1d, except setting the coarsening flags correctly
16616 fix_coarsen_flags();
16617
16618 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
16619
16620 return (flags_before != flags_after);
16621}
16622
16623
16624
16625template <>
16626bool
16628{
16629 // save the flags to determine whether something was changed in the
16630 // course of this function
16631 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
16632
16633 // do nothing in 1d, except setting the coarsening flags correctly
16634 fix_coarsen_flags();
16635
16636 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
16637
16638 return (flags_before != flags_after);
16639}
16640
16641
16642
16643template <>
16644bool
16646{
16647 // save the flags to determine whether something was changed in the
16648 // course of this function
16649 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
16650
16651 // do nothing in 1d, except setting the coarsening flags correctly
16652 fix_coarsen_flags();
16653
16654 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
16655
16656 return (flags_before != flags_after);
16657}
16658
16659
16660
16661namespace
16662{
16663 // check if the given @param cell marked for coarsening would
16664 // produce an unrefined island. To break up long chains of these
16665 // cells we recursively check our neighbors in case we change this
16666 // cell. This reduces the number of outer iterations dramatically.
16667 template <int dim, int spacedim>
16668 void
16669 possibly_do_not_produce_unrefined_islands(
16671 {
16672 Assert(cell->has_children(), ExcInternalError());
16673
16674 unsigned int n_neighbors = 0;
16675 // count all neighbors that will be refined along the face of our
16676 // cell after the next step
16677 unsigned int count = 0;
16678 for (const unsigned int n : GeometryInfo<dim>::face_indices())
16679 {
16680 const typename Triangulation<dim, spacedim>::cell_iterator neighbor =
16681 cell->neighbor(n);
16682 if (neighbor.state() == IteratorState::valid)
16683 {
16684 ++n_neighbors;
16685 if (face_will_be_refined_by_neighbor(cell, n))
16686 ++count;
16687 }
16688 }
16689 // clear coarsen flags if either all existing neighbors will be
16690 // refined or all but one will be and the cell is in the interior
16691 // of the domain
16692 if (count == n_neighbors ||
16693 (count >= n_neighbors - 1 &&
16694 n_neighbors == GeometryInfo<dim>::faces_per_cell))
16695 {
16696 for (unsigned int c = 0; c < cell->n_children(); ++c)
16697 cell->child(c)->clear_coarsen_flag();
16698
16699 for (const unsigned int face : GeometryInfo<dim>::face_indices())
16700 if (!cell->at_boundary(face) &&
16701 (!cell->neighbor(face)->is_active()) &&
16702 (cell_will_be_coarsened(cell->neighbor(face))))
16703 possibly_do_not_produce_unrefined_islands<dim, spacedim>(
16704 cell->neighbor(face));
16705 }
16706 }
16707
16708
16709 // see if the current cell needs to be refined to avoid unrefined
16710 // islands.
16711 //
16712 // there are sometimes chains of cells that induce refinement of
16713 // each other. to avoid running the loop in
16714 // prepare_coarsening_and_refinement over and over again for each
16715 // one of them, at least for the isotropic refinement case we seek
16716 // to flag neighboring elements as well as necessary. this takes
16717 // care of (slightly pathological) cases like
16718 // deal.II/mesh_smoothing_03
16719 template <int dim, int spacedim>
16720 void
16721 possibly_refine_unrefined_island(
16723 const bool allow_anisotropic_smoothing)
16724 {
16725 Assert(cell->is_active(), ExcInternalError());
16726
16727#ifdef DEBUG
16728 // If this is not a parallel::distributed::Triangulation, then we really
16729 // should only get here if the cell is marked for refinement:
16731 *>(&cell->get_triangulation()) == nullptr)
16732 Assert(cell->refine_flag_set() == false, ExcInternalError());
16733 else
16734 // But if this is a p::d::Triangulation, then we don't have that
16735 // much control and we can get here because mesh smoothing is
16736 // requested but can not be honored because p4est controls
16737 // what gets refined. In that case, we can at least provide
16738 // a better error message.
16739 Assert(cell->refine_flag_set() == false,
16740 ExcMessage(
16741 "The triangulation is trying to avoid unrefined islands "
16742 "during mesh refinement/coarsening, as you had requested "
16743 " by passing the appropriate 'smoothing flags' to the "
16744 "constructor of the triangulation. However, for objects "
16745 "of type parallel::distributed::Triangulation, control "
16746 "over which cells get refined rests with p4est, not the "
16747 "deal.II triangulation, and consequently it is not "
16748 "always possible to avoid unrefined islands in the mesh. "
16749 "Please remove the constructor argument to the triangulation "
16750 "object that requests mesh smoothing."));
16751#endif
16752
16753 // now we provide two algorithms. the first one is the standard
16754 // one, coming from the time, where only isotropic refinement was
16755 // possible. it simply counts the neighbors that are or will be
16756 // refined and compares to the number of other ones. the second
16757 // one does this check independently for each direction: if all
16758 // neighbors in one direction (normally two, at the boundary only
16759 // one) are refined, the current cell is flagged to be refined in
16760 // an according direction.
16761
16762 if (allow_anisotropic_smoothing == false)
16763 {
16764 // use first algorithm
16765 unsigned int refined_neighbors = 0, unrefined_neighbors = 0;
16766 for (const unsigned int face : GeometryInfo<dim>::face_indices())
16767 if (!cell->at_boundary(face))
16768 {
16769 if (face_will_be_refined_by_neighbor(cell, face))
16770 ++refined_neighbors;
16771 else
16772 ++unrefined_neighbors;
16773 }
16774
16775 if (unrefined_neighbors < refined_neighbors)
16776 {
16777 cell->clear_coarsen_flag();
16778 cell->set_refine_flag();
16779
16780 // ok, so now we have flagged this cell. if we know that
16781 // there were any unrefined neighbors at all, see if any
16782 // of those will have to be refined as well
16783 if (unrefined_neighbors > 0)
16784 for (const unsigned int face : GeometryInfo<dim>::face_indices())
16785 if (!cell->at_boundary(face) &&
16786 (face_will_be_refined_by_neighbor(cell, face) == false) &&
16787 (cell->neighbor(face)->has_children() == false) &&
16788 (cell->neighbor(face)->refine_flag_set() == false))
16789 possibly_refine_unrefined_island<dim, spacedim>(
16790 cell->neighbor(face), allow_anisotropic_smoothing);
16791 }
16792 }
16793 else
16794 {
16795 // variable to store the cell refine case needed to fulfill
16796 // all smoothing requirements
16797 RefinementCase<dim> smoothing_cell_refinement_case =
16799
16800 // use second algorithm, do the check individually for each
16801 // direction
16802 for (unsigned int face_pair = 0;
16803 face_pair < GeometryInfo<dim>::faces_per_cell / 2;
16804 ++face_pair)
16805 {
16806 // variable to store the cell refine case needed to refine
16807 // at the current face pair in the same way as the
16808 // neighbors do...
16809 RefinementCase<dim> directional_cell_refinement_case =
16811
16812 for (unsigned int face_index = 0; face_index < 2; ++face_index)
16813 {
16814 unsigned int face = 2 * face_pair + face_index;
16815 // variable to store the refine case (to come) of the
16816 // face under consideration
16817 RefinementCase<dim - 1> expected_face_ref_case =
16818 RefinementCase<dim - 1>::no_refinement;
16819
16820 if (cell->neighbor(face).state() == IteratorState::valid)
16821 face_will_be_refined_by_neighbor<dim, spacedim>(
16822 cell, face, expected_face_ref_case);
16823 // now extract which refine case would be necessary to
16824 // achieve the same face refinement. set the
16825 // intersection with other requirements for the same
16826 // direction.
16827
16828 // note: using the intersection is not an obvious
16829 // decision, we could also argue that it is more
16830 // natural to use the union. however, intersection is
16831 // the less aggressive tactic and favours a smaller
16832 // number of refined cells over an intensive
16833 // smoothing. this way we try not to lose too much of
16834 // the effort we put in anisotropic refinement
16835 // indicators due to overly aggressive smoothing...
16836 directional_cell_refinement_case =
16837 (directional_cell_refinement_case &
16840 expected_face_ref_case,
16841 face,
16842 cell->face_orientation(face),
16843 cell->face_flip(face),
16844 cell->face_rotation(face)));
16845 } // for both face indices
16846 // if both requirements sum up to something useful, add
16847 // this to the refine case for smoothing. note: if
16848 // directional_cell_refinement_case is isotropic still,
16849 // then something went wrong...
16850 Assert(directional_cell_refinement_case <
16853 smoothing_cell_refinement_case =
16854 smoothing_cell_refinement_case | directional_cell_refinement_case;
16855 } // for all face_pairs
16856 // no we collected contributions from all directions. combine
16857 // the new flags with the existing refine case, but only if
16858 // smoothing is required
16859 if (smoothing_cell_refinement_case)
16860 {
16861 cell->clear_coarsen_flag();
16862 cell->set_refine_flag(cell->refine_flag_set() |
16863 smoothing_cell_refinement_case);
16864 }
16865 }
16866 }
16867} // namespace
16868
16869#ifndef DOXYGEN
16870template <int dim, int spacedim>
16873{
16874 // save the flags to determine whether something was changed in the
16875 // course of this function
16876 const auto coarsen_flags_before = internal::extract_raw_coarsen_flags(levels);
16877 const auto refine_flags_before = internal::extract_raw_refine_flags(levels);
16878
16879 // save the flags at the outset of each loop. we do so in order to
16880 // find out whether something was changed in the present loop, in
16881 // which case we would have to re-run the loop. the other
16882 // possibility to find this out would be to set a flag
16883 // @p{something_changed} to true each time we change something.
16884 // however, sometimes one change in one of the parts of the loop is
16885 // undone by another one, so we might end up in an endless loop. we
16886 // could be tempted to break this loop at an arbitrary number of
16887 // runs, but that would not be a clean solution, since we would
16888 // either have to 1/ break the loop too early, in which case the
16889 // promise that a second call to this function immediately after the
16890 // first one does not change anything, would be broken, or 2/ we do
16891 // as many loops as there are levels. we know that information is
16892 // transported over one level in each run of the loop, so this is
16893 // enough. Unfortunately, each loop is rather expensive, so we chose
16894 // the way presented here
16895 auto coarsen_flags_before_loop = coarsen_flags_before;
16896 auto refine_flags_before_loop = refine_flags_before;
16897
16898 // now for what is done in each loop: we have to fulfill several
16899 // tasks at the same time, namely several mesh smoothing algorithms
16900 // and mesh regularization, by which we mean that the next mesh
16901 // fulfills several requirements such as no double refinement at
16902 // each face or line, etc.
16903 //
16904 // since doing these things at once seems almost impossible (in the
16905 // first year of this library, they were done in two functions, one
16906 // for refinement and one for coarsening, and most things within
16907 // these were done at once, so the code was rather impossible to
16908 // join into this, only, function), we do them one after each
16909 // other. the order in which we do them is such that the important
16910 // tasks, namely regularization, are done last and the least
16911 // important things are done the first. the following order is
16912 // chosen:
16913 //
16914 // 0/ Only if coarsest_level_1 or patch_level_1 is set: clear all
16915 // coarsen flags on level 1 to avoid level 0 cells being created
16916 // by coarsening. As coarsen flags will never be added, this can
16917 // be done once and for all before the actual loop starts.
16918 //
16919 // 1/ do not coarsen a cell if 'most of the neighbors' will be
16920 // refined after the step. This is to prevent occurrence of
16921 // unrefined islands.
16922 //
16923 // 2/ eliminate refined islands in the interior and at the
16924 // boundary. since they don't do much harm besides increasing the
16925 // number of degrees of freedom, doing this has a rather low
16926 // priority.
16927 //
16928 // 3/ limit the level difference of neighboring cells at each
16929 // vertex.
16930 //
16931 // 4/ eliminate unrefined islands. this has higher priority since
16932 // this diminishes the approximation properties not only of the
16933 // unrefined island, but also of the surrounding patch.
16934 //
16935 // 5/ ensure patch level 1. Then the triangulation consists of
16936 // patches, i.e. of cells that are refined once. It follows that
16937 // if at least one of the children of a cell is or will be
16938 // refined than all children need to be refined. This step only
16939 // sets refinement flags and does not set coarsening flags. If
16940 // the patch_level_1 flag is set, then
16941 // eliminate_unrefined_islands, eliminate_refined_inner_islands
16942 // and eliminate_refined_boundary_islands will be fulfilled
16943 // automatically and do not need to be enforced separately.
16944 //
16945 // 6/ take care of the requirement that no double refinement is done
16946 // at each face
16947 //
16948 // 7/ take care that no double refinement is done at each line in 3d
16949 // or higher dimensions.
16950 //
16951 // 8/ make sure that all children of each cell are either flagged
16952 // for coarsening or none of the children is
16953 //
16954 // For some of these steps, it is known that they interact. Namely,
16955 // it is not possible to guarantee that after step 6 another step 5
16956 // would have no effect; the same holds for the opposite order and
16957 // also when taking into account step 7. however, it is important to
16958 // guarantee that step five or six do not undo something that step 5
16959 // did, and step 7 not something of step 6, otherwise the
16960 // requirements will not be satisfied even if the loop
16961 // terminates. this is accomplished by the fact that steps 5 and 6
16962 // only *add* refinement flags and delete coarsening flags
16963 // (therefore, step 6 can't undo something that step 4 already did),
16964 // and step 7 only deletes coarsening flags, never adds some. step 7
16965 // needs also take care that it won't tag cells for refinement for
16966 // which some neighbors are more refined or will be refined.
16967
16968 //------------------------------------
16969 // STEP 0:
16970 // Only if coarsest_level_1 or patch_level_1 is set: clear all
16971 // coarsen flags on level 1 to avoid level 0 cells being created
16972 // by coarsening.
16973 if (((smooth_grid & coarsest_level_1) || (smooth_grid & patch_level_1)) &&
16974 n_levels() >= 2)
16975 {
16976 for (const auto &cell : active_cell_iterators_on_level(1))
16977 cell->clear_coarsen_flag();
16978 }
16979
16980 bool mesh_changed_in_this_loop = false;
16981 do
16982 {
16983 //------------------------------------
16984 // STEP 1:
16985 // do not coarsen a cell if 'most of the neighbors' will be
16986 // refined after the step. This is to prevent the occurrence
16987 // of unrefined islands. If patch_level_1 is set, this will
16988 // be automatically fulfilled.
16989 if (smooth_grid & do_not_produce_unrefined_islands &&
16990 !(smooth_grid & patch_level_1))
16991 {
16992 for (const auto &cell : cell_iterators())
16993 {
16994 // only do something if this
16995 // cell will be coarsened
16996 if (!cell->is_active() && cell_will_be_coarsened(cell))
16997 possibly_do_not_produce_unrefined_islands<dim, spacedim>(cell);
16998 }
16999 }
17000
17001
17002 //------------------------------------
17003 // STEP 2:
17004 // eliminate refined islands in the interior and at the
17005 // boundary. since they don't do much harm besides increasing
17006 // the number of degrees of freedom, doing this has a rather
17007 // low priority. If patch_level_1 is set, this will be
17008 // automatically fulfilled.
17009 //
17010 // there is one corner case to consider: if this is a
17011 // distributed triangulation, there may be refined islands on
17012 // the boundary of which we own only part (e.g. a single cell
17013 // in the corner of a domain). the rest of the island is
17014 // ghost cells and it *looks* like the area around it
17015 // (artificial cells) are coarser but this is only because
17016 // they may actually be equally fine on other
17017 // processors. it's hard to detect this case but we can do
17018 // the following: only set coarsen flags to remove this
17019 // refined island if all cells we want to set flags on are
17020 // locally owned
17021 if (smooth_grid & (eliminate_refined_inner_islands |
17022 eliminate_refined_boundary_islands) &&
17023 !(smooth_grid & patch_level_1))
17024 {
17025 for (const auto &cell : cell_iterators())
17026 if (!cell->is_active() ||
17027 (cell->is_active() && cell->refine_flag_set() &&
17028 cell->is_locally_owned()))
17029 {
17030 // check whether all children are active, i.e. not
17031 // refined themselves. This is a precondition that the
17032 // children may be coarsened away. If the cell is only
17033 // flagged for refinement, then all future children
17034 // will be active
17035 bool all_children_active = true;
17036 if (!cell->is_active())
17037 for (unsigned int c = 0; c < cell->n_children(); ++c)
17038 if (!cell->child(c)->is_active() ||
17039 cell->child(c)->is_ghost() ||
17040 cell->child(c)->is_artificial())
17041 {
17042 all_children_active = false;
17043 break;
17044 }
17045
17046 if (all_children_active)
17047 {
17048 // count number of refined and unrefined neighbors
17049 // of cell. neighbors on lower levels are counted
17050 // as unrefined since they can only get to the
17051 // same level as this cell by the next refinement
17052 // cycle
17053 unsigned int unrefined_neighbors = 0, total_neighbors = 0;
17054
17055 // Keep track if this cell is at a periodic
17056 // boundary or not. TODO: We do not currently run
17057 // the algorithm for inner islands at a periodic
17058 // boundary (remains to be implemented), but we
17059 // also don't want to consider them
17060 // boundary_island cells as this can interfere
17061 // with 2:1 refinement across periodic faces.
17062 // Instead: just ignore those cells for this
17063 // smoothing operation below.
17064 bool at_periodic_boundary = false;
17065
17066 for (const unsigned int n : cell->face_indices())
17067 {
17068 const cell_iterator neighbor = cell->neighbor(n);
17069 if (neighbor.state() == IteratorState::valid)
17070 {
17071 ++total_neighbors;
17072
17073 if (!face_will_be_refined_by_neighbor(cell, n))
17074 ++unrefined_neighbors;
17075 }
17076 else if (cell->has_periodic_neighbor(n))
17077 {
17078 ++total_neighbors;
17079 at_periodic_boundary = true;
17080 }
17081 }
17082
17083 // if all neighbors unrefined: mark this cell for
17084 // coarsening or don't refine if marked for that
17085 //
17086 // also do the distinction between the two
17087 // versions of the eliminate_refined_*_islands
17088 // flag
17089 //
17090 // the last check is whether there are any
17091 // neighbors at all. if not so, then we are (e.g.)
17092 // on the coarsest grid with one cell, for which,
17093 // of course, we do not remove the refine flag.
17094 if ((unrefined_neighbors == total_neighbors) &&
17095 ((!cell->at_boundary() &&
17096 (smooth_grid & eliminate_refined_inner_islands)) ||
17097 (cell->at_boundary() && !at_periodic_boundary &&
17098 (smooth_grid &
17099 eliminate_refined_boundary_islands))) &&
17100 (total_neighbors != 0))
17101 {
17102 if (!cell->is_active())
17103 for (unsigned int c = 0; c < cell->n_children(); ++c)
17104 {
17105 cell->child(c)->clear_refine_flag();
17106 cell->child(c)->set_coarsen_flag();
17107 }
17108 else
17109 cell->clear_refine_flag();
17110 }
17111 }
17112 }
17113 }
17114
17115 //------------------------------------
17116 // STEP 3:
17117 // limit the level difference of neighboring cells at each
17118 // vertex.
17119 //
17120 // in case of anisotropic refinement this does not make
17121 // sense. as soon as one cell is anisotropically refined, an
17122 // Assertion is thrown. therefore we can ignore this problem
17123 // later on
17124 if (smooth_grid & limit_level_difference_at_vertices)
17125 {
17126 Assert(!anisotropic_refinement,
17127 ExcMessage("In case of anisotropic refinement the "
17128 "limit_level_difference_at_vertices flag for "
17129 "mesh smoothing must not be set!"));
17130
17131 // store highest level one of the cells adjacent to a vertex
17132 // belongs to
17133 std::vector<int> vertex_level(vertices.size(), 0);
17134 for (const auto &cell : active_cell_iterators())
17135 {
17136 if (cell->refine_flag_set())
17137 for (const unsigned int vertex : cell->vertex_indices())
17138 vertex_level[cell->vertex_index(vertex)] =
17139 std::max(vertex_level[cell->vertex_index(vertex)],
17140 cell->level() + 1);
17141 else if (!cell->coarsen_flag_set())
17142 for (const unsigned int vertex : cell->vertex_indices())
17143 vertex_level[cell->vertex_index(vertex)] =
17144 std::max(vertex_level[cell->vertex_index(vertex)],
17145 cell->level());
17146 else
17147 {
17148 // if coarsen flag is set then tentatively assume
17149 // that the cell will be coarsened. this isn't
17150 // always true (the coarsen flag could be removed
17151 // again) and so we may make an error here
17152 Assert(cell->coarsen_flag_set(), ExcInternalError());
17153 for (const unsigned int vertex : cell->vertex_indices())
17154 vertex_level[cell->vertex_index(vertex)] =
17155 std::max(vertex_level[cell->vertex_index(vertex)],
17156 cell->level() - 1);
17157 }
17158 }
17159
17160
17161 // loop over all cells in reverse order. do so because we
17162 // can then update the vertex levels on the adjacent
17163 // vertices and maybe already flag additional cells in this
17164 // loop
17165 //
17166 // note that not only may we have to add additional
17167 // refinement flags, but we will also have to remove
17168 // coarsening flags on cells adjacent to vertices that will
17169 // see refinement
17170 for (active_cell_iterator cell = last_active(); cell != end(); --cell)
17171 if (cell->refine_flag_set() == false)
17172 {
17173 for (const unsigned int vertex : cell->vertex_indices())
17174 if (vertex_level[cell->vertex_index(vertex)] >=
17175 cell->level() + 1)
17176 {
17177 // remove coarsen flag...
17178 cell->clear_coarsen_flag();
17179
17180 // ...and if necessary also refine the current
17181 // cell, at the same time updating the level
17182 // information about vertices
17183 if (vertex_level[cell->vertex_index(vertex)] >
17184 cell->level() + 1)
17185 {
17186 cell->set_refine_flag();
17187
17188 for (const unsigned int v : cell->vertex_indices())
17189 vertex_level[cell->vertex_index(v)] =
17190 std::max(vertex_level[cell->vertex_index(v)],
17191 cell->level() + 1);
17192 }
17193
17194 // continue and see whether we may, for example,
17195 // go into the inner'if'
17196 // above based on a
17197 // different vertex
17198 }
17199 }
17200 }
17201
17202 //-----------------------------------
17203 // STEP 4:
17204 // eliminate unrefined islands. this has higher priority
17205 // since this diminishes the approximation properties not
17206 // only of the unrefined island, but also of the surrounding
17207 // patch.
17208 //
17209 // do the loop from finest to coarsest cells since we may
17210 // trigger a cascade by marking cells for refinement which
17211 // may trigger more cells further down below
17212 if (smooth_grid & eliminate_unrefined_islands)
17213 {
17214 for (active_cell_iterator cell = last_active(); cell != end(); --cell)
17215 // only do something if cell is not already flagged for
17216 // (isotropic) refinement
17217 if (cell->refine_flag_set() !=
17219 possibly_refine_unrefined_island<dim, spacedim>(
17220 cell, (smooth_grid & allow_anisotropic_smoothing) != 0);
17221 }
17222
17223 //-------------------------------
17224 // STEP 5:
17225 // ensure patch level 1.
17226 //
17227 // Introduce some terminology:
17228 // - a cell that is refined
17229 // once is a patch of
17230 // level 1 simply called patch.
17231 // - a cell that is globally
17232 // refined twice is called
17233 // a patch of level 2.
17234 // - patch level n says that
17235 // the triangulation consists
17236 // of patches of level n.
17237 // This makes sense only
17238 // if the grid is already at
17239 // least n times globally
17240 // refined.
17241 //
17242 // E.g. from patch level 1 follows: if at least one of the
17243 // children of a cell is or will be refined than enforce all
17244 // children to be refined.
17245
17246 // This step 4 only sets refinement flags and does not set
17247 // coarsening flags.
17248 if (smooth_grid & patch_level_1)
17249 {
17250 // An important assumption (A) is that before calling this
17251 // function the grid was already of patch level 1.
17252
17253 // loop over all cells whose children are all active. (By
17254 // assumption (A) either all or none of the children are
17255 // active). If the refine flag of at least one of the
17256 // children is set then set_refine_flag and
17257 // clear_coarsen_flag of all children.
17258 for (const auto &cell : cell_iterators())
17259 if (!cell->is_active())
17260 {
17261 // ensure the invariant. we can then check whether all
17262 // of its children are further refined or not by
17263 // simply looking at the first child
17264 Assert(cell_is_patch_level_1(cell), ExcInternalError());
17265 if (cell->child(0)->has_children() == true)
17266 continue;
17267
17268 // cell is found to be a patch. combine the refine
17269 // cases of all children
17270 RefinementCase<dim> combined_ref_case =
17272 for (unsigned int i = 0; i < cell->n_children(); ++i)
17273 combined_ref_case =
17274 combined_ref_case | cell->child(i)->refine_flag_set();
17275 if (combined_ref_case != RefinementCase<dim>::no_refinement)
17276 for (unsigned int i = 0; i < cell->n_children(); ++i)
17277 {
17278 cell_iterator child = cell->child(i);
17279
17280 child->clear_coarsen_flag();
17281 child->set_refine_flag(combined_ref_case);
17282 }
17283 }
17284
17285 // The code above dealt with the case where we may get a
17286 // non-patch_level_1 mesh from refinement. Now also deal
17287 // with the case where we could get such a mesh by
17288 // coarsening. Coarsen the children (and remove the
17289 // grandchildren) only if all cell->grandchild(i)
17290 // ->coarsen_flag_set() are set.
17291 //
17292 // for a case where this is a bit tricky, take a look at the
17293 // mesh_smoothing_0[12] testcases
17294 for (const auto &cell : cell_iterators())
17295 {
17296 // check if this cell has active grandchildren. note
17297 // that we know that it is patch_level_1, i.e. if one of
17298 // its children is active then so are all, and it isn't
17299 // going to have any grandchildren at all:
17300 if (cell->is_active() || cell->child(0)->is_active())
17301 continue;
17302
17303 // cell is not active, and so are none of its
17304 // children. check the grandchildren. note that the
17305 // children are also patch_level_1, and so we only ever
17306 // need to check their first child
17307 const unsigned int n_children = cell->n_children();
17308 bool has_active_grandchildren = false;
17309
17310 for (unsigned int i = 0; i < n_children; ++i)
17311 if (cell->child(i)->child(0)->is_active())
17312 {
17313 has_active_grandchildren = true;
17314 break;
17315 }
17316
17317 if (has_active_grandchildren == false)
17318 continue;
17319
17320
17321 // ok, there are active grandchildren. see if either all
17322 // or none of them are flagged for coarsening
17323 unsigned int n_grandchildren = 0;
17324
17325 // count all coarsen flags of the grandchildren.
17326 unsigned int n_coarsen_flags = 0;
17327
17328 // cell is not a patch (of level 1) as it has a
17329 // grandchild. Is cell a patch of level 2?? Therefore:
17330 // find out whether all cell->child(i) are patches
17331 for (unsigned int c = 0; c < n_children; ++c)
17332 {
17333 // get at the child. by assumption (A), and the
17334 // check by which we got here, the child is not
17335 // active
17336 cell_iterator child = cell->child(c);
17337
17338 const unsigned int nn_children = child->n_children();
17339 n_grandchildren += nn_children;
17340
17341 // if child is found to be a patch of active cells
17342 // itself, then add up how many of its children are
17343 // supposed to be coarsened
17344 if (child->child(0)->is_active())
17345 for (unsigned int cc = 0; cc < nn_children; ++cc)
17346 if (child->child(cc)->coarsen_flag_set())
17347 ++n_coarsen_flags;
17348 }
17349
17350 // if not all grandchildren are supposed to be coarsened
17351 // (e.g. because some simply don't have the flag set, or
17352 // because they are not active and therefore cannot
17353 // carry the flag), then remove the coarsen flag from
17354 // all of the active grandchildren. note that there may
17355 // be coarsen flags on the grandgrandchildren -- we
17356 // don't clear them here, but we'll get to them in later
17357 // iterations if necessary
17358 //
17359 // there is nothing we have to do if no coarsen flags
17360 // have been set at all
17361 if ((n_coarsen_flags != n_grandchildren) && (n_coarsen_flags > 0))
17362 for (unsigned int c = 0; c < n_children; ++c)
17363 {
17364 const cell_iterator child = cell->child(c);
17365 if (child->child(0)->is_active())
17366 for (unsigned int cc = 0; cc < child->n_children(); ++cc)
17367 child->child(cc)->clear_coarsen_flag();
17368 }
17369 }
17370 }
17371
17372 //--------------------------------
17373 //
17374 // at the boundary we could end up with cells with negative
17375 // volume or at least with a part, that is negative, if the
17376 // cell is refined anisotropically. we have to check, whether
17377 // that can happen
17378 this->policy->prevent_distorted_boundary_cells(*this);
17379
17380 //-------------------------------
17381 // STEP 6:
17382 // take care of the requirement that no
17383 // double refinement is done at each face
17384 //
17385 // in case of anisotropic refinement it is only likely, but
17386 // not sure, that the cells, which are more refined along a
17387 // certain face common to two cells are on a higher
17388 // level. therefore we cannot be sure, that the requirement
17389 // of no double refinement is fulfilled after a single pass
17390 // of the following actions. We could just wait for the next
17391 // global loop. when this function terminates, the
17392 // requirement will be fulfilled. However, it might be faster
17393 // to insert an inner loop here.
17394 bool changed = true;
17395 while (changed)
17396 {
17397 changed = false;
17398 active_cell_iterator cell = last_active(), endc = end();
17399
17400 for (; cell != endc; --cell)
17401 if (cell->refine_flag_set())
17402 {
17403 // loop over neighbors of cell
17404 for (const auto i : cell->face_indices())
17405 {
17406 // only do something if the face is not at the
17407 // boundary and if the face will be refined with
17408 // the RefineCase currently flagged for
17409 const bool has_periodic_neighbor =
17410 cell->has_periodic_neighbor(i);
17411 const bool has_neighbor_or_periodic_neighbor =
17412 !cell->at_boundary(i) || has_periodic_neighbor;
17413 if (has_neighbor_or_periodic_neighbor &&
17415 cell->refine_flag_set(), i) !=
17417 {
17418 // 1) if the neighbor has children: nothing to
17419 // worry about. 2) if the neighbor is active
17420 // and a coarser one, ensure, that its
17421 // refine_flag is set 3) if the neighbor is
17422 // active and as refined along the face as our
17423 // current cell, make sure, that no
17424 // coarsen_flag is set. if we remove the
17425 // coarsen flag of our neighbor,
17426 // fix_coarsen_flags() makes sure, that the
17427 // mother cell will not be coarsened
17428 if (cell->neighbor_or_periodic_neighbor(i)->is_active())
17429 {
17430 if ((!has_periodic_neighbor &&
17431 cell->neighbor_is_coarser(i)) ||
17432 (has_periodic_neighbor &&
17433 cell->periodic_neighbor_is_coarser(i)))
17434 {
17435 if (cell->neighbor_or_periodic_neighbor(i)
17436 ->coarsen_flag_set())
17437 cell->neighbor_or_periodic_neighbor(i)
17438 ->clear_coarsen_flag();
17439 // we'll set the refine flag for this
17440 // neighbor below. we note, that we
17441 // have changed something by setting
17442 // the changed flag to true. We do not
17443 // need to do so, if we just removed
17444 // the coarsen flag, as the changed
17445 // flag only indicates the need to
17446 // re-run the inner loop. however, we
17447 // only loop over cells flagged for
17448 // refinement here, so nothing to
17449 // worry about if we remove coarsen
17450 // flags
17451
17452 if (dim == 2)
17453 {
17454 if (smooth_grid &
17455 allow_anisotropic_smoothing)
17456 changed =
17457 has_periodic_neighbor ?
17458 cell->periodic_neighbor(i)
17459 ->flag_for_face_refinement(
17460 cell
17461 ->periodic_neighbor_of_coarser_periodic_neighbor(
17462 i)
17463 .first,
17465 cell->neighbor(i)
17466 ->flag_for_face_refinement(
17467 cell
17468 ->neighbor_of_coarser_neighbor(
17469 i)
17470 .first,
17472 else
17473 {
17474 if (!cell
17475 ->neighbor_or_periodic_neighbor(
17476 i)
17477 ->refine_flag_set())
17478 changed = true;
17479 cell->neighbor_or_periodic_neighbor(i)
17480 ->set_refine_flag();
17481 }
17482 }
17483 else // i.e. if (dim==3)
17484 {
17485 // ugly situations might arise here,
17486 // consider the following situation, which
17487 // shows neighboring cells at the common
17488 // face, where the upper right element is
17489 // coarser at the given face. Now the upper
17490 // child element of the lower left wants to
17491 // refine according to cut_z, such that
17492 // there is a 'horizontal' refinement of the
17493 // face marked with #####
17494 //
17495 // / /
17496 // / /
17497 // *---------------*
17498 // | |
17499 // | |
17500 // | |
17501 // | |
17502 // | |
17503 // | | /
17504 // | |/
17505 // *---------------*
17506 //
17507 //
17508 // *---------------*
17509 // /| /|
17510 // / | ##### / |
17511 // | |
17512 // *---------------*
17513 // /| /|
17514 // / | / |
17515 // | |
17516 // *---------------*
17517 // / /
17518 // / /
17519 //
17520 // this introduces too many hanging nodes
17521 // and the neighboring (coarser) cell (upper
17522 // right) has to be refined. If it is only
17523 // refined according to cut_z, then
17524 // everything is ok:
17525 //
17526 // / /
17527 // / /
17528 // *---------------*
17529 // | |
17530 // | | /
17531 // | |/
17532 // *---------------*
17533 // | |
17534 // | | /
17535 // | |/
17536 // *---------------*
17537 //
17538 //
17539 // *---------------*
17540 // /| /|
17541 // / *---------------*
17542 // /| /|
17543 // *---------------*
17544 // /| /|
17545 // / | / |
17546 // | |
17547 // *---------------*
17548 // / /
17549 // / /
17550 //
17551 // if however the cell wants to refine
17552 // itself in an other way, or if we disallow
17553 // anisotropic smoothing, then simply
17554 // refining the neighbor isotropically is
17555 // not going to work, since this introduces
17556 // a refinement of face ##### with both
17557 // cut_x and cut_y, which is not possible:
17558 //
17559 // / / /
17560 // / / /
17561 // *-------*-------*
17562 // | | |
17563 // | | | /
17564 // | | |/
17565 // *-------*-------*
17566 // | | |
17567 // | | | /
17568 // | | |/
17569 // *-------*-------*
17570 //
17571 //
17572 // *---------------*
17573 // /| /|
17574 // / *---------------*
17575 // /| /|
17576 // *---------------*
17577 // /| /|
17578 // / | / |
17579 // | |
17580 // *---------------*
17581 // / /
17582 // / /
17583 //
17584 // thus, in this case we also need to refine
17585 // our current cell in the new direction:
17586 //
17587 // / / /
17588 // / / /
17589 // *-------*-------*
17590 // | | |
17591 // | | | /
17592 // | | |/
17593 // *-------*-------*
17594 // | | |
17595 // | | | /
17596 // | | |/
17597 // *-------*-------*
17598 //
17599 //
17600 // *-------*-------*
17601 // /| /| /|
17602 // / *-------*-------*
17603 // /| /| /|
17604 // *-------*-------*
17605 // /| / /|
17606 // / | / |
17607 // | |
17608 // *---------------*
17609 // / /
17610 // / /
17611
17612 std::pair<unsigned int, unsigned int>
17613 nb_indices =
17614 has_periodic_neighbor ?
17615 cell
17616 ->periodic_neighbor_of_coarser_periodic_neighbor(
17617 i) :
17618 cell->neighbor_of_coarser_neighbor(i);
17619 unsigned int refined_along_x = 0,
17620 refined_along_y = 0,
17621 to_be_refined_along_x = 0,
17622 to_be_refined_along_y = 0;
17623
17624 const int this_face_index =
17625 cell->face_index(i);
17626
17627 // step 1: detect, along which axis the face
17628 // is currently refined
17629
17630 // first, we need an iterator pointing to
17631 // the parent face. This requires a slight
17632 // detour in case the neighbor is behind a
17633 // periodic face.
17634 const auto parent_face = [&]() {
17635 if (has_periodic_neighbor)
17636 {
17637 const auto neighbor =
17638 cell->periodic_neighbor(i);
17639 const auto parent_face_no =
17640 neighbor
17641 ->periodic_neighbor_of_periodic_neighbor(
17642 nb_indices.first);
17643 auto parent =
17644 neighbor->periodic_neighbor(
17645 nb_indices.first);
17646 return parent->face(parent_face_no);
17647 }
17648 else
17649 return cell->neighbor(i)->face(
17650 nb_indices.first);
17651 }();
17652
17653 if ((this_face_index ==
17654 parent_face->child_index(0)) ||
17655 (this_face_index ==
17656 parent_face->child_index(1)))
17657 {
17658 // this might be an
17659 // anisotropic child. get the
17660 // face refine case of the
17661 // neighbors face and count
17662 // refinements in x and y
17663 // direction.
17664 RefinementCase<dim - 1> frc =
17665 parent_face->refinement_case();
17667 ++refined_along_x;
17669 ++refined_along_y;
17670 }
17671 else
17672 // this has to be an isotropic
17673 // child
17674 {
17675 ++refined_along_x;
17676 ++refined_along_y;
17677 }
17678 // step 2: detect, along which axis the face
17679 // has to be refined given the current
17680 // refine flag
17681 RefinementCase<dim - 1> flagged_frc =
17683 cell->refine_flag_set(),
17684 i,
17685 cell->face_orientation(i),
17686 cell->face_flip(i),
17687 cell->face_rotation(i));
17688 if (flagged_frc &
17690 ++to_be_refined_along_x;
17691 if (flagged_frc &
17693 ++to_be_refined_along_y;
17694
17695 // step 3: set the refine flag of the
17696 // (coarser and active) neighbor.
17697 if ((smooth_grid &
17698 allow_anisotropic_smoothing) ||
17699 cell->neighbor_or_periodic_neighbor(i)
17700 ->refine_flag_set())
17701 {
17702 if (refined_along_x +
17703 to_be_refined_along_x >
17704 1)
17705 changed |=
17706 cell
17707 ->neighbor_or_periodic_neighbor(i)
17708 ->flag_for_face_refinement(
17709 nb_indices.first,
17710 RefinementCase<dim -
17711 1>::cut_axis(0));
17712 if (refined_along_y +
17713 to_be_refined_along_y >
17714 1)
17715 changed |=
17716 cell
17717 ->neighbor_or_periodic_neighbor(i)
17718 ->flag_for_face_refinement(
17719 nb_indices.first,
17720 RefinementCase<dim -
17721 1>::cut_axis(1));
17722 }
17723 else
17724 {
17725 if (cell
17726 ->neighbor_or_periodic_neighbor(i)
17727 ->refine_flag_set() !=
17730 changed = true;
17731 cell->neighbor_or_periodic_neighbor(i)
17732 ->set_refine_flag();
17733 }
17734
17735 // step 4: if necessary (see above) add to
17736 // the refine flag of the current cell
17737 cell_iterator nb =
17738 cell->neighbor_or_periodic_neighbor(i);
17739 RefinementCase<dim - 1> nb_frc =
17741 nb->refine_flag_set(),
17742 nb_indices.first,
17743 nb->face_orientation(nb_indices.first),
17744 nb->face_flip(nb_indices.first),
17745 nb->face_rotation(nb_indices.first));
17746 if ((nb_frc & RefinementCase<dim>::cut_x) &&
17747 !((refined_along_x != 0u) ||
17748 (to_be_refined_along_x != 0u)))
17749 changed |= cell->flag_for_face_refinement(
17750 i,
17752 if ((nb_frc & RefinementCase<dim>::cut_y) &&
17753 !((refined_along_y != 0u) ||
17754 (to_be_refined_along_y != 0u)))
17755 changed |= cell->flag_for_face_refinement(
17756 i,
17758 }
17759 } // if neighbor is coarser
17760 else // -> now the neighbor is not coarser
17761 {
17762 cell->neighbor_or_periodic_neighbor(i)
17763 ->clear_coarsen_flag();
17764 const unsigned int nb_nb =
17765 has_periodic_neighbor ?
17766 cell
17767 ->periodic_neighbor_of_periodic_neighbor(
17768 i) :
17769 cell->neighbor_of_neighbor(i);
17770 const cell_iterator neighbor =
17771 cell->neighbor_or_periodic_neighbor(i);
17772 RefinementCase<dim - 1> face_ref_case =
17774 neighbor->refine_flag_set(),
17775 nb_nb,
17776 neighbor->face_orientation(nb_nb),
17777 neighbor->face_flip(nb_nb),
17778 neighbor->face_rotation(nb_nb));
17779 RefinementCase<dim - 1> needed_face_ref_case =
17781 cell->refine_flag_set(),
17782 i,
17783 cell->face_orientation(i),
17784 cell->face_flip(i),
17785 cell->face_rotation(i));
17786 // if the neighbor wants to refine the
17787 // face with cut_x and we want cut_y
17788 // or vice versa, we have to refine
17789 // isotropically at the given face
17790 if ((face_ref_case ==
17792 needed_face_ref_case ==
17794 (face_ref_case ==
17796 needed_face_ref_case ==
17798 {
17799 changed = cell->flag_for_face_refinement(
17800 i, face_ref_case);
17801 neighbor->flag_for_face_refinement(
17802 nb_nb, needed_face_ref_case);
17803 }
17804 }
17805 }
17806 else //-> the neighbor is not active
17807 {
17808 RefinementCase<dim - 1>
17809 face_ref_case = cell->face(i)->refinement_case(),
17810 needed_face_ref_case =
17812 cell->refine_flag_set(),
17813 i,
17814 cell->face_orientation(i),
17815 cell->face_flip(i),
17816 cell->face_rotation(i));
17817 // if the face is refined with cut_x and
17818 // we want cut_y or vice versa, we have to
17819 // refine isotropically at the given face
17820 if ((face_ref_case == RefinementCase<dim>::cut_x &&
17821 needed_face_ref_case ==
17823 (face_ref_case == RefinementCase<dim>::cut_y &&
17824 needed_face_ref_case ==
17826 changed =
17827 cell->flag_for_face_refinement(i,
17828 face_ref_case);
17829 }
17830 }
17831 }
17832 }
17833 }
17834
17835 //------------------------------------
17836 // STEP 7:
17837 // take care that no double refinement is done at each line in 3d or
17838 // higher dimensions.
17839 this->policy->prepare_refinement_dim_dependent(*this);
17840
17841 //------------------------------------
17842 // STEP 8:
17843 // make sure that all children of each cell are either flagged for
17844 // coarsening or none of the children is
17845 fix_coarsen_flags();
17846
17847 // get the refinement and coarsening flags
17848 auto coarsen_flags_after_loop =
17849 internal::extract_raw_coarsen_flags(levels);
17850 auto refine_flags_after_loop = internal::extract_raw_refine_flags(levels);
17851
17852 // find out whether something was changed in this loop
17853 mesh_changed_in_this_loop =
17854 ((coarsen_flags_before_loop != coarsen_flags_after_loop) ||
17855 (refine_flags_before_loop != refine_flags_after_loop));
17856
17857 // set the flags for the next loop already
17858 coarsen_flags_before_loop.swap(coarsen_flags_after_loop);
17859 refine_flags_before_loop.swap(refine_flags_after_loop);
17860 }
17861 while (mesh_changed_in_this_loop);
17862
17863
17864 // find out whether something was really changed in this
17865 // function. Note that @p{..._flags_before_loop} represents the state
17866 // after the last loop, i.e., the present state
17867 return ((coarsen_flags_before != coarsen_flags_before_loop) ||
17868 (refine_flags_before != refine_flags_before_loop));
17869}
17870
17871
17872
17873template <int dim, int spacedim>
17876 const unsigned int magic_number1,
17877 const std::vector<bool> &v,
17878 const unsigned int magic_number2,
17879 std::ostream &out)
17880{
17881 const unsigned int N = v.size();
17882 unsigned char *flags = new unsigned char[N / 8 + 1];
17883 for (unsigned int i = 0; i < N / 8 + 1; ++i)
17884 flags[i] = 0;
17885
17886 for (unsigned int position = 0; position < N; ++position)
17887 flags[position / 8] |= (v[position] ? (1 << (position % 8)) : 0);
17888
17889 AssertThrow(out.fail() == false, ExcIO());
17890
17891 // format:
17892 // 0. magic number
17893 // 1. number of flags
17894 // 2. the flags
17895 // 3. magic number
17896 out << magic_number1 << ' ' << N << std::endl;
17897 for (unsigned int i = 0; i < N / 8 + 1; ++i)
17898 out << static_cast<unsigned int>(flags[i]) << ' ';
17899
17900 out << std::endl << magic_number2 << std::endl;
17901
17902 delete[] flags;
17903
17904 AssertThrow(out.fail() == false, ExcIO());
17905}
17906
17907
17908template <int dim, int spacedim>
17911 const unsigned int magic_number1,
17912 std::vector<bool> &v,
17913 const unsigned int magic_number2,
17914 std::istream &in)
17915{
17916 AssertThrow(in.fail() == false, ExcIO());
17917
17918 unsigned int magic_number;
17919 in >> magic_number;
17920 AssertThrow(magic_number == magic_number1, ExcGridReadError());
17921
17922 unsigned int N;
17923 in >> N;
17924 v.resize(N);
17925
17926 unsigned char *flags = new unsigned char[N / 8 + 1];
17927 unsigned short int tmp;
17928 for (unsigned int i = 0; i < N / 8 + 1; ++i)
17929 {
17930 in >> tmp;
17931 flags[i] = tmp;
17932 }
17933
17934 for (unsigned int position = 0; position != N; ++position)
17935 v[position] = ((flags[position / 8] & (1 << (position % 8))) != 0);
17936
17937 in >> magic_number;
17938 AssertThrow(magic_number == magic_number2, ExcGridReadError());
17939
17940 delete[] flags;
17941
17942 AssertThrow(in.fail() == false, ExcIO());
17943}
17944
17945
17946
17947template <int dim, int spacedim>
17950{
17951 std::size_t mem = 0;
17952 mem += sizeof(MeshSmoothing);
17953 mem += MemoryConsumption::memory_consumption(reference_cells);
17954 mem += MemoryConsumption::memory_consumption(periodic_face_pairs_level_0);
17956 for (const auto &level : levels)
17959 mem += MemoryConsumption::memory_consumption(vertices_used);
17960 mem += sizeof(manifolds);
17961 mem += sizeof(smooth_grid);
17962 mem += MemoryConsumption::memory_consumption(number_cache);
17963 mem += sizeof(faces);
17964 if (faces)
17966
17967 return mem;
17968}
17969
17970
17971
17972template <int dim, int spacedim>
17975 default;
17976
17977#endif
17978
17979// explicit instantiations
17980#include "tria.inst"
17981
ArrayView< std::remove_reference_t< typename std::iterator_traits< Iterator >::reference >, MemorySpaceType > make_array_view(const Iterator begin, const Iterator end)
Definition array_view.h:949
CellStatus
Definition cell_status.h:31
@ cell_will_be_refined
@ children_will_be_coarsened
types::coarse_cell_id get_coarse_cell_id() const
Definition cell_id.h:393
EnableObserverPointer & operator=(const EnableObserverPointer &)
virtual std::unique_ptr< Manifold< dim, spacedim > > clone() const =0
Definition point.h:111
numbers::NumberTraits< Number >::real_type distance(const Point< dim, Number > &p) const
unsigned int face_to_cell_vertices(const unsigned int face, const unsigned int vertex, const unsigned char face_orientation) const
static constexpr unsigned char default_combined_face_orientation()
unsigned int standard_to_real_face_vertex(const unsigned int vertex, const unsigned int face, const unsigned char face_orientation) const
static constexpr unsigned char reversed_combined_line_orientation()
unsigned int n_lines() const
unsigned char get_combined_orientation(const ArrayView< const T > &vertices_0, const ArrayView< const T > &vertices_1) const
constexpr void clear()
void join() const
IteratorState::IteratorStates state() const
virtual void add_periodicity(const std::vector< GridTools::PeriodicFacePair< cell_iterator > > &)
virtual types::global_cell_index n_global_active_cells() const
quad_iterator begin_quad(const unsigned int level=0) const
MPI_Comm get_communicator() const
typename IteratorSelector::raw_line_iterator raw_line_iterator
Definition tria.h:4125
active_vertex_iterator begin_active_vertex() const
void load_user_indices_quad(const std::vector< unsigned int > &v)
unsigned int n_quads() const
Triangulation & operator=(Triangulation< dim, spacedim > &&tria) noexcept
void load_user_indices(const std::vector< unsigned int > &v)
std::vector< bool > vertices_used
Definition tria.h:4501
virtual void clear()
bool anisotropic_refinement
Definition tria.h:4512
active_quad_iterator begin_active_quad(const unsigned int level=0) const
bool get_anisotropic_refinement_flag() const
virtual const MeshSmoothing & get_mesh_smoothing() const
virtual void copy_triangulation(const Triangulation< dim, spacedim > &other_tria)
virtual types::coarse_cell_id n_global_coarse_cells() const
std::unique_ptr< std::map< unsigned int, types::manifold_id > > vertex_to_manifold_id_map_1d
Definition tria.h:4570
void save_user_pointers_quad(std::vector< void * > &v) const
void save_user_flags_hex(std::ostream &out) const
void clear_user_flags_quad()
unsigned int n_faces() const
active_hex_iterator begin_active_hex(const unsigned int level=0) const
static void read_bool_vector(const unsigned int magic_number1, std::vector< bool > &v, const unsigned int magic_number2, std::istream &in)
virtual std::weak_ptr< const Utilities::MPI::Partitioner > global_active_cell_index_partitioner() const
bool all_reference_cells_are_hyper_cube() const
void load_user_flags_line(std::istream &in)
void clear_user_data()
raw_hex_iterator begin_raw_hex(const unsigned int level=0) const
const std::map< std::pair< cell_iterator, unsigned int >, std::pair< std::pair< cell_iterator, unsigned int >, unsigned char > > & get_periodic_face_map() const
void save_user_flags_line(std::ostream &out) const
active_cell_iterator last_active() const
void save(Archive &ar, const unsigned int version) const
void reset_global_cell_indices()
face_iterator end_face() const
void reset_active_cell_indices()
cell_iterator create_cell_iterator(const CellId &cell_id) const
cell_iterator begin(const unsigned int level=0) const
void fix_coarsen_flags()
virtual MPI_Comm get_mpi_communicator() const
void save_user_pointers_line(std::vector< void * > &v) const
void load_refine_flags(std::istream &in)
void save_user_indices_line(std::vector< unsigned int > &v) const
raw_cell_iterator begin_raw(const unsigned int level=0) const
unsigned int n_lines() const
virtual void set_mesh_smoothing(const MeshSmoothing mesh_smoothing)
unsigned int n_raw_lines() const
virtual std::size_t memory_consumption() const
std::vector< Point< spacedim > > vertices
Definition tria.h:4496
raw_quad_iterator begin_raw_quad(const unsigned int level=0) const
virtual types::subdomain_id locally_owned_subdomain() const
unsigned int n_raw_faces() const
unsigned int n_active_faces() const
virtual void create_triangulation(const std::vector< Point< spacedim > > &vertices, const std::vector< CellData< dim > > &cells, const SubCellData &subcelldata)
const bool check_for_distorted_cells
Definition tria.h:4519
raw_cell_iterator end_raw(const unsigned int level) const
line_iterator end_line() const
std::unique_ptr< std::map< unsigned int, types::boundary_id > > vertex_to_boundary_id_map_1d
Definition tria.h:4547
void load_user_flags_quad(std::istream &in)
unsigned int n_active_cells() const
virtual void update_reference_cells()
std::vector< ReferenceCell > reference_cells
Definition tria.h:4041
void update_periodic_face_map()
void clear_despite_subscriptions()
void coarsen_global(const unsigned int times=1)
Triangulation(const MeshSmoothing smooth_grid=none, const bool check_for_distorted_cells=false)
void save_user_flags(std::ostream &out) const
void refine_global(const unsigned int times=1)
virtual std::weak_ptr< const Utilities::MPI::Partitioner > global_level_cell_index_partitioner(const unsigned int level) const
void load_user_flags_hex(std::istream &in)
void load_user_pointers_quad(const std::vector< void * > &v)
std::unique_ptr<::internal::TriangulationImplementation::TriaFaces > faces
Definition tria.h:4490
unsigned int n_used_vertices() const
void reset_cell_vertex_indices_cache()
unsigned int n_active_lines() const
void load_user_indices_line(const std::vector< unsigned int > &v)
void clear_user_flags_hex()
void save_user_pointers_hex(std::vector< void * > &v) const
const std::vector< ReferenceCell > & get_reference_cells() const
typename IteratorSelector::raw_quad_iterator raw_quad_iterator
Definition tria.h:4126
void load_user_pointers(const std::vector< void * > &v)
unsigned int register_data_attach(const std::function< std::vector< char >(const cell_iterator &, const ::CellStatus)> &pack_callback, const bool returns_variable_size_data)
::internal::TriangulationImplementation::NumberCache< dim > number_cache
Definition tria.h:4530
void save_attached_data(const unsigned int global_first_cell, const unsigned int global_num_cells, const std::string &file_basename) const
void save_user_indices_hex(std::vector< unsigned int > &v) const
DistortedCellList execute_refinement()
void update_cell_relations()
active_line_iterator begin_active_line(const unsigned int level=0) const
void save_user_indices_quad(std::vector< unsigned int > &v) const
void load_user_pointers_hex(const std::vector< void * > &v)
void pack_data_serial()
cell_iterator end() const
virtual bool has_hanging_nodes() const
std::vector< GridTools::PeriodicFacePair< cell_iterator > > periodic_face_pairs_level_0
Definition tria.h:4102
unsigned int n_raw_cells(const unsigned int level) const
bool contains_cell(const CellId &cell_id) const
void load_attached_data(const unsigned int global_first_cell, const unsigned int global_num_cells, const unsigned int local_num_cells, const std::string &file_basename, const unsigned int n_attached_deserialize_fixed, const unsigned int n_attached_deserialize_variable)
void load_coarsen_flags(std::istream &out)
quad_iterator end_quad() const
line_iterator begin_line(const unsigned int level=0) const
unsigned int max_adjacent_cells() const
vertex_iterator begin_vertex() const
void clear_user_flags()
unsigned int n_hexs() const
vertex_iterator end_vertex() const
void load_user_pointers_line(const std::vector< void * > &v)
hex_iterator end_hex() const
hex_iterator begin_hex(const unsigned int level=0) const
virtual void execute_coarsening_and_refinement()
active_cell_iterator end_active(const unsigned int level) const
bool is_mixed_mesh() const
cell_iterator last() const
unsigned int n_active_quads() const
void load_user_indices_hex(const std::vector< unsigned int > &v)
unsigned int n_raw_quads() const
void save_user_pointers(std::vector< void * > &v) const
face_iterator begin_face() const
unsigned int n_cells() const
virtual bool prepare_coarsening_and_refinement()
void unpack_data_serial()
const std::vector< bool > & get_used_vertices() const
typename IteratorSelector::raw_hex_iterator raw_hex_iterator
Definition tria.h:4127
MeshSmoothing smooth_grid
Definition tria.h:4035
void save_refine_flags(std::ostream &out) const
std::unique_ptr< ::internal::TriangulationImplementation::Policy< dim, spacedim > > policy
Definition tria.h:4093
Triangulation< dim, spacedim > & get_triangulation()
void save_user_flags_quad(std::ostream &out) const
Signals signals
Definition tria.h:2526
virtual ~Triangulation() override
unsigned int n_vertices() const
void load(Archive &ar, const unsigned int version)
void save_user_indices(std::vector< unsigned int > &v) const
void notify_ready_to_unpack(const unsigned int handle, const std::function< void(const cell_iterator &, const ::CellStatus, const boost::iterator_range< std::vector< char >::const_iterator > &)> &unpack_callback)
bool all_reference_cells_are_simplex() const
std::vector< std::unique_ptr<::internal::TriangulationImplementation::TriaLevel > > levels
Definition tria.h:4482
unsigned int n_raw_hexs(const unsigned int level) const
void set_all_refine_flags()
unsigned int n_active_hexs() const
virtual std::vector< types::boundary_id > get_boundary_ids() const
void load_user_flags(std::istream &in)
void reset_policy()
void save_coarsen_flags(std::ostream &out) const
active_face_iterator begin_active_face() const
void clear_user_flags_line()
raw_line_iterator begin_raw_line(const unsigned int level=0) const
static void write_bool_vector(const unsigned int magic_number1, const std::vector< bool > &v, const unsigned int magic_number2, std::ostream &out)
void flip_all_direction_flags()
active_cell_iterator begin_active(const unsigned int level=0) const
void execute_coarsening()
typename std::pair< cell_iterator, CellStatus > cell_relation_t
Definition tria.h:393
void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation) override
Definition tria.cc:2558
void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation) override
Definition tria.cc:2565
void delete_children(Triangulation< dim, spacedim > &tria, typename Triangulation< dim, spacedim >::cell_iterator &cell, std::vector< unsigned int > &line_cell_count, std::vector< unsigned int > &quad_cell_count) override
Definition tria.cc:2541
void update_neighbors(Triangulation< dim, spacedim > &tria) override
Definition tria.cc:2535
bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell) override
Definition tria.cc:2572
Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells) override
Definition tria.cc:2551
std::unique_ptr< Policy< dim, spacedim > > clone() override
Definition tria.cc:2580
virtual std::unique_ptr< Policy< dim, spacedim > > clone()=0
virtual void update_neighbors(Triangulation< dim, spacedim > &tria)=0
virtual void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation)=0
virtual void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation)=0
virtual Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells)=0
virtual bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell)=0
virtual void delete_children(Triangulation< dim, spacedim > &triangulation, typename Triangulation< dim, spacedim >::cell_iterator &cell, std::vector< unsigned int > &line_cell_count, std::vector< unsigned int > &quad_cell_count)=0
std::vector< std::pair< int, int > > neighbors
std::vector< types::global_cell_index > global_active_cell_indices
std::vector< types::global_cell_index > global_level_cell_indices
std::vector< ReferenceCell > reference_cell
std::vector< types::subdomain_id > level_subdomain_ids
std::vector< types::subdomain_id > subdomain_ids
std::vector< unsigned int > active_cell_indices
std::vector< types::manifold_id > manifold_id
std::vector< BoundaryOrMaterialId > boundary_or_material_id
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:498
#define DEAL_II_CXX20_REQUIRES(condition)
Definition config.h:175
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:499
Point< 2 > second
Definition grid_out.cc: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:534
#define AssertDimension(dim1, dim2)
#define AssertThrowMPI(error_code)
static ::ExceptionBase & ExcGridHasInvalidCell(int arg1)
static ::ExceptionBase & ExcMultiplySetLineInfoOfLine(int arg1, int arg2)
#define AssertNothrow(cond, exc)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcInteriorLineCantBeBoundary(int arg1, int arg2, types::boundary_id arg3)
#define DeclException3(Exception3, type1, type2, type3, outsequence)
Definition exceptions.h:557
#define DeclException1(Exception1, type1, outsequence)
Definition exceptions.h:511
static ::ExceptionBase & ExcInvalidVertexIndex(int arg1, int arg2, int arg3)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define DeclException5( Exception5, type1, type2, type3, type4, type5, outsequence)
Definition exceptions.h:606
#define AssertThrow(cond, exc)
static ::ExceptionBase & ExcInconsistentQuadInfoOfQuad(int arg1, int arg2, int arg3, int arg4, std::string arg5)
typename IteratorSelector::hex_iterator hex_iterator
Definition tria.h:1691
typename IteratorSelector::active_quad_iterator active_quad_iterator
Definition tria.h:1682
typename IteratorSelector::active_hex_iterator active_hex_iterator
Definition tria.h:1702
typename IteratorSelector::quad_iterator quad_iterator
Definition tria.h:1667
typename IteratorSelector::line_iterator line_iterator
Definition tria.h:1643
TriaIterator< CellAccessor< dim, spacedim > > cell_iterator
Definition tria.h:1556
typename IteratorSelector::active_line_iterator active_line_iterator
Definition tria.h:1658
void set_all_manifold_ids_on_boundary(const types::manifold_id number)
const Manifold< dim, spacedim > & get_manifold(const types::manifold_id number) const
virtual std::vector< types::manifold_id > get_manifold_ids() const
void reset_manifold(const types::manifold_id manifold_number)
void set_manifold(const types::manifold_id number, const Manifold< dim, spacedim > &manifold_object)
void reset_all_manifolds()
void set_all_manifold_ids(const types::manifold_id number)
Task< RT > new_task(const std::function< RT()> &function)
#define AssertIsNotUsed(obj)
#define DEAL_II_ASSERT_UNREACHABLE()
#define DEAL_II_NOT_IMPLEMENTED()
const unsigned int mn_tria_refine_flags_end
const unsigned int mn_tria_coarsen_flags_end
const unsigned int mn_tria_refine_flags_begin
const unsigned int mn_tria_hex_user_flags_end
const unsigned int mn_tria_line_user_flags_begin
const unsigned int mn_tria_line_user_flags_end
const unsigned int mn_tria_quad_user_flags_end
const unsigned int mn_tria_coarsen_flags_begin
const unsigned int mn_tria_hex_user_flags_begin
const unsigned int mn_tria_quad_user_flags_begin
const Mapping< dim, spacedim > & get_default_linear_mapping(const Triangulation< dim, spacedim > &triangulation)
Definition mapping.cc:294
std::vector< index_type > data
Definition mpi.cc:735
std::size_t size
Definition mpi.cc:734
void create_triangulation(Triangulation< dim, dim > &tria, const AdditionalData &additional_data=AdditionalData())
void reference_cell(Triangulation< dim, spacedim > &tria, const ReferenceCell &reference_cell)
double diameter(const Triangulation< dim, spacedim > &tria)
@ valid
Iterator points to a valid object.
std::enable_if_t< std::is_fundamental_v< T >, std::size_t > memory_consumption(const T &t)
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
Tensor< 2, dim, Number > l(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
constexpr const ReferenceCell Tetrahedron
constexpr const ReferenceCell Quadrilateral
constexpr const ReferenceCell Invalid
constexpr const ReferenceCell Triangle
constexpr const ReferenceCell Hexahedron
constexpr const ReferenceCell Line
VectorType::value_type * end(VectorType &V)
VectorType::value_type * begin(VectorType &V)
int File_write_at_c(MPI_File fh, MPI_Offset offset, const void *buf, MPI_Count count, MPI_Datatype datatype, MPI_Status *status)
int File_read_at_c(MPI_File fh, MPI_Offset offset, void *buf, MPI_Count count, MPI_Datatype datatype, MPI_Status *status)
unsigned int n_mpi_processes(const MPI_Comm mpi_communicator)
Definition mpi.cc:92
T max(const T &t, const MPI_Comm mpi_communicator)
unsigned int this_mpi_process(const MPI_Comm mpi_communicator)
Definition mpi.cc:107
size_t pack(const T &object, std::vector< char > &dest_buffer, const bool allow_compression=true)
Definition utilities.h:1381
constexpr T fixed_power(const T t)
Definition utilities.h:942
unsigned int n_active_cells(const internal::TriangulationImplementation::NumberCache< 1 > &c)
Definition tria.cc:14878
const Manifold< dim, spacedim > & get_default_flat_manifold()
Definition tria.cc:11983
unsigned int n_cells(const internal::TriangulationImplementation::NumberCache< 1 > &c)
Definition tria.cc:14871
void reserve_space(TriaFaces &tria_faces, const unsigned int new_quads_in_pairs, const unsigned int new_quads_single)
Definition tria.cc:1997
void monitor_memory(const TriaLevel &tria_level, const unsigned int true_dimension)
Definition tria.cc:2199
std::tuple< bool, bool, bool > split_face_orientation(const unsigned char combined_face_orientation)
const types::boundary_id internal_face_boundary_id
Definition types.h:312
const types::subdomain_id invalid_subdomain_id
Definition types.h:341
static const unsigned int invalid_unsigned_int
Definition types.h:220
const types::manifold_id flat_manifold_id
Definition types.h:325
const types::global_dof_index invalid_dof_index
Definition types.h:252
STL namespace.
::VectorizedArray< Number, width > min(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > abs(const ::VectorizedArray< Number, width > &)
unsigned int manifold_id
Definition types.h:156
unsigned int boundary_id
Definition types.h:144
const ::parallel::distributed::Triangulation< dim, spacedim > * triangulation
static unsigned int child_cell_on_face(const RefinementCase< dim > &ref_case, const unsigned int face, const unsigned int subface, const bool face_orientation=true, const bool face_flip=false, const bool face_rotation=false, const RefinementCase< dim - 1 > &face_refinement_case=RefinementCase< dim - 1 >::isotropic_refinement)
static RefinementCase< dim - 1 > face_refinement_case(const RefinementCase< dim > &cell_refinement_case, const unsigned int face_no, const bool face_orientation=true, const bool face_flip=false, const bool face_rotation=false)
static std_cxx20::ranges::iota_view< unsigned int, unsigned int > face_indices()
static RefinementCase< dim > min_cell_refinement_case_for_face_refinement(const RefinementCase< dim - 1 > &face_refinement_case, const unsigned int face_no, const bool face_orientation=true, const bool face_flip=false, const bool face_rotation=false)
static unsigned int n_children(const RefinementCase< dim > &refinement_case)
static void alternating_form_at_vertices(const Point< spacedim >(&vertices)[vertices_per_cell], Tensor< spacedim - dim, spacedim >(&forms)[vertices_per_cell])
bool check_consistency(const unsigned int dim) const
std::vector< std::vector< CellData< dim > > > cell_infos
std::vector<::CellData< dim > > coarse_cells
std::vector< Point< spacedim > > coarse_cell_vertices
virtual ~DistortedCellList() noexcept override
std::list< typename Triangulation< dim, spacedim >::cell_iterator > distorted_cells
Definition tria.h:1737
boost::signals2::signal< void(const Triangulation< dim, spacedim > &destination_tria)> copy
Definition tria.h:2372
static void update_neighbors(Triangulation< 1, spacedim > &)
Definition tria.cc:11865
static void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &)
Definition tria.cc:11955
static Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:11946
static bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &)
Definition tria.cc:11971
static void update_neighbors(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:11869
static void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:11963
static void delete_children(Triangulation< dim, spacedim > &, typename Triangulation< dim, spacedim >::cell_iterator &, std::vector< unsigned int > &, std::vector< unsigned int > &)
Definition tria.cc:11935
static void reserve_space_(TriaObjects &obj, const unsigned int size)
Definition tria.cc:3628
static void reserve_space_(TriaFaces &faces, const unsigned structdim, const unsigned int size)
Definition tria.cc:3567
static void compute_number_cache_dim(const Triangulation< dim, spacedim > &triangulation, const unsigned int level_objects, internal::TriangulationImplementation::NumberCache< 2 > &number_cache)
Definition tria.cc:2786
static void prevent_distorted_boundary_cells(Triangulation< 1, spacedim > &)
Definition tria.cc:11472
static void update_neighbors(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:3014
static void prepare_refinement_dim_dependent(const Triangulation< dim, spacedim > &)
Definition tria.cc:11560
static void delete_children(Triangulation< 3, spacedim > &triangulation, typename Triangulation< 3, spacedim >::cell_iterator &cell, std::vector< unsigned int > &line_cell_count, std::vector< unsigned int > &quad_cell_count)
Definition tria.cc:3923
static void reserve_space_(TriaLevel &level, const unsigned int spacedim, const unsigned int size, const bool orientation_needed)
Definition tria.cc:3589
static void update_neighbors(Triangulation< 1, spacedim > &)
Definition tria.cc:3008
static Triangulation< 3, spacedim >::DistortedCellList execute_refinement(Triangulation< 3, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:7111
static Triangulation< dim, spacedim >::DistortedCellList execute_refinement_isotropic(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:4918
static void compute_number_cache(const Triangulation< dim, spacedim > &triangulation, const unsigned int level_objects, internal::TriangulationImplementation::NumberCache< dim > &number_cache)
Definition tria.cc:2986
static void create_children(Triangulation< 2, spacedim > &triangulation, unsigned int &next_unused_vertex, typename Triangulation< 2, spacedim >::raw_line_iterator &next_unused_line, typename Triangulation< 2, spacedim >::raw_cell_iterator &next_unused_cell, const typename Triangulation< 2, spacedim >::cell_iterator &cell)
Definition tria.cc:4551
static void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:11479
static bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell)
Definition tria.cc:11793
static void compute_number_cache_dim(const Triangulation< dim, spacedim > &triangulation, const unsigned int level_objects, internal::TriangulationImplementation::NumberCache< 3 > &number_cache)
Definition tria.cc:2893
static void delete_children(Triangulation< 1, spacedim > &triangulation, typename Triangulation< 1, spacedim >::cell_iterator &cell, std::vector< unsigned int > &, std::vector< unsigned int > &)
Definition tria.cc:3681
static void prepare_refinement_dim_dependent(Triangulation< 3, spacedim > &triangulation)
Definition tria.cc:11570
static void delete_children(Triangulation< 2, spacedim > &triangulation, typename Triangulation< 2, spacedim >::cell_iterator &cell, std::vector< unsigned int > &line_cell_count, std::vector< unsigned int > &)
Definition tria.cc:3785
static void compute_number_cache_dim(const Triangulation< dim, spacedim > &triangulation, const unsigned int level_objects, internal::TriangulationImplementation::NumberCache< 1 > &number_cache)
Definition tria.cc:2698
static Triangulation< 1, spacedim >::DistortedCellList execute_refinement(Triangulation< 1, spacedim > &triangulation, const bool)
Definition tria.cc:5376
static Triangulation< 3, spacedim >::DistortedCellList execute_refinement_isotropic(Triangulation< 3, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:5920
static void create_triangulation(const std::vector< Point< spacedim > > &vertices, const std::vector< CellData< dim > > &cells, const SubCellData &subcelldata, Triangulation< dim, spacedim > &tria)
Definition tria.cc:3193
static Triangulation< 2, spacedim >::DistortedCellList execute_refinement(Triangulation< 2, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:5611
static void process_subcelldata(const CRS< T > &crs, TriaObjects &obj, const std::vector< CellData< structdim > > &boundary_objects_in, const std::vector< Point< spacedim > > &vertex_locations)
Definition tria.cc:3456
std::vector< std::vector< CellData< dim > > > cell_infos