Reference documentation for deal.II version GIT relicensing-1062-gc06da148b8 2024-07-15 19:20:02+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
tria.cc
Go to the documentation of this file.
1// ------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: LGPL-2.1-or-later
4// Copyright (C) 1999 - 2024 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Part of the source code is dual licensed under Apache-2.0 WITH
9// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
10// governing the source code and code contributions can be found in
11// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
12//
13// ------------------------------------------------------------------------
14
15
18#include <deal.II/base/mpi.templates.h>
23
25
30#include <deal.II/grid/tria.h>
35
36#include <boost/archive/text_iarchive.hpp>
37#include <boost/archive/text_oarchive.hpp>
38
39#include <algorithm>
40#include <array>
41#include <cmath>
42#include <cstdint>
43#include <fstream>
44#include <functional>
45#include <limits>
46#include <list>
47#include <map>
48#include <memory>
49#include <numeric>
50
51
53
54
55namespace internal
56{
57 namespace TriangulationImplementation
58 {
60 : n_levels(0)
61 , n_lines(0)
62 , n_active_lines(0)
63 // all other fields are
64 // default constructed
65 {}
66
67
68
69 std::size_t
71 {
72 std::size_t mem =
77 MemoryConsumption::memory_consumption(n_active_lines_level);
78
79 if (active_cell_index_partitioner)
80 mem += active_cell_index_partitioner->memory_consumption();
81
82 for (const auto &partitioner : level_cell_index_partitioners)
83 if (partitioner)
84 mem += partitioner->memory_consumption();
85
86 return mem;
87 }
88
89
91 : n_quads(0)
92 , n_active_quads(0)
93 // all other fields are
94 // default constructed
95 {}
96
97
98
99 std::size_t
108
109
110
112 : n_hexes(0)
113 , n_active_hexes(0)
114 // all other fields are
115 // default constructed
116 {}
117
118
119
120 std::size_t
129 } // namespace TriangulationImplementation
130
131
132 template <int dim, int spacedim>
135 : variable_size_data_stored(false)
136 {}
137
138
139 template <int dim, int spacedim>
141 void CellAttachedDataSerializer<dim, spacedim>::pack_data(
142 const std::vector<cell_relation_t> &cell_relations,
143 const std::vector<
144 typename internal::CellAttachedData<dim, spacedim>::pack_callback_t>
145 &pack_callbacks_fixed,
146 const std::vector<
147 typename internal::CellAttachedData<dim, spacedim>::pack_callback_t>
148 &pack_callbacks_variable,
149 const MPI_Comm &mpi_communicator)
150 {
151 Assert(src_data_fixed.empty(),
152 ExcMessage("Previously packed data has not been released yet!"));
153 Assert(src_sizes_variable.empty(), ExcInternalError());
154
155 const unsigned int n_callbacks_fixed = pack_callbacks_fixed.size();
156 const unsigned int n_callbacks_variable = pack_callbacks_variable.size();
157
158 // Store information that we packed variable size data in
159 // a member variable for later.
160 variable_size_data_stored = (n_callbacks_variable > 0);
161
162 // If variable transfer is scheduled, we will store the data size that
163 // each variable size callback function writes in this auxiliary
164 // container. The information will be stored by each cell in this vector
165 // temporarily.
166 std::vector<unsigned int> cell_sizes_variable_cumulative(
167 n_callbacks_variable);
168
169 // Prepare the buffer structure, in which each callback function will
170 // store its data for each active cell.
171 // The outmost shell in this container construct corresponds to the
172 // data packed per cell. The next layer resembles the data that
173 // each callback function packs on the corresponding cell. These
174 // buffers are chains of chars stored in an std::vector<char>.
175 // A visualisation of the data structure:
176 /* clang-format off */
177 // | cell_1 | | cell_2 | ...
178 // || callback_1 || callback_2 |...| || callback_1 || callback_2 |...| ...
179 // |||char|char|...|||char|char|...|...| |||char|char|...|||char|char|...|...| ...
180 /* clang-format on */
181 std::vector<std::vector<std::vector<char>>> packed_fixed_size_data(
182 cell_relations.size());
183 std::vector<std::vector<std::vector<char>>> packed_variable_size_data(
184 variable_size_data_stored ? cell_relations.size() : 0);
185
186 //
187 // --------- Pack data for fixed and variable size transfer ---------
188 //
189 // Iterate over all cells, call all callback functions on each cell,
190 // and store their data in the corresponding buffer scope.
191 {
192 auto cell_rel_it = cell_relations.cbegin();
193 auto data_cell_fixed_it = packed_fixed_size_data.begin();
194 auto data_cell_variable_it = packed_variable_size_data.begin();
195 for (; cell_rel_it != cell_relations.cend(); ++cell_rel_it)
196 {
197 const auto &dealii_cell = cell_rel_it->first;
198 const auto &cell_status = cell_rel_it->second;
199
200 // Assertions about the tree structure.
201 switch (cell_status)
202 {
205 // double check the condition that we will only ever attach
206 // data to active cells when we get here
207 Assert(dealii_cell->is_active(), ExcInternalError());
208 break;
209
211 // double check the condition that we will only ever attach
212 // data to cells with children when we get here. however, we
213 // can only tolerate one level of coarsening at a time, so
214 // check that the children are all active
215 Assert(dealii_cell->is_active() == false, ExcInternalError());
216 for (unsigned int c = 0;
217 c < GeometryInfo<dim>::max_children_per_cell;
218 ++c)
219 Assert(dealii_cell->child(c)->is_active(),
221 break;
222
224 // do nothing on invalid cells
225 break;
226
227 default:
229 break;
230 }
231
232 // Reserve memory corresponding to the number of callback
233 // functions that will be called.
234 // If variable size transfer is scheduled, we need to leave
235 // room for an array that holds information about how many
236 // bytes each of the variable size callback functions will
237 // write.
238 // On cells flagged with CellStatus::cell_invalid, only its CellStatus
239 // will be stored.
240 const unsigned int n_fixed_size_data_sets_on_cell =
241 1 + ((cell_status == CellStatus::cell_invalid) ?
242 0 :
243 ((variable_size_data_stored ? 1 : 0) + n_callbacks_fixed));
244 data_cell_fixed_it->resize(n_fixed_size_data_sets_on_cell);
245
246 // We continue with packing all data on this specific cell.
247 auto data_fixed_it = data_cell_fixed_it->begin();
248
249 // First, we pack the CellStatus information.
250 // to get consistent data sizes on each cell for the fixed size
251 // transfer, we won't allow compression
252 *data_fixed_it =
253 Utilities::pack(cell_status, /*allow_compression=*/false);
254 ++data_fixed_it;
255
256 // Proceed with all registered callback functions.
257 // Skip cells with the CellStatus::cell_invalid flag.
258 if (cell_status != CellStatus::cell_invalid)
259 {
260 // Pack fixed size data.
261 for (auto callback_it = pack_callbacks_fixed.cbegin();
262 callback_it != pack_callbacks_fixed.cend();
263 ++callback_it, ++data_fixed_it)
264 {
265 *data_fixed_it = (*callback_it)(dealii_cell, cell_status);
266 }
267
268 // Pack variable size data.
269 // If we store variable size data, we need to transfer
270 // the sizes of each corresponding callback function
271 // via fixed size transfer as well.
272 if (variable_size_data_stored)
273 {
274 const unsigned int n_variable_size_data_sets_on_cell =
275 ((cell_status == CellStatus::cell_invalid) ?
276 0 :
277 n_callbacks_variable);
278 data_cell_variable_it->resize(
279 n_variable_size_data_sets_on_cell);
280
281 auto callback_it = pack_callbacks_variable.cbegin();
282 auto data_variable_it = data_cell_variable_it->begin();
283 auto sizes_variable_it =
284 cell_sizes_variable_cumulative.begin();
285 for (; callback_it != pack_callbacks_variable.cend();
286 ++callback_it, ++data_variable_it, ++sizes_variable_it)
287 {
288 *data_variable_it =
289 (*callback_it)(dealii_cell, cell_status);
290
291 // Store data sizes for each callback function first.
292 // Make it cumulative below.
293 *sizes_variable_it = data_variable_it->size();
294 }
295
296 // Turn size vector into its cumulative representation.
297 std::partial_sum(cell_sizes_variable_cumulative.begin(),
298 cell_sizes_variable_cumulative.end(),
299 cell_sizes_variable_cumulative.begin());
300
301 // Serialize cumulative variable size vector
302 // value-by-value. This way we can circumvent the overhead
303 // of storing the container object as a whole, since we
304 // know its size by the number of registered callback
305 // functions.
306 data_fixed_it->resize(n_callbacks_variable *
307 sizeof(unsigned int));
308 for (unsigned int i = 0; i < n_callbacks_variable; ++i)
309 std::memcpy(&(data_fixed_it->at(i * sizeof(unsigned int))),
310 &(cell_sizes_variable_cumulative.at(i)),
311 sizeof(unsigned int));
312
313 ++data_fixed_it;
314 }
315
316 // Double check that we packed everything we wanted
317 // in the fixed size buffers.
318 Assert(data_fixed_it == data_cell_fixed_it->end(),
320 }
321
322 ++data_cell_fixed_it;
323
324 // Increment the variable size data iterator
325 // only if we actually pack this kind of data
326 // to avoid getting out of bounds.
327 if (variable_size_data_stored)
328 ++data_cell_variable_it;
329 } // loop over cell_relations
330 }
331
332 //
333 // ----------- Gather data sizes for fixed size transfer ------------
334 //
335 // Generate a vector which stores the sizes of each callback function,
336 // including the packed CellStatus transfer.
337 // Find the very first cell that we wrote to with all callback
338 // functions (i.e. a cell that was not flagged with
339 // CellStatus::cell_invalid) and store the sizes of each buffer.
340 //
341 // To deal with the case that at least one of the processors does not
342 // own any cell at all, we will exchange the information about the data
343 // sizes among them later. The code in between is still well-defined,
344 // since the following loops will be skipped.
345 std::vector<unsigned int> local_sizes_fixed(
346 1 + n_callbacks_fixed + (variable_size_data_stored ? 1 : 0));
347 for (const auto &data_cell : packed_fixed_size_data)
348 {
349 if (data_cell.size() == local_sizes_fixed.size())
350 {
351 auto sizes_fixed_it = local_sizes_fixed.begin();
352 auto data_fixed_it = data_cell.cbegin();
353 for (; data_fixed_it != data_cell.cend();
354 ++data_fixed_it, ++sizes_fixed_it)
355 {
356 *sizes_fixed_it = data_fixed_it->size();
357 }
358
359 break;
360 }
361 }
362
363 // Check if all cells have valid sizes.
364 for (auto data_cell_fixed_it = packed_fixed_size_data.cbegin();
365 data_cell_fixed_it != packed_fixed_size_data.cend();
366 ++data_cell_fixed_it)
367 {
368 Assert((data_cell_fixed_it->size() == 1) ||
369 (data_cell_fixed_it->size() == local_sizes_fixed.size()),
371 }
372
373 // Share information about the packed data sizes
374 // of all callback functions across all processors, in case one
375 // of them does not own any cells at all.
376 std::vector<unsigned int> global_sizes_fixed(local_sizes_fixed.size());
377 Utilities::MPI::max(local_sizes_fixed,
378 mpi_communicator,
379 global_sizes_fixed);
380
381 // Construct cumulative sizes, since this is the only information
382 // we need from now on.
383 sizes_fixed_cumulative.resize(global_sizes_fixed.size());
384 std::partial_sum(global_sizes_fixed.begin(),
385 global_sizes_fixed.end(),
386 sizes_fixed_cumulative.begin());
387
388 //
389 // ---------- Gather data sizes for variable size transfer ----------
390 //
391 if (variable_size_data_stored)
392 {
393 src_sizes_variable.reserve(packed_variable_size_data.size());
394 for (const auto &data_cell : packed_variable_size_data)
395 {
396 int variable_data_size_on_cell = 0;
397
398 for (const auto &data : data_cell)
399 variable_data_size_on_cell += data.size();
401 src_sizes_variable.push_back(variable_data_size_on_cell);
402 }
403 }
404
405 //
406 // ------------------------ Build buffers ---------------------------
407 //
408 const unsigned int expected_size_fixed =
409 cell_relations.size() * sizes_fixed_cumulative.back();
410 const unsigned int expected_size_variable =
411 std::accumulate(src_sizes_variable.begin(),
412 src_sizes_variable.end(),
413 std::vector<int>::size_type(0));
414
415 // Move every piece of packed fixed size data into the consecutive
416 // buffer.
417 src_data_fixed.reserve(expected_size_fixed);
418 for (const auto &data_cell_fixed : packed_fixed_size_data)
419 {
420 // Move every fraction of packed data into the buffer
421 // reserved for this particular cell.
422 for (const auto &data_fixed : data_cell_fixed)
423 std::move(data_fixed.begin(),
424 data_fixed.end(),
425 std::back_inserter(src_data_fixed));
426
427 // If we only packed the CellStatus information
428 // (i.e. encountered a cell flagged CellStatus::cell_invalid),
429 // fill the remaining space with invalid entries.
430 // We can skip this if there is nothing else to pack.
431 if ((data_cell_fixed.size() == 1) &&
432 (sizes_fixed_cumulative.size() > 1))
434 const std::size_t bytes_skipped =
435 sizes_fixed_cumulative.back() - sizes_fixed_cumulative.front();
436
437 src_data_fixed.insert(src_data_fixed.end(),
438 bytes_skipped,
439 static_cast<char>(-1)); // invalid_char
440 }
441 }
442
443 // Move every piece of packed variable size data into the consecutive
444 // buffer.
445 if (variable_size_data_stored)
446 {
447 src_data_variable.reserve(expected_size_variable);
448 for (const auto &data_cell : packed_variable_size_data)
449 {
450 // Move every fraction of packed data into the buffer
451 // reserved for this particular cell.
452 for (const auto &data : data_cell)
453 std::move(data.begin(),
454 data.end(),
455 std::back_inserter(src_data_variable));
456 }
458
459 // Double check that we packed everything correctly.
460 Assert(src_data_fixed.size() == expected_size_fixed, ExcInternalError());
461 Assert(src_data_variable.size() == expected_size_variable,
463 }
464
465
466
467 template <int dim, int spacedim>
469 void CellAttachedDataSerializer<dim, spacedim>::unpack_cell_status(
470 std::vector<
471 typename CellAttachedDataSerializer<dim, spacedim>::cell_relation_t>
472 &cell_relations) const
473 {
474 Assert(sizes_fixed_cumulative.size() > 0,
475 ExcMessage("No data has been packed!"));
476 if (cell_relations.size() > 0)
477 {
478 Assert(dest_data_fixed.size() > 0,
479 ExcMessage("No data has been received!"));
480 }
482 // Size of CellStatus object that will be unpacked on each cell.
483 const unsigned int size = sizes_fixed_cumulative.front();
484
485 // Iterate over all cells and overwrite the CellStatus
486 // information from the transferred data.
487 // Proceed buffer iterator position to next cell after
488 // each iteration.
489 auto cell_rel_it = cell_relations.begin();
490 auto dest_fixed_it = dest_data_fixed.cbegin();
491 for (; cell_rel_it != cell_relations.end();
492 ++cell_rel_it, dest_fixed_it += sizes_fixed_cumulative.back())
493 {
494 cell_rel_it->second = // cell_status
495 Utilities::unpack<CellStatus>(dest_fixed_it,
496 dest_fixed_it + size,
497 /*allow_compression=*/false);
498 }
499 }
500
501
502
503 template <int dim, int spacedim>
505 void CellAttachedDataSerializer<dim, spacedim>::unpack_data(
506 const std::vector<
507 typename CellAttachedDataSerializer<dim, spacedim>::cell_relation_t>
508 &cell_relations,
509 const unsigned int handle,
510 const std::function<
511 void(const cell_iterator &,
512 const CellStatus &,
513 const boost::iterator_range<std::vector<char>::const_iterator> &)>
514 &unpack_callback) const
515 {
516 // We decode the handle returned by register_data_attach() back into
517 // a format we can use. All even handles belong to those callback
518 // functions which write/read variable size data, all odd handles
519 // interact with fixed size buffers.
520 const bool callback_variable_transfer = (handle % 2 == 0);
521 const unsigned int callback_index = handle / 2;
522
523 // Cells will always receive fixed size data (i.e., CellStatus
524 // information), but not necessarily variable size data (e.g., with a
525 // ParticleHandler a cell might not contain any particle at all).
526 // Thus it is sufficient to check if fixed size data has been received.
527 Assert(sizes_fixed_cumulative.size() > 0,
528 ExcMessage("No data has been packed!"));
529 if (cell_relations.size() > 0)
530 {
531 Assert(dest_data_fixed.size() > 0,
532 ExcMessage("No data has been received!"));
533 }
534
535 std::vector<char>::const_iterator dest_data_it;
536 std::vector<char>::const_iterator dest_sizes_cell_it;
537
538 // Depending on whether our callback function unpacks fixed or
539 // variable size data, we have to pursue different approaches
540 // to localize the correct fraction of the buffer from which
541 // we are allowed to read.
542 unsigned int offset = numbers::invalid_unsigned_int;
543 unsigned int size = numbers::invalid_unsigned_int;
544 unsigned int data_increment = numbers::invalid_unsigned_int;
545
546 if (callback_variable_transfer)
547 {
548 // For the variable size data, we need to extract the
549 // data size from the fixed size buffer on each cell.
550 //
551 // We packed this information last, so the last packed
552 // object in the fixed size buffer corresponds to the
553 // variable data sizes.
554 //
555 // The last entry of sizes_fixed_cumulative corresponds
556 // to the size of all fixed size data packed on the cell.
557 // To get the offset for the last packed object, we need
558 // to get the next-to-last entry.
559 const unsigned int offset_variable_data_sizes =
560 sizes_fixed_cumulative[sizes_fixed_cumulative.size() - 2];
561
562 // This iterator points to the data size that the
563 // callback_function packed for each specific cell.
564 // Adjust buffer iterator to the offset of the callback
565 // function so that we only have to advance its position
566 // to the next cell after each iteration.
567 dest_sizes_cell_it = dest_data_fixed.cbegin() +
568 offset_variable_data_sizes +
569 callback_index * sizeof(unsigned int);
570
571 // Let the data iterator point to the correct buffer.
572 dest_data_it = dest_data_variable.cbegin();
573 }
574 else
575 {
576 // For the fixed size data, we can get the information about
577 // the buffer location on each cell directly from the
578 // sizes_fixed_cumulative vector.
579 offset = sizes_fixed_cumulative[callback_index];
580 size = sizes_fixed_cumulative[callback_index + 1] - offset;
581 data_increment = sizes_fixed_cumulative.back();
582
583 // Let the data iterator point to the correct buffer.
584 // Adjust buffer iterator to the offset of the callback
585 // function so that we only have to advance its position
586 // to the next cell after each iteration.
587 if (cell_relations.begin() != cell_relations.end())
588 dest_data_it = dest_data_fixed.cbegin() + offset;
589 }
590
591 // Iterate over all cells and unpack the transferred data.
592 auto cell_rel_it = cell_relations.begin();
593 auto dest_sizes_it = dest_sizes_variable.cbegin();
594 for (; cell_rel_it != cell_relations.end(); ++cell_rel_it)
595 {
596 const auto &dealii_cell = cell_rel_it->first;
597 const auto &cell_status = cell_rel_it->second;
598
599 if (callback_variable_transfer)
600 {
601 // Update the increment according to the whole data size
602 // of the current cell.
603 data_increment = *dest_sizes_it;
604
605 if (cell_status != CellStatus::cell_invalid)
606 {
607 // Extract the corresponding values for offset and size from
608 // the cumulative sizes array stored in the fixed size
609 // buffer.
610 if (callback_index == 0)
611 offset = 0;
612 else
613 std::memcpy(&offset,
614 &(*(dest_sizes_cell_it - sizeof(unsigned int))),
615 sizeof(unsigned int));
616
617 std::memcpy(&size,
618 &(*dest_sizes_cell_it),
619 sizeof(unsigned int));
620
621 size -= offset;
622
623 // Move the data iterator to the corresponding position
624 // of the callback function and adjust the increment
625 // accordingly.
626 dest_data_it += offset;
627 data_increment -= offset;
628 }
629
630 // Advance data size iterators to the next cell, avoid iterating
631 // past the end of dest_sizes_cell_it
632 if (cell_rel_it != cell_relations.end() - 1)
633 dest_sizes_cell_it += sizes_fixed_cumulative.back();
634 ++dest_sizes_it;
635 }
636
637 switch (cell_status)
638 {
641 unpack_callback(dealii_cell,
642 cell_status,
643 boost::make_iterator_range(dest_data_it,
644 dest_data_it + size));
645 break;
646
648 unpack_callback(dealii_cell->parent(),
649 cell_status,
650 boost::make_iterator_range(dest_data_it,
651 dest_data_it + size));
652 break;
653
655 // Skip this cell.
656 break;
657
658 default:
660 break;
661 }
662
663 if (cell_rel_it != cell_relations.end() - 1)
664 dest_data_it += data_increment;
665 }
666 }
667
668
669
670 template <int dim, int spacedim>
672 void CellAttachedDataSerializer<dim, spacedim>::save(
673 const unsigned int global_first_cell,
674 const unsigned int global_num_cells,
675 const std::string &filename,
676 const MPI_Comm &mpi_communicator) const
677 {
678 Assert(sizes_fixed_cumulative.size() > 0,
679 ExcMessage("No data has been packed!"));
680
681#ifdef DEAL_II_WITH_MPI
682 // Large fractions of this function have been copied from
683 // DataOutInterface::write_vtu_in_parallel.
684 // TODO: Write general MPIIO interface.
685
686 const int myrank = Utilities::MPI::this_mpi_process(mpi_communicator);
687 const int mpisize = Utilities::MPI::n_mpi_processes(mpi_communicator);
688
689 if (mpisize > 1)
690 {
691 const unsigned int bytes_per_cell = sizes_fixed_cumulative.back();
692
693 //
694 // ---------- Fixed size data ----------
695 //
696 {
697 const std::string fname_fixed = std::string(filename) + "_fixed.data";
698
699 MPI_Info info;
700 int ierr = MPI_Info_create(&info);
701 AssertThrowMPI(ierr);
702
703 MPI_File fh;
704 ierr = MPI_File_open(mpi_communicator,
705 fname_fixed.c_str(),
706 MPI_MODE_CREATE | MPI_MODE_WRONLY,
707 info,
708 &fh);
709 AssertThrowMPI(ierr);
710
711 ierr = MPI_File_set_size(fh, 0); // delete the file contents
712 AssertThrowMPI(ierr);
713 // this barrier is necessary, because otherwise others might already
714 // write while one core is still setting the size to zero.
715 ierr = MPI_Barrier(mpi_communicator);
716 AssertThrowMPI(ierr);
717 ierr = MPI_Info_free(&info);
718 AssertThrowMPI(ierr);
719 // ------------------
720
721 // Write cumulative sizes to file.
722 // Since each processor owns the same information about the data
723 // sizes, it is sufficient to let only the first processor perform
724 // this task.
725 if (myrank == 0)
726 {
728 fh,
729 0,
730 sizes_fixed_cumulative.data(),
731 sizes_fixed_cumulative.size(),
732 MPI_UNSIGNED,
733 MPI_STATUS_IGNORE);
734 AssertThrowMPI(ierr);
735 }
736
737 // Write packed data to file simultaneously.
738 const MPI_Offset size_header =
739 sizes_fixed_cumulative.size() * sizeof(unsigned int);
740
741 // Make sure we do the following computation in 64bit integers to be
742 // able to handle 4GB+ files:
743 const MPI_Offset my_global_file_position =
744 size_header +
745 static_cast<MPI_Offset>(global_first_cell) * bytes_per_cell;
746
747 ierr =
749 my_global_file_position,
750 src_data_fixed.data(),
751 src_data_fixed.size(),
752 MPI_BYTE,
753 MPI_STATUS_IGNORE);
754 AssertThrowMPI(ierr);
755
756 ierr = MPI_File_close(&fh);
757 AssertThrowMPI(ierr);
758 }
759
760
761
762 //
763 // ---------- Variable size data ----------
764 //
765 if (variable_size_data_stored)
766 {
767 const std::string fname_variable =
768 std::string(filename) + "_variable.data";
769
770 MPI_Info info;
771 int ierr = MPI_Info_create(&info);
772 AssertThrowMPI(ierr);
773
774 MPI_File fh;
775 ierr = MPI_File_open(mpi_communicator,
776 fname_variable.c_str(),
777 MPI_MODE_CREATE | MPI_MODE_WRONLY,
778 info,
779 &fh);
780 AssertThrowMPI(ierr);
781
782 ierr = MPI_File_set_size(fh, 0); // delete the file contents
783 AssertThrowMPI(ierr);
784 // this barrier is necessary, because otherwise others might already
785 // write while one core is still setting the size to zero.
786 ierr = MPI_Barrier(mpi_communicator);
787 AssertThrowMPI(ierr);
788 ierr = MPI_Info_free(&info);
789 AssertThrowMPI(ierr);
790
791 // Write sizes of each cell into file simultaneously.
792 {
793 const MPI_Offset my_global_file_position =
794 static_cast<MPI_Offset>(global_first_cell) *
795 sizeof(unsigned int);
796
797 // It is very unlikely that a single process has more than
798 // 2 billion cells, but we might as well check.
799 AssertThrow(src_sizes_variable.size() <
800 static_cast<std::size_t>(
801 std::numeric_limits<int>::max()),
803
805 fh,
806 my_global_file_position,
807 src_sizes_variable.data(),
808 src_sizes_variable.size(),
809 MPI_INT,
810 MPI_STATUS_IGNORE);
811 AssertThrowMPI(ierr);
812 }
813
814 // Gather size of data in bytes we want to store from this
815 // processor and compute the prefix sum. We do this in 64 bit
816 // to avoid overflow for files larger than 4GB:
817 const std::uint64_t size_on_proc = src_data_variable.size();
818 std::uint64_t prefix_sum = 0;
819 ierr = MPI_Exscan(&size_on_proc,
820 &prefix_sum,
821 1,
822 MPI_UINT64_T,
823 MPI_SUM,
824 mpi_communicator);
825 AssertThrowMPI(ierr);
826
827 const MPI_Offset my_global_file_position =
828 static_cast<MPI_Offset>(global_num_cells) * sizeof(unsigned int) +
829 prefix_sum;
830
831 // Write data consecutively into file.
833 fh,
834 my_global_file_position,
835 src_data_variable.data(),
836 src_data_variable.size(),
837 MPI_BYTE,
838 MPI_STATUS_IGNORE);
839 AssertThrowMPI(ierr);
840
841
842 ierr = MPI_File_close(&fh);
843 AssertThrowMPI(ierr);
844 }
845 } // if (mpisize > 1)
846 else
847#endif
848 {
849 (void)global_first_cell;
850 (void)global_num_cells;
851 (void)mpi_communicator;
852
853 //
854 // ---------- Fixed size data ----------
855 //
856 {
857 const std::string fname_fixed = std::string(filename) + "_fixed.data";
858
859 std::ofstream file(fname_fixed, std::ios::binary | std::ios::out);
860
861 // Write header data.
862 file.write(reinterpret_cast<const char *>(
863 sizes_fixed_cumulative.data()),
864 sizes_fixed_cumulative.size() * sizeof(unsigned int));
865
866 // Write packed data.
867 file.write(reinterpret_cast<const char *>(src_data_fixed.data()),
868 src_data_fixed.size() * sizeof(char));
869
870 file.close();
871 }
872
873 //
874 // ---------- Variable size data ----------
875 //
876 if (variable_size_data_stored)
877 {
878 const std::string fname_variable =
879 std::string(filename) + "_variable.data";
880
881 std::ofstream file(fname_variable,
882 std::ios::binary | std::ios::out);
883
884 // Write header data.
885 file.write(reinterpret_cast<const char *>(
886 src_sizes_variable.data()),
887 src_sizes_variable.size() * sizeof(int));
888
889 // Write packed data.
890 file.write(reinterpret_cast<const char *>(src_data_variable.data()),
891 src_data_variable.size() * sizeof(char));
892
893 file.close();
894 }
895 }
896 }
897
898
899 template <int dim, int spacedim>
901 void CellAttachedDataSerializer<dim, spacedim>::load(
902 const unsigned int global_first_cell,
903 const unsigned int global_num_cells,
904 const unsigned int local_num_cells,
905 const std::string &filename,
906 const unsigned int n_attached_deserialize_fixed,
907 const unsigned int n_attached_deserialize_variable,
908 const MPI_Comm &mpi_communicator)
909 {
910 Assert(dest_data_fixed.empty(),
911 ExcMessage("Previously loaded data has not been released yet!"));
912
913 variable_size_data_stored = (n_attached_deserialize_variable > 0);
914
915#ifdef DEAL_II_WITH_MPI
916 // Large fractions of this function have been copied from
917 // DataOutInterface::write_vtu_in_parallel.
918 // TODO: Write general MPIIO interface.
919
920 const int mpisize = Utilities::MPI::n_mpi_processes(mpi_communicator);
921
922 if (mpisize > 1)
923 {
924 //
925 // ---------- Fixed size data ----------
926 //
927 {
928 const std::string fname_fixed = std::string(filename) + "_fixed.data";
929
930 MPI_Info info;
931 int ierr = MPI_Info_create(&info);
932 AssertThrowMPI(ierr);
933
934 MPI_File fh;
935 ierr = MPI_File_open(
936 mpi_communicator, fname_fixed.c_str(), MPI_MODE_RDONLY, info, &fh);
937 AssertThrowMPI(ierr);
938
939 ierr = MPI_Info_free(&info);
940 AssertThrowMPI(ierr);
941
942 // Read cumulative sizes from file.
943 // Since all processors need the same information about the data
944 // sizes, let each of them retrieve it by reading from the same
945 // location in the file.
946 sizes_fixed_cumulative.resize(1 + n_attached_deserialize_fixed +
947 (variable_size_data_stored ? 1 : 0));
949 fh,
950 0,
951 sizes_fixed_cumulative.data(),
952 sizes_fixed_cumulative.size(),
953 MPI_UNSIGNED,
954 MPI_STATUS_IGNORE);
955 AssertThrowMPI(ierr);
956
957 // Allocate sufficient memory.
958 const unsigned int bytes_per_cell = sizes_fixed_cumulative.back();
959 dest_data_fixed.resize(static_cast<size_t>(local_num_cells) *
960 bytes_per_cell);
961
962 // Read packed data from file simultaneously.
963 const MPI_Offset size_header =
964 sizes_fixed_cumulative.size() * sizeof(unsigned int);
965
966 // Make sure we do the following computation in 64bit integers to be
967 // able to handle 4GB+ files:
968 const MPI_Offset my_global_file_position =
969 size_header +
970 static_cast<MPI_Offset>(global_first_cell) * bytes_per_cell;
971
972 ierr =
974 my_global_file_position,
975 dest_data_fixed.data(),
976 dest_data_fixed.size(),
977 MPI_BYTE,
978 MPI_STATUS_IGNORE);
979 AssertThrowMPI(ierr);
980
981
982 ierr = MPI_File_close(&fh);
983 AssertThrowMPI(ierr);
984 }
985
986 //
987 // ---------- Variable size data ----------
988 //
989 if (variable_size_data_stored)
990 {
991 const std::string fname_variable =
992 std::string(filename) + "_variable.data";
993
994 MPI_Info info;
995 int ierr = MPI_Info_create(&info);
996 AssertThrowMPI(ierr);
997
998 MPI_File fh;
999 ierr = MPI_File_open(mpi_communicator,
1000 fname_variable.c_str(),
1001 MPI_MODE_RDONLY,
1002 info,
1003 &fh);
1004 AssertThrowMPI(ierr);
1005
1006 ierr = MPI_Info_free(&info);
1007 AssertThrowMPI(ierr);
1008
1009 // Read sizes of all locally owned cells.
1010 dest_sizes_variable.resize(local_num_cells);
1011
1012 const MPI_Offset my_global_file_position_sizes =
1013 static_cast<MPI_Offset>(global_first_cell) * sizeof(unsigned int);
1014
1016 fh,
1017 my_global_file_position_sizes,
1018 dest_sizes_variable.data(),
1019 dest_sizes_variable.size(),
1020 MPI_INT,
1021 MPI_STATUS_IGNORE);
1022 AssertThrowMPI(ierr);
1023
1024
1025 // Compute my data size in bytes and compute prefix sum. We do this
1026 // in 64 bit to avoid overflow for files larger than 4 GB:
1027 const std::uint64_t size_on_proc =
1028 std::accumulate(dest_sizes_variable.begin(),
1029 dest_sizes_variable.end(),
1030 0ULL);
1031
1032 std::uint64_t prefix_sum = 0;
1033 ierr = MPI_Exscan(&size_on_proc,
1034 &prefix_sum,
1035 1,
1036 MPI_UINT64_T,
1037 MPI_SUM,
1038 mpi_communicator);
1039 AssertThrowMPI(ierr);
1040
1041 const MPI_Offset my_global_file_position =
1042 static_cast<MPI_Offset>(global_num_cells) * sizeof(unsigned int) +
1043 prefix_sum;
1044
1045 dest_data_variable.resize(size_on_proc);
1046
1048 fh,
1049 my_global_file_position,
1050 dest_data_variable.data(),
1051 dest_data_variable.size(),
1052 MPI_BYTE,
1053 MPI_STATUS_IGNORE);
1054 AssertThrowMPI(ierr);
1055
1056 ierr = MPI_File_close(&fh);
1057 AssertThrowMPI(ierr);
1058 }
1059 }
1060 else // if (mpisize > 1)
1061#endif
1062 {
1063 (void)global_first_cell;
1064 (void)global_num_cells;
1065 (void)mpi_communicator;
1066
1067 //
1068 // ---------- Fixed size data ----------
1069 //
1070 {
1071 const std::string fname_fixed = std::string(filename) + "_fixed.data";
1072
1073 std::ifstream file(fname_fixed, std::ios::binary | std::ios::in);
1074 sizes_fixed_cumulative.resize(1 + n_attached_deserialize_fixed +
1075 (variable_size_data_stored ? 1 : 0));
1076
1077 // Read header data.
1078 file.read(reinterpret_cast<char *>(sizes_fixed_cumulative.data()),
1079 sizes_fixed_cumulative.size() * sizeof(unsigned int));
1080
1081 const unsigned int bytes_per_cell = sizes_fixed_cumulative.back();
1082 dest_data_fixed.resize(static_cast<size_t>(local_num_cells) *
1083 bytes_per_cell);
1084
1085 // Read packed data.
1086 file.read(reinterpret_cast<char *>(dest_data_fixed.data()),
1087 dest_data_fixed.size() * sizeof(char));
1088
1089 file.close();
1090 }
1091
1092 //
1093 // ---------- Variable size data ----------
1094 //
1095 if (variable_size_data_stored)
1096 {
1097 const std::string fname_variable =
1098 std::string(filename) + "_variable.data";
1099
1100 std::ifstream file(fname_variable, std::ios::binary | std::ios::in);
1101
1102 // Read header data.
1103 dest_sizes_variable.resize(local_num_cells);
1104 file.read(reinterpret_cast<char *>(dest_sizes_variable.data()),
1105 dest_sizes_variable.size() * sizeof(int));
1106
1107 // Read packed data.
1108 const std::uint64_t size =
1109 std::accumulate(dest_sizes_variable.begin(),
1110 dest_sizes_variable.end(),
1111 0ULL);
1112 dest_data_variable.resize(size);
1113 file.read(reinterpret_cast<char *>(dest_data_variable.data()),
1114 dest_data_variable.size() * sizeof(char));
1115
1116 file.close();
1117 }
1118 }
1119 }
1120
1121
1122 template <int dim, int spacedim>
1124 void CellAttachedDataSerializer<dim, spacedim>::clear()
1125 {
1126 variable_size_data_stored = false;
1127
1128 // free information about data sizes
1129 sizes_fixed_cumulative.clear();
1130 sizes_fixed_cumulative.shrink_to_fit();
1131
1132 // free fixed size transfer data
1133 src_data_fixed.clear();
1134 src_data_fixed.shrink_to_fit();
1135
1136 dest_data_fixed.clear();
1137 dest_data_fixed.shrink_to_fit();
1138
1139 // free variable size transfer data
1140 src_sizes_variable.clear();
1141 src_sizes_variable.shrink_to_fit();
1142
1143 src_data_variable.clear();
1144 src_data_variable.shrink_to_fit();
1145
1146 dest_sizes_variable.clear();
1147 dest_sizes_variable.shrink_to_fit();
1148
1149 dest_data_variable.clear();
1150 dest_data_variable.shrink_to_fit();
1151 }
1152
1153} // namespace internal
1154
1155// anonymous namespace for internal helper functions
1156namespace
1157{
1158 // return whether the given cell is
1159 // patch_level_1, i.e. determine
1160 // whether either all or none of
1161 // its children are further
1162 // refined. this function can only
1163 // be called for non-active cells.
1164 template <int dim, int spacedim>
1165 bool
1166 cell_is_patch_level_1(
1168 {
1169 Assert(cell->is_active() == false, ExcInternalError());
1170
1171 unsigned int n_active_children = 0;
1172 for (unsigned int i = 0; i < cell->n_children(); ++i)
1173 if (cell->child(i)->is_active())
1174 ++n_active_children;
1175
1176 return (n_active_children == 0) ||
1177 (n_active_children == cell->n_children());
1178 }
1179
1180
1181
1182 // return, whether a given @p cell will be
1183 // coarsened, which is the case if all
1184 // children are active and have their coarsen
1185 // flag set. In case only part of the coarsen
1186 // flags are set, remove them.
1187 template <int dim, int spacedim>
1188 bool
1189 cell_will_be_coarsened(
1191 {
1192 // only cells with children should be
1193 // considered for coarsening
1194
1195 if (cell->has_children())
1196 {
1197 unsigned int children_to_coarsen = 0;
1198 const unsigned int n_children = cell->n_children();
1199
1200 for (unsigned int c = 0; c < n_children; ++c)
1201 if (cell->child(c)->is_active() && cell->child(c)->coarsen_flag_set())
1202 ++children_to_coarsen;
1203 if (children_to_coarsen == n_children)
1204 return true;
1205 else
1206 for (unsigned int c = 0; c < n_children; ++c)
1207 if (cell->child(c)->is_active())
1208 cell->child(c)->clear_coarsen_flag();
1209 }
1210 // no children, so no coarsening
1211 // possible. however, no children also
1212 // means that this cell will be in the same
1213 // state as if it had children and was
1214 // coarsened. So, what should we return -
1215 // false or true?
1216 // make sure we do not have to do this at
1217 // all...
1218 Assert(cell->has_children(), ExcInternalError());
1219 // ... and then simply return false
1220 return false;
1221 }
1222
1223
1224 // return, whether the face @p face_no of the
1225 // given @p cell will be refined after the
1226 // current refinement step, considering
1227 // refine and coarsen flags and considering
1228 // only those refinemnts that will be caused
1229 // by the neighboring cell.
1230
1231 // this function is used on both active cells
1232 // and cells with children. on cells with
1233 // children it also of interest to know 'how'
1234 // the face will be refined. thus there is an
1235 // additional third argument @p
1236 // expected_face_ref_case returning just
1237 // that. be aware, that this variable will
1238 // only contain useful information if this
1239 // function is called for an active cell.
1240 //
1241 // thus, this is an internal function, users
1242 // should call one of the two alternatives
1243 // following below.
1244 template <int dim, int spacedim>
1245 bool
1246 face_will_be_refined_by_neighbor_internal(
1248 const unsigned int face_no,
1249 RefinementCase<dim - 1> &expected_face_ref_case)
1250 {
1251 // first of all: set the default value for
1252 // expected_face_ref_case, which is no
1253 // refinement at all
1254 expected_face_ref_case = RefinementCase<dim - 1>::no_refinement;
1255
1256 const typename Triangulation<dim, spacedim>::cell_iterator neighbor =
1257 cell->neighbor(face_no);
1258
1259 // If we are at the boundary, there is no
1260 // neighbor which could refine the face
1261 if (neighbor.state() != IteratorState::valid)
1262 return false;
1263
1264 if (neighbor->has_children())
1265 {
1266 // if the neighbor is refined, it may be
1267 // coarsened. if so, then it won't refine
1268 // the face, no matter what else happens
1269 if (cell_will_be_coarsened(neighbor))
1270 return false;
1271 else
1272 // if the neighbor is refined, then it
1273 // is also refined at our current
1274 // face. It will stay so without
1275 // coarsening, so return true in that
1276 // case.
1277 {
1278 expected_face_ref_case = cell->face(face_no)->refinement_case();
1279 return true;
1280 }
1281 }
1282
1283 // now, the neighbor is not refined, but
1284 // perhaps it will be
1285 const RefinementCase<dim> nb_ref_flag = neighbor->refine_flag_set();
1286 if (nb_ref_flag != RefinementCase<dim>::no_refinement)
1287 {
1288 // now we need to know, which of the
1289 // neighbors faces points towards us
1290 const unsigned int neighbor_neighbor = cell->neighbor_face_no(face_no);
1291 // check, whether the cell will be
1292 // refined in a way that refines our
1293 // face
1294 const RefinementCase<dim - 1> face_ref_case =
1296 nb_ref_flag,
1297 neighbor_neighbor,
1298 neighbor->face_orientation(neighbor_neighbor),
1299 neighbor->face_flip(neighbor_neighbor),
1300 neighbor->face_rotation(neighbor_neighbor));
1301 if (face_ref_case != RefinementCase<dim - 1>::no_refinement)
1302 {
1304 neighbor_face = neighbor->face(neighbor_neighbor);
1305 const int this_face_index = cell->face_index(face_no);
1306
1307 // there are still two basic
1308 // possibilities here: the neighbor
1309 // might be coarser or as coarse
1310 // as we are
1311 if (neighbor_face->index() == this_face_index)
1312 // the neighbor is as coarse as
1313 // we are and will be refined at
1314 // the face of consideration, so
1315 // return true
1316 {
1317 expected_face_ref_case = face_ref_case;
1318 return true;
1319 }
1320 else
1321 {
1322 // the neighbor is coarser.
1323 // this is the most complicated
1324 // case. It might be, that the
1325 // neighbor's face will be
1326 // refined, but that we will
1327 // not see this, as we are
1328 // refined in a similar way.
1329
1330 // so, the neighbor's face must
1331 // have children. check, if our
1332 // cell's face is one of these
1333 // (it could also be a
1334 // grand_child)
1335 for (unsigned int c = 0; c < neighbor_face->n_children(); ++c)
1336 if (neighbor_face->child_index(c) == this_face_index)
1337 {
1338 // if the flagged refine
1339 // case of the face is a
1340 // subset or the same as
1341 // the current refine case,
1342 // then the face, as seen
1343 // from our cell, won't be
1344 // refined by the neighbor
1345 if ((neighbor_face->refinement_case() | face_ref_case) ==
1346 neighbor_face->refinement_case())
1347 return false;
1348 else
1349 {
1350 // if we are active, we
1351 // must be an
1352 // anisotropic child
1353 // and the coming
1354 // face_ref_case is
1355 // isotropic. Thus,
1356 // from our cell we
1357 // will see exactly the
1358 // opposite refine case
1359 // that the face has
1360 // now...
1361 Assert(
1362 face_ref_case ==
1365 expected_face_ref_case =
1366 ~neighbor_face->refinement_case();
1367 return true;
1368 }
1369 }
1370
1371 // so, obviously we were not
1372 // one of the children, but a
1373 // grandchild. This is only
1374 // possible in 3d.
1375 Assert(dim == 3, ExcInternalError());
1376 // In that case, however, no
1377 // matter what the neighbor
1378 // does, it won't be finer
1379 // after the next refinement
1380 // step.
1381 return false;
1382 }
1383 } // if face will be refined
1384 } // if neighbor is flagged for refinement
1385
1386 // no cases left, so the neighbor will not
1387 // refine the face
1388 return false;
1389 }
1390
1391 // version of above function for both active
1392 // and non-active cells
1393 template <int dim, int spacedim>
1394 bool
1395 face_will_be_refined_by_neighbor(
1397 const unsigned int face_no)
1398 {
1399 RefinementCase<dim - 1> dummy = RefinementCase<dim - 1>::no_refinement;
1400 return face_will_be_refined_by_neighbor_internal(cell, face_no, dummy);
1401 }
1402
1403 // version of above function for active cells
1404 // only. Additionally returning the refine
1405 // case (to come) of the face under
1406 // consideration
1407 template <int dim, int spacedim>
1408 bool
1409 face_will_be_refined_by_neighbor(
1411 const unsigned int face_no,
1412 RefinementCase<dim - 1> &expected_face_ref_case)
1413 {
1414 return face_will_be_refined_by_neighbor_internal(cell,
1415 face_no,
1416 expected_face_ref_case);
1417 }
1418
1419
1420
1421 template <int dim, int spacedim>
1422 bool
1423 satisfies_level1_at_vertex_rule(
1425 {
1426 std::vector<unsigned int> min_adjacent_cell_level(
1427 triangulation.n_vertices(), triangulation.n_levels());
1428 std::vector<unsigned int> max_adjacent_cell_level(
1429 triangulation.n_vertices(), 0);
1430
1431 for (const auto &cell : triangulation.active_cell_iterators())
1432 for (const unsigned int v : cell->vertex_indices())
1433 {
1434 min_adjacent_cell_level[cell->vertex_index(v)] =
1435 std::min<unsigned int>(
1436 min_adjacent_cell_level[cell->vertex_index(v)], cell->level());
1437 max_adjacent_cell_level[cell->vertex_index(v)] =
1438 std::max<unsigned int>(
1439 min_adjacent_cell_level[cell->vertex_index(v)], cell->level());
1440 }
1441
1442 for (unsigned int k = 0; k < triangulation.n_vertices(); ++k)
1443 if (triangulation.vertex_used(k))
1444 if (max_adjacent_cell_level[k] - min_adjacent_cell_level[k] > 1)
1445 return false;
1446 return true;
1447 }
1448
1449
1450
1468 template <int dim, int spacedim>
1469 unsigned int
1470 middle_vertex_index(
1472 {
1473 if (line->has_children())
1474 return line->child(0)->vertex_index(1);
1476 }
1477
1478
1479 template <int dim, int spacedim>
1480 unsigned int
1481 middle_vertex_index(
1483 {
1484 switch (static_cast<unsigned char>(quad->refinement_case()))
1485 {
1487 return middle_vertex_index<dim, spacedim>(quad->child(0)->line(1));
1488 break;
1490 return middle_vertex_index<dim, spacedim>(quad->child(0)->line(3));
1491 break;
1493 return quad->child(0)->vertex_index(3);
1494 break;
1495 default:
1496 break;
1497 }
1499 }
1500
1501
1502 template <int dim, int spacedim>
1503 unsigned int
1504 middle_vertex_index(
1506 {
1507 switch (static_cast<unsigned char>(hex->refinement_case()))
1508 {
1510 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(1));
1511 break;
1513 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(3));
1514 break;
1516 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(5));
1517 break;
1519 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(11));
1520 break;
1522 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(5));
1523 break;
1525 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(7));
1526 break;
1528 return hex->child(0)->vertex_index(7);
1529 break;
1530 default:
1531 break;
1532 }
1534 }
1535
1536
1549 template <class TRIANGULATION>
1550 inline typename TRIANGULATION::DistortedCellList
1551 collect_distorted_coarse_cells(const TRIANGULATION &)
1552 {
1553 return typename TRIANGULATION::DistortedCellList();
1554 }
1555
1556
1557
1566 template <int dim>
1568 collect_distorted_coarse_cells(const Triangulation<dim, dim> &triangulation)
1569 {
1570 typename Triangulation<dim, dim>::DistortedCellList distorted_cells;
1571 for (const auto &cell : triangulation.cell_iterators_on_level(0))
1572 {
1574 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1575 vertices[i] = cell->vertex(i);
1576
1579
1580 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1581 if (determinants[i] <=
1582 1e-9 * Utilities::fixed_power<dim>(cell->diameter()))
1583 {
1584 distorted_cells.distorted_cells.push_back(cell);
1585 break;
1586 }
1587 }
1588
1589 return distorted_cells;
1590 }
1591
1592
1599 template <int dim>
1600 bool
1601 has_distorted_children(
1602 const typename Triangulation<dim, dim>::cell_iterator &cell)
1603 {
1604 Assert(cell->has_children(), ExcInternalError());
1605
1606 for (unsigned int c = 0; c < cell->n_children(); ++c)
1607 {
1609 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1610 vertices[i] = cell->child(c)->vertex(i);
1611
1614
1615 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1616 if (determinants[i] <=
1617 1e-9 * Utilities::fixed_power<dim>(cell->child(c)->diameter()))
1618 return true;
1619 }
1620
1621 return false;
1622 }
1623
1624
1632 template <int dim, int spacedim>
1633 bool
1634 has_distorted_children(
1636 {
1637 return false;
1638 }
1639
1640
1641 template <int dim, int spacedim>
1642 void
1643 update_periodic_face_map_recursively(
1644 const typename Triangulation<dim, spacedim>::cell_iterator &cell_1,
1645 const typename Triangulation<dim, spacedim>::cell_iterator &cell_2,
1646 unsigned int n_face_1,
1647 unsigned int n_face_2,
1648 const unsigned char orientation,
1649 typename std::map<
1651 unsigned int>,
1652 std::pair<std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
1653 unsigned int>,
1654 unsigned char>> &periodic_face_map)
1655 {
1656 using FaceIterator = typename Triangulation<dim, spacedim>::face_iterator;
1657 const FaceIterator face_1 = cell_1->face(n_face_1);
1658 const FaceIterator face_2 = cell_2->face(n_face_2);
1659
1660 const unsigned char inverse_orientation =
1661 face_1->reference_cell().get_inverse_combined_orientation(orientation);
1662
1663#ifdef DEBUG
1664 const auto [face_orientation, face_rotation, face_flip] =
1666
1667 Assert((dim != 1) || (face_orientation == true && face_flip == false &&
1668 face_rotation == false),
1669 ExcMessage("The supplied orientation "
1670 "(face_orientation, face_flip, face_rotation) "
1671 "is invalid for 1d"));
1672
1673 Assert((dim != 2) || (face_flip == false && face_rotation == false),
1674 ExcMessage("The supplied orientation "
1675 "(face_orientation, face_flip, face_rotation) "
1676 "is invalid for 2d"));
1677#endif
1678
1679 Assert(face_1 != face_2, ExcMessage("face_1 and face_2 are equal!"));
1680
1681 Assert(face_1->at_boundary() && face_2->at_boundary(),
1682 ExcMessage("Periodic faces must be on the boundary"));
1683
1684 // Check if the requirement that each edge can only have at most one hanging
1685 // node, and as a consequence neighboring cells can differ by at most
1686 // one refinement level is enforced. In 1d, there are no hanging nodes and
1687 // so neighboring cells can differ by more than one refinement level.
1688 Assert(dim == 1 || std::abs(cell_1->level() - cell_2->level()) < 2,
1690
1691 // insert periodic face pair for both cells
1692 using CellFace =
1693 std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
1694 unsigned int>;
1695 const CellFace cell_face_1(cell_1, n_face_1);
1696 const CellFace cell_face_2(cell_2, n_face_2);
1697 const std::pair<CellFace, unsigned char> cell_face_orientation_2(
1698 cell_face_2, orientation);
1699
1700 const std::pair<CellFace, std::pair<CellFace, unsigned char>>
1701 periodic_faces(cell_face_1, cell_face_orientation_2);
1702
1703 // Only one periodic neighbor is allowed
1704 Assert(periodic_face_map.count(cell_face_1) == 0, ExcInternalError());
1705 periodic_face_map.insert(periodic_faces);
1706
1707 if (dim == 1)
1708 {
1709 if (cell_1->has_children())
1710 {
1711 if (cell_2->has_children())
1712 {
1713 update_periodic_face_map_recursively<dim, spacedim>(
1714 cell_1->child(n_face_1),
1715 cell_2->child(n_face_2),
1716 n_face_1,
1717 n_face_2,
1718 orientation,
1719 periodic_face_map);
1720 }
1721 else // only face_1 has children
1722 {
1723 update_periodic_face_map_recursively<dim, spacedim>(
1724 cell_1->child(n_face_1),
1725 cell_2,
1726 n_face_1,
1727 n_face_2,
1728 orientation,
1729 periodic_face_map);
1730 }
1731 }
1732 }
1733 else // dim == 2 || dim == 3
1734 {
1735 if (cell_1->has_children())
1736 {
1737 if (cell_2->has_children())
1738 {
1739 // In the case that both faces have children, we loop over all
1740 // children and apply update_periodic_face_map_recursively
1741 // recursively:
1742
1743 Assert(face_1->n_children() ==
1745 face_2->n_children() ==
1748
1749 const auto reference_cell = cell_1->reference_cell();
1750
1751 for (unsigned int i = 0;
1752 i < GeometryInfo<dim>::max_children_per_face;
1753 ++i)
1754 {
1755 // Lookup the index for the second face
1756 const unsigned int j =
1757 reference_cell.standard_to_real_face_vertex(
1758 i, n_face_1, inverse_orientation);
1759
1760 // find subcell ids that belong to the subface indices
1761 unsigned int child_cell_1 =
1763 cell_1->refinement_case(),
1764 n_face_1,
1765 i,
1766 cell_1->face_orientation(n_face_1),
1767 cell_1->face_flip(n_face_1),
1768 cell_1->face_rotation(n_face_1),
1769 face_1->refinement_case());
1770 unsigned int child_cell_2 =
1772 cell_2->refinement_case(),
1773 n_face_2,
1774 j,
1775 cell_2->face_orientation(n_face_2),
1776 cell_2->face_flip(n_face_2),
1777 cell_2->face_rotation(n_face_2),
1778 face_2->refinement_case());
1779
1780 Assert(cell_1->child(child_cell_1)->face(n_face_1) ==
1781 face_1->child(i),
1783 Assert(cell_2->child(child_cell_2)->face(n_face_2) ==
1784 face_2->child(j),
1786
1787 // precondition: subcell has the same orientation as cell
1788 // (so that the face numbers coincide) recursive call
1789 update_periodic_face_map_recursively<dim, spacedim>(
1790 cell_1->child(child_cell_1),
1791 cell_2->child(child_cell_2),
1792 n_face_1,
1793 n_face_2,
1794 orientation,
1795 periodic_face_map);
1796 }
1797 }
1798 else // only face_1 has children
1799 {
1800 for (unsigned int i = 0;
1801 i < GeometryInfo<dim>::max_children_per_face;
1802 ++i)
1803 {
1804 // find subcell ids that belong to the subface indices
1805 unsigned int child_cell_1 =
1807 cell_1->refinement_case(),
1808 n_face_1,
1809 i,
1810 cell_1->face_orientation(n_face_1),
1811 cell_1->face_flip(n_face_1),
1812 cell_1->face_rotation(n_face_1),
1813 face_1->refinement_case());
1814
1815 // recursive call
1816 update_periodic_face_map_recursively<dim, spacedim>(
1817 cell_1->child(child_cell_1),
1818 cell_2,
1819 n_face_1,
1820 n_face_2,
1821 orientation,
1822 periodic_face_map);
1823 }
1824 }
1825 }
1826 }
1827 }
1828
1829
1830} // end of anonymous namespace
1831
1832
1833namespace internal
1834{
1835 namespace TriangulationImplementation
1836 {
1837 // make sure that if in the following we
1838 // write Triangulation<dim,spacedim>
1839 // we mean the *class*
1840 // ::Triangulation, not the
1841 // enclosing namespace
1842 // internal::TriangulationImplementation
1843 using ::Triangulation;
1844
1850 int,
1851 << "Something went wrong upon construction of cell "
1852 << arg1);
1863 int,
1864 << "Cell " << arg1
1865 << " has negative measure. This typically "
1866 << "indicates some distortion in the cell, or a mistakenly "
1867 << "swapped pair of vertices in the input to "
1868 << "Triangulation::create_triangulation().");
1877 int,
1878 int,
1879 int,
1880 << "Error while creating cell " << arg1
1881 << ": the vertex index " << arg2 << " must be between 0 and "
1882 << arg3 << '.');
1889 int,
1890 int,
1892 << "The input data for creating a triangulation contained "
1893 << "information about a line with indices " << arg1 << " and " << arg2
1894 << " that is described to have boundary indicator "
1895 << static_cast<int>(arg3)
1896 << ". However, this is an internal line not located on the "
1897 << "boundary. You cannot assign a boundary indicator to it." << std::endl
1898 << std::endl
1899 << "If this happened at a place where you call "
1900 << "Triangulation::create_triangulation() yourself, you need "
1901 << "to check the SubCellData object you pass to this function."
1902 << std::endl
1903 << std::endl
1904 << "If this happened in a place where you are reading a mesh "
1905 << "from a file, then you need to investigate why such a line "
1906 << "ended up in the input file. A typical case is a geometry "
1907 << "that consisted of multiple parts and for which the mesh "
1908 << "generator program assumes that the interface between "
1909 << "two parts is a boundary when that isn't supposed to be "
1910 << "the case, or where the mesh generator simply assigns "
1911 << "'geometry indicators' to lines at the perimeter of "
1912 << "a part that are not supposed to be interpreted as "
1913 << "'boundary indicators'.");
1920 int,
1921 int,
1922 int,
1923 int,
1925 << "The input data for creating a triangulation contained "
1926 << "information about a quad with indices " << arg1 << ", " << arg2
1927 << ", " << arg3 << ", and " << arg4
1928 << " that is described to have boundary indicator "
1929 << static_cast<int>(arg5)
1930 << ". However, this is an internal quad not located on the "
1931 << "boundary. You cannot assign a boundary indicator to it." << std::endl
1932 << std::endl
1933 << "If this happened at a place where you call "
1934 << "Triangulation::create_triangulation() yourself, you need "
1935 << "to check the SubCellData object you pass to this function."
1936 << std::endl
1937 << std::endl
1938 << "If this happened in a place where you are reading a mesh "
1939 << "from a file, then you need to investigate why such a quad "
1940 << "ended up in the input file. A typical case is a geometry "
1941 << "that consisted of multiple parts and for which the mesh "
1942 << "generator program assumes that the interface between "
1943 << "two parts is a boundary when that isn't supposed to be "
1944 << "the case, or where the mesh generator simply assigns "
1945 << "'geometry indicators' to quads at the surface of "
1946 << "a part that are not supposed to be interpreted as "
1947 << "'boundary indicators'.");
1954 int,
1955 int,
1956 << "In SubCellData the line info of the line with vertex indices " << arg1
1957 << " and " << arg2 << " appears more than once. "
1958 << "This is not allowed.");
1965 int,
1966 int,
1967 std::string,
1968 << "In SubCellData the line info of the line with vertex indices " << arg1
1969 << " and " << arg2 << " appears multiple times with different (valid) "
1970 << arg3 << ". This is not allowed.");
1977 int,
1978 int,
1979 int,
1980 int,
1981 std::string,
1982 << "In SubCellData the quad info of the quad with line indices " << arg1
1983 << ", " << arg2 << ", " << arg3 << " and " << arg4
1984 << " appears multiple times with different (valid) " << arg5
1985 << ". This is not allowed.");
1986
1987 /*
1988 * Reserve space for TriaFaces. Details:
1989 *
1990 * Reserve space for line_orientations.
1991 *
1992 * @note Used only for dim=3.
1993 */
1994 void
1996 const unsigned int new_quads_in_pairs,
1997 const unsigned int new_quads_single)
1998 {
1999 AssertDimension(tria_faces.dim, 3);
2000
2001 Assert(new_quads_in_pairs % 2 == 0, ExcInternalError());
2002
2003 unsigned int next_free_single = 0;
2004 unsigned int next_free_pair = 0;
2005
2006 // count the number of objects, of unused single objects and of
2007 // unused pairs of objects
2008 unsigned int n_quads = 0;
2009 unsigned int n_unused_pairs = 0;
2010 unsigned int n_unused_singles = 0;
2011 for (unsigned int i = 0; i < tria_faces.quads.used.size(); ++i)
2012 {
2013 if (tria_faces.quads.used[i])
2014 ++n_quads;
2015 else if (i + 1 < tria_faces.quads.used.size())
2016 {
2017 if (tria_faces.quads.used[i + 1])
2018 {
2019 ++n_unused_singles;
2020 if (next_free_single == 0)
2021 next_free_single = i;
2022 }
2023 else
2024 {
2025 ++n_unused_pairs;
2026 if (next_free_pair == 0)
2027 next_free_pair = i;
2028 ++i;
2029 }
2030 }
2031 else
2032 ++n_unused_singles;
2033 }
2034 Assert(n_quads + 2 * n_unused_pairs + n_unused_singles ==
2035 tria_faces.quads.used.size(),
2037 (void)n_quads;
2038
2039 // how many single quads are needed in addition to n_unused_quads?
2040 const int additional_single_quads = new_quads_single - n_unused_singles;
2041
2042 unsigned int new_size =
2043 tria_faces.quads.used.size() + new_quads_in_pairs - 2 * n_unused_pairs;
2044 if (additional_single_quads > 0)
2045 new_size += additional_single_quads;
2046
2047 // see above...
2048 if (new_size > tria_faces.quads.n_objects())
2049 {
2050 // reserve the field of the derived class
2051 tria_faces.quads_line_orientations.resize(
2052 new_size * GeometryInfo<3>::lines_per_face, true);
2053
2054 auto &q_is_q = tria_faces.quad_is_quadrilateral;
2055 q_is_q.reserve(new_size);
2056 q_is_q.insert(q_is_q.end(), new_size - q_is_q.size(), true);
2057 }
2058 }
2059
2060
2061
2075 void
2077 const unsigned int total_cells,
2078 const unsigned int dimension,
2079 const unsigned int space_dimension,
2080 const bool tetraheder_in_mesh = false)
2081 {
2082 // we need space for total_cells cells. Maybe we have more already
2083 // with those cells which are unused, so only allocate new space if
2084 // needed.
2085 //
2086 // note that all arrays should have equal sizes (checked by
2087 // @p{monitor_memory}
2088 if (total_cells > tria_level.refine_flags.size())
2089 {
2090 tria_level.refine_flags.reserve(total_cells);
2091 tria_level.refine_flags.insert(tria_level.refine_flags.end(),
2092 total_cells -
2093 tria_level.refine_flags.size(),
2094 /*RefinementCase::no_refinement=*/0);
2095
2096 if (tetraheder_in_mesh)
2097 {
2098 tria_level.refine_choice.reserve(total_cells);
2099 tria_level.refine_choice.insert(
2100 tria_level.refine_choice.end(),
2101 total_cells - tria_level.refine_choice.size(),
2102 static_cast<char>(
2104 }
2105
2106 tria_level.coarsen_flags.reserve(total_cells);
2107 tria_level.coarsen_flags.insert(tria_level.coarsen_flags.end(),
2108 total_cells -
2109 tria_level.coarsen_flags.size(),
2110 false);
2111
2112 tria_level.active_cell_indices.reserve(total_cells);
2113 tria_level.active_cell_indices.insert(
2114 tria_level.active_cell_indices.end(),
2115 total_cells - tria_level.active_cell_indices.size(),
2117
2118 tria_level.subdomain_ids.reserve(total_cells);
2119 tria_level.subdomain_ids.insert(tria_level.subdomain_ids.end(),
2120 total_cells -
2121 tria_level.subdomain_ids.size(),
2122 0);
2123
2124 tria_level.level_subdomain_ids.reserve(total_cells);
2125 tria_level.level_subdomain_ids.insert(
2126 tria_level.level_subdomain_ids.end(),
2127 total_cells - tria_level.level_subdomain_ids.size(),
2128 0);
2129
2130 tria_level.global_active_cell_indices.reserve(total_cells);
2131 tria_level.global_active_cell_indices.insert(
2132 tria_level.global_active_cell_indices.end(),
2133 total_cells - tria_level.global_active_cell_indices.size(),
2135
2136 tria_level.global_level_cell_indices.reserve(total_cells);
2137 tria_level.global_level_cell_indices.insert(
2138 tria_level.global_level_cell_indices.end(),
2139 total_cells - tria_level.global_level_cell_indices.size(),
2141
2142 if (dimension == space_dimension - 1)
2143 {
2144 tria_level.direction_flags.reserve(total_cells);
2145 tria_level.direction_flags.insert(
2146 tria_level.direction_flags.end(),
2147 total_cells - tria_level.direction_flags.size(),
2148 true);
2149 }
2150 else
2151 tria_level.direction_flags.clear();
2152
2153 tria_level.parents.reserve((total_cells + 1) / 2);
2154 tria_level.parents.insert(tria_level.parents.end(),
2155 (total_cells + 1) / 2 -
2156 tria_level.parents.size(),
2157 -1);
2158
2159 tria_level.neighbors.reserve(total_cells * (2 * dimension));
2160 tria_level.neighbors.insert(tria_level.neighbors.end(),
2161 total_cells * (2 * dimension) -
2162 tria_level.neighbors.size(),
2163 std::make_pair(-1, -1));
2164
2165 if (tria_level.dim == 2 || tria_level.dim == 3)
2166 {
2167 const unsigned int max_faces_per_cell = 2 * dimension;
2168 tria_level.face_orientations.resize(total_cells *
2169 max_faces_per_cell);
2170
2171 tria_level.reference_cell.reserve(total_cells);
2172 tria_level.reference_cell.insert(
2173 tria_level.reference_cell.end(),
2174 total_cells - tria_level.reference_cell.size(),
2175 tria_level.dim == 2 ? ReferenceCells::Quadrilateral :
2177 }
2178 }
2179 }
2180
2181
2182
2187 int,
2188 int,
2189 << "The containers have sizes " << arg1 << " and " << arg2
2190 << ", which is not as expected.");
2191
2197 void
2198 monitor_memory(const TriaLevel &tria_level,
2199 const unsigned int true_dimension)
2200 {
2201 (void)tria_level;
2202 (void)true_dimension;
2203 Assert(2 * true_dimension * tria_level.refine_flags.size() ==
2204 tria_level.neighbors.size(),
2205 ExcMemoryInexact(tria_level.refine_flags.size(),
2206 tria_level.neighbors.size()));
2207 Assert(2 * true_dimension * tria_level.coarsen_flags.size() ==
2208 tria_level.neighbors.size(),
2209 ExcMemoryInexact(tria_level.coarsen_flags.size(),
2210 tria_level.neighbors.size()));
2211 }
2212
2213
2214
2227 void
2229 const unsigned int new_objects_in_pairs,
2230 const unsigned int new_objects_single = 0)
2231 {
2232 if (tria_objects.structdim <= 2)
2233 {
2234 Assert(new_objects_in_pairs % 2 == 0, ExcInternalError());
2235
2236 tria_objects.next_free_single = 0;
2237 tria_objects.next_free_pair = 0;
2238 tria_objects.reverse_order_next_free_single = false;
2239
2240 // count the number of objects, of unused single objects and of
2241 // unused pairs of objects
2242 unsigned int n_objects = 0;
2243 unsigned int n_unused_pairs = 0;
2244 unsigned int n_unused_singles = 0;
2245 for (unsigned int i = 0; i < tria_objects.used.size(); ++i)
2246 {
2247 if (tria_objects.used[i])
2248 ++n_objects;
2249 else if (i + 1 < tria_objects.used.size())
2250 {
2251 if (tria_objects.used[i + 1])
2252 {
2253 ++n_unused_singles;
2254 if (tria_objects.next_free_single == 0)
2255 tria_objects.next_free_single = i;
2256 }
2257 else
2258 {
2259 ++n_unused_pairs;
2260 if (tria_objects.next_free_pair == 0)
2261 tria_objects.next_free_pair = i;
2262 ++i;
2263 }
2264 }
2265 else
2266 ++n_unused_singles;
2267 }
2268 Assert(n_objects + 2 * n_unused_pairs + n_unused_singles ==
2269 tria_objects.used.size(),
2271 (void)n_objects;
2272
2273 // how many single objects are needed in addition to
2274 // n_unused_objects?
2275 const int additional_single_objects =
2276 new_objects_single - n_unused_singles;
2277
2278 unsigned int new_size = tria_objects.used.size() +
2279 new_objects_in_pairs - 2 * n_unused_pairs;
2280 if (additional_single_objects > 0)
2281 new_size += additional_single_objects;
2282
2283 // only allocate space if necessary
2284 if (new_size > tria_objects.n_objects())
2285 {
2286 const unsigned int max_faces_per_cell =
2287 2 * tria_objects.structdim;
2288 const unsigned int max_children_per_cell =
2289 1 << tria_objects.structdim;
2290
2291 tria_objects.cells.reserve(new_size * max_faces_per_cell);
2292 tria_objects.cells.insert(tria_objects.cells.end(),
2293 (new_size - tria_objects.n_objects()) *
2294 max_faces_per_cell,
2295 -1);
2296
2297 tria_objects.used.reserve(new_size);
2298 tria_objects.used.insert(tria_objects.used.end(),
2299 new_size - tria_objects.used.size(),
2300 false);
2301
2302 tria_objects.user_flags.reserve(new_size);
2303 tria_objects.user_flags.insert(tria_objects.user_flags.end(),
2304 new_size -
2305 tria_objects.user_flags.size(),
2306 false);
2307
2308 const unsigned int factor = max_children_per_cell / 2;
2309 tria_objects.children.reserve(factor * new_size);
2310 tria_objects.children.insert(tria_objects.children.end(),
2311 factor * new_size -
2312 tria_objects.children.size(),
2313 -1);
2314
2315 if (tria_objects.structdim > 1)
2316 {
2317 tria_objects.refinement_cases.reserve(new_size);
2318 tria_objects.refinement_cases.insert(
2319 tria_objects.refinement_cases.end(),
2320 new_size - tria_objects.refinement_cases.size(),
2321 /*RefinementCase::no_refinement=*/0);
2322 }
2323
2324 // first reserve, then resize. Otherwise the std library can
2325 // decide to allocate more entries.
2326 tria_objects.boundary_or_material_id.reserve(new_size);
2327 tria_objects.boundary_or_material_id.resize(new_size);
2328
2329 tria_objects.user_data.reserve(new_size);
2330 tria_objects.user_data.resize(new_size);
2331
2332 tria_objects.manifold_id.reserve(new_size);
2333 tria_objects.manifold_id.insert(tria_objects.manifold_id.end(),
2334 new_size -
2335 tria_objects.manifold_id.size(),
2337 }
2338
2339 if (n_unused_singles == 0)
2340 {
2341 tria_objects.next_free_single = new_size - 1;
2342 tria_objects.reverse_order_next_free_single = true;
2343 }
2344 }
2345 else
2346 {
2347 const unsigned int new_hexes = new_objects_in_pairs;
2348
2349 const unsigned int new_size =
2350 new_hexes + std::count(tria_objects.used.begin(),
2351 tria_objects.used.end(),
2352 true);
2353
2354 // see above...
2355 if (new_size > tria_objects.n_objects())
2356 {
2357 const unsigned int max_faces_per_cell =
2358 2 * tria_objects.structdim;
2359
2360 tria_objects.cells.reserve(new_size * max_faces_per_cell);
2361 tria_objects.cells.insert(tria_objects.cells.end(),
2362 (new_size - tria_objects.n_objects()) *
2363 max_faces_per_cell,
2364 -1);
2365
2366 tria_objects.used.reserve(new_size);
2367 tria_objects.used.insert(tria_objects.used.end(),
2368 new_size - tria_objects.used.size(),
2369 false);
2370
2371 tria_objects.user_flags.reserve(new_size);
2372 tria_objects.user_flags.insert(tria_objects.user_flags.end(),
2373 new_size -
2374 tria_objects.user_flags.size(),
2375 false);
2376
2377 tria_objects.children.reserve(4 * new_size);
2378 tria_objects.children.insert(tria_objects.children.end(),
2379 4 * new_size -
2380 tria_objects.children.size(),
2381 -1);
2382
2383 // for the following fields, we know exactly how many elements
2384 // we need, so first reserve then resize (resize itself, at least
2385 // with some compiler libraries, appears to round up the size it
2386 // actually reserves)
2387 tria_objects.boundary_or_material_id.reserve(new_size);
2388 tria_objects.boundary_or_material_id.resize(new_size);
2389
2390 tria_objects.manifold_id.reserve(new_size);
2391 tria_objects.manifold_id.insert(tria_objects.manifold_id.end(),
2392 new_size -
2393 tria_objects.manifold_id.size(),
2395
2396 tria_objects.user_data.reserve(new_size);
2397 tria_objects.user_data.resize(new_size);
2398
2399 tria_objects.refinement_cases.reserve(new_size);
2400 tria_objects.refinement_cases.insert(
2401 tria_objects.refinement_cases.end(),
2402 new_size - tria_objects.refinement_cases.size(),
2403 /*RefinementCase::no_refinement=*/0);
2404 }
2405 tria_objects.next_free_single = tria_objects.next_free_pair = 0;
2406 }
2407 }
2408
2409
2410
2416 void
2417 monitor_memory(const TriaObjects &tria_object, const unsigned int)
2418 {
2419 Assert(tria_object.n_objects() == tria_object.used.size(),
2420 ExcMemoryInexact(tria_object.n_objects(),
2421 tria_object.used.size()));
2422 Assert(tria_object.n_objects() == tria_object.user_flags.size(),
2423 ExcMemoryInexact(tria_object.n_objects(),
2424 tria_object.user_flags.size()));
2425 Assert(tria_object.n_objects() ==
2426 tria_object.boundary_or_material_id.size(),
2427 ExcMemoryInexact(tria_object.n_objects(),
2428 tria_object.boundary_or_material_id.size()));
2429 Assert(tria_object.n_objects() == tria_object.manifold_id.size(),
2430 ExcMemoryInexact(tria_object.n_objects(),
2431 tria_object.manifold_id.size()));
2432 Assert(tria_object.n_objects() == tria_object.user_data.size(),
2433 ExcMemoryInexact(tria_object.n_objects(),
2434 tria_object.user_data.size()));
2435
2436 if (tria_object.structdim == 1)
2437 {
2438 Assert(1 * tria_object.n_objects() == tria_object.children.size(),
2439 ExcMemoryInexact(tria_object.n_objects(),
2440 tria_object.children.size()));
2441 }
2442 else if (tria_object.structdim == 2)
2443 {
2444 Assert(2 * tria_object.n_objects() == tria_object.children.size(),
2445 ExcMemoryInexact(tria_object.n_objects(),
2446 tria_object.children.size()));
2447 }
2448 else if (tria_object.structdim == 3)
2449 {
2450 Assert(4 * tria_object.n_objects() == tria_object.children.size(),
2451 ExcMemoryInexact(tria_object.n_objects(),
2452 tria_object.children.size()));
2453 }
2454 }
2455
2456
2457
2462 template <int dim, int spacedim>
2464 {
2465 public:
2469 virtual ~Policy() = default;
2470
2474 virtual void
2476
2480 virtual void
2484 std::vector<unsigned int> &line_cell_count,
2485 std::vector<unsigned int> &quad_cell_count) = 0;
2486
2492 const bool check_for_distorted_cells) = 0;
2493
2497 virtual void
2500
2504 virtual void
2507
2511 virtual bool
2513 const typename Triangulation<dim, spacedim>::cell_iterator &cell) = 0;
2514
2521 virtual std::unique_ptr<Policy<dim, spacedim>>
2522 clone() = 0;
2523 };
2524
2525
2526
2532 template <int dim, int spacedim, typename T>
2533 class PolicyWrapper : public Policy<dim, spacedim>
2534 {
2535 public:
2536 void
2538 {
2539 T::update_neighbors(tria);
2540 }
2541
2542 void
2546 std::vector<unsigned int> &line_cell_count,
2547 std::vector<unsigned int> &quad_cell_count) override
2548 {
2549 T::delete_children(tria, cell, line_cell_count, quad_cell_count);
2550 }
2551
2554 const bool check_for_distorted_cells) override
2555 {
2556 return T::execute_refinement(triangulation, check_for_distorted_cells);
2557 }
2558
2559 void
2562 {
2563 T::prevent_distorted_boundary_cells(triangulation);
2564 }
2565
2566 void
2569 {
2570 T::prepare_refinement_dim_dependent(triangulation);
2571 }
2572
2573 bool
2576 override
2577 {
2578 return T::template coarsening_allowed<dim, spacedim>(cell);
2579 }
2580
2581 std::unique_ptr<Policy<dim, spacedim>>
2582 clone() override
2583 {
2584 return std::make_unique<PolicyWrapper<dim, spacedim, T>>();
2585 }
2586 };
2587
2588
2589
2686 {
2698 template <int dim, int spacedim>
2699 static void
2702 const unsigned int level_objects,
2704 {
2705 using line_iterator =
2707
2708 number_cache.n_levels = 0;
2709 if (level_objects > 0)
2710 // find the last level on which there are used cells
2711 for (unsigned int level = 0; level < level_objects; ++level)
2712 if (triangulation.begin(level) != triangulation.end(level))
2713 number_cache.n_levels = level + 1;
2714
2715 // no cells at all?
2716 Assert(number_cache.n_levels > 0, ExcInternalError());
2717
2718 //---------------------------------
2719 // update the number of lines on the different levels in the
2720 // cache
2721 number_cache.n_lines = 0;
2722 number_cache.n_active_lines = 0;
2723
2724 // for 1d, lines have levels so take count the objects per
2725 // level and globally
2726 if (dim == 1)
2727 {
2728 number_cache.n_lines_level.resize(number_cache.n_levels);
2729 number_cache.n_active_lines_level.resize(number_cache.n_levels);
2730
2731 for (unsigned int level = 0; level < number_cache.n_levels; ++level)
2732 {
2733 // count lines on this level
2734 number_cache.n_lines_level[level] = 0;
2735 number_cache.n_active_lines_level[level] = 0;
2736
2737 line_iterator line = triangulation.begin_line(level),
2738 endc =
2739 (level == number_cache.n_levels - 1 ?
2740 line_iterator(triangulation.end_line()) :
2741 triangulation.begin_line(level + 1));
2742 for (; line != endc; ++line)
2743 {
2744 ++number_cache.n_lines_level[level];
2745 if (line->has_children() == false)
2746 ++number_cache.n_active_lines_level[level];
2747 }
2748
2749 // update total number of lines
2750 number_cache.n_lines += number_cache.n_lines_level[level];
2751 number_cache.n_active_lines +=
2752 number_cache.n_active_lines_level[level];
2753 }
2754 }
2755 else
2756 {
2757 // for dim>1, there are no levels for lines
2758 number_cache.n_lines_level.clear();
2759 number_cache.n_active_lines_level.clear();
2760
2761 line_iterator line = triangulation.begin_line(),
2762 endc = triangulation.end_line();
2763 for (; line != endc; ++line)
2764 {
2765 ++number_cache.n_lines;
2766 if (line->has_children() == false)
2767 ++number_cache.n_active_lines;
2768 }
2769 }
2770 }
2771
2786 template <int dim, int spacedim>
2787 static void
2790 const unsigned int level_objects,
2792 {
2793 // update lines and n_levels in number_cache. since we don't
2794 // access any of these numbers, we can do this in the
2795 // background
2797 static_cast<
2798 void (*)(const Triangulation<dim, spacedim> &,
2799 const unsigned int,
2801 &compute_number_cache_dim<dim, spacedim>),
2803 level_objects,
2805 number_cache));
2806
2807 using quad_iterator =
2809
2810 //---------------------------------
2811 // update the number of quads on the different levels in the
2812 // cache
2813 number_cache.n_quads = 0;
2814 number_cache.n_active_quads = 0;
2815
2816 // for 2d, quads have levels so take count the objects per
2817 // level and globally
2818 if (dim == 2)
2819 {
2820 // count the number of levels; the function we called above
2821 // on a separate Task for lines also does this and puts it into
2822 // number_cache.n_levels, but this datum may not yet be
2823 // available as we call the function on a separate task
2824 unsigned int n_levels = 0;
2825 if (level_objects > 0)
2826 // find the last level on which there are used cells
2827 for (unsigned int level = 0; level < level_objects; ++level)
2828 if (triangulation.begin(level) != triangulation.end(level))
2829 n_levels = level + 1;
2830
2831 number_cache.n_quads_level.resize(n_levels);
2832 number_cache.n_active_quads_level.resize(n_levels);
2833
2834 for (unsigned int level = 0; level < n_levels; ++level)
2835 {
2836 // count quads on this level
2837 number_cache.n_quads_level[level] = 0;
2838 number_cache.n_active_quads_level[level] = 0;
2839
2840 quad_iterator quad = triangulation.begin_quad(level),
2841 endc =
2842 (level == n_levels - 1 ?
2843 quad_iterator(triangulation.end_quad()) :
2844 triangulation.begin_quad(level + 1));
2845 for (; quad != endc; ++quad)
2846 {
2847 ++number_cache.n_quads_level[level];
2848 if (quad->has_children() == false)
2849 ++number_cache.n_active_quads_level[level];
2850 }
2851
2852 // update total number of quads
2853 number_cache.n_quads += number_cache.n_quads_level[level];
2854 number_cache.n_active_quads +=
2855 number_cache.n_active_quads_level[level];
2856 }
2857 }
2858 else
2859 {
2860 // for dim>2, there are no levels for quads
2861 number_cache.n_quads_level.clear();
2862 number_cache.n_active_quads_level.clear();
2863
2864 quad_iterator quad = triangulation.begin_quad(),
2865 endc = triangulation.end_quad();
2866 for (; quad != endc; ++quad)
2867 {
2868 ++number_cache.n_quads;
2869 if (quad->has_children() == false)
2870 ++number_cache.n_active_quads;
2871 }
2872 }
2873
2874 // wait for the background computation for lines
2875 update_lines.join();
2876 }
2877
2893 template <int dim, int spacedim>
2894 static void
2897 const unsigned int level_objects,
2899 {
2900 // update quads, lines and n_levels in number_cache. since we
2901 // don't access any of these numbers, we can do this in the
2902 // background
2903 Threads::Task<void> update_quads_and_lines = Threads::new_task(
2904 static_cast<
2905 void (*)(const Triangulation<dim, spacedim> &,
2906 const unsigned int,
2908 &compute_number_cache_dim<dim, spacedim>),
2910 level_objects,
2912 number_cache));
2913
2914 using hex_iterator =
2916
2917 //---------------------------------
2918 // update the number of hexes on the different levels in the
2919 // cache
2920 number_cache.n_hexes = 0;
2921 number_cache.n_active_hexes = 0;
2922
2923 // for 3d, hexes have levels so take count the objects per
2924 // level and globally
2925 if (dim == 3)
2926 {
2927 // count the number of levels; the function we called
2928 // above on a separate Task for quads (recursively, via
2929 // the lines function) also does this and puts it into
2930 // number_cache.n_levels, but this datum may not yet be
2931 // available as we call the function on a separate task
2932 unsigned int n_levels = 0;
2933 if (level_objects > 0)
2934 // find the last level on which there are used cells
2935 for (unsigned int level = 0; level < level_objects; ++level)
2936 if (triangulation.begin(level) != triangulation.end(level))
2937 n_levels = level + 1;
2938
2939 number_cache.n_hexes_level.resize(n_levels);
2940 number_cache.n_active_hexes_level.resize(n_levels);
2941
2942 for (unsigned int level = 0; level < n_levels; ++level)
2943 {
2944 // count hexes on this level
2945 number_cache.n_hexes_level[level] = 0;
2946 number_cache.n_active_hexes_level[level] = 0;
2947
2948 hex_iterator hex = triangulation.begin_hex(level),
2949 endc = (level == n_levels - 1 ?
2950 hex_iterator(triangulation.end_hex()) :
2951 triangulation.begin_hex(level + 1));
2952 for (; hex != endc; ++hex)
2953 {
2954 ++number_cache.n_hexes_level[level];
2955 if (hex->has_children() == false)
2956 ++number_cache.n_active_hexes_level[level];
2957 }
2958
2959 // update total number of hexes
2960 number_cache.n_hexes += number_cache.n_hexes_level[level];
2961 number_cache.n_active_hexes +=
2962 number_cache.n_active_hexes_level[level];
2963 }
2964 }
2965 else
2966 {
2967 // for dim>3, there are no levels for hexes
2968 number_cache.n_hexes_level.clear();
2969 number_cache.n_active_hexes_level.clear();
2970
2971 hex_iterator hex = triangulation.begin_hex(),
2972 endc = triangulation.end_hex();
2973 for (; hex != endc; ++hex)
2974 {
2975 ++number_cache.n_hexes;
2976 if (hex->has_children() == false)
2977 ++number_cache.n_active_hexes;
2978 }
2979 }
2980
2981 // wait for the background computation for quads
2982 update_quads_and_lines.join();
2983 }
2984
2985
2986 template <int dim, int spacedim>
2987 static void
2990 const unsigned int level_objects,
2992 {
2993 compute_number_cache_dim(triangulation, level_objects, number_cache);
2994
2995 number_cache.active_cell_index_partitioner =
2996 std::make_shared<const Utilities::MPI::Partitioner>(
2997 triangulation.n_active_cells());
2998
2999 number_cache.level_cell_index_partitioners.resize(
3000 triangulation.n_levels());
3001 for (unsigned int level = 0; level < triangulation.n_levels(); ++level)
3002 number_cache.level_cell_index_partitioners[level] =
3003 std::make_shared<const Utilities::MPI::Partitioner>(
3004 triangulation.n_cells(level));
3005 }
3006
3007
3008 template <int spacedim>
3009 static void
3012
3013
3014 template <int dim, int spacedim>
3015 static void
3017 {
3018 // each face can be neighbored on two sides
3019 // by cells. according to the face's
3020 // intrinsic normal we define the left
3021 // neighbor as the one for which the face
3022 // normal points outward, and store that
3023 // one first; the second one is then
3024 // the right neighbor for which the
3025 // face normal points inward. This
3026 // information depends on the type of cell
3027 // and local number of face for the
3028 // 'standard ordering and orientation' of
3029 // faces and then on the face_orientation
3030 // information for the real mesh. Set up a
3031 // table to have fast access to those
3032 // offsets (0 for left and 1 for
3033 // right). Some of the values are invalid
3034 // as they reference too large face
3035 // numbers, but we just leave them at a
3036 // zero value.
3037 //
3038 // Note, that in 2d for lines as faces the
3039 // normal direction given in the
3040 // GeometryInfo class is not consistent. We
3041 // thus define here that the normal for a
3042 // line points to the right if the line
3043 // points upwards.
3044 //
3045 // There is one more point to
3046 // consider, however: if we have
3047 // dim<spacedim, then we may have
3048 // cases where cells are
3049 // inverted. In effect, both
3050 // cells think they are the left
3051 // neighbor of an edge, for
3052 // example, which leads us to
3053 // forget neighborship
3054 // information (a case that shows
3055 // this is
3056 // codim_one/hanging_nodes_02). We
3057 // store whether a cell is
3058 // inverted using the
3059 // direction_flag, so if a cell
3060 // has a false direction_flag,
3061 // then we need to invert our
3062 // selection whether we are a
3063 // left or right neighbor in all
3064 // following computations.
3065 //
3066 // first index: dimension (minus 2)
3067 // second index: local face index
3068 // third index: face_orientation (false and true)
3069 static const unsigned int left_right_offset[2][6][2] = {
3070 // quadrilateral
3071 {{0, 1}, // face 0, face_orientation = false and true
3072 {1, 0}, // face 1, face_orientation = false and true
3073 {1, 0}, // face 2, face_orientation = false and true
3074 {0, 1}, // face 3, face_orientation = false and true
3075 {0, 0}, // face 4, invalid face
3076 {0, 0}}, // face 5, invalid face
3077 // hexahedron
3078 {{0, 1}, {1, 0}, {0, 1}, {1, 0}, {0, 1}, {1, 0}}};
3079
3080 // now create a vector of the two active
3081 // neighbors (left and right) for each face
3082 // and fill it by looping over all cells. For
3083 // cases with anisotropic refinement and more
3084 // then one cell neighboring at a given side
3085 // of the face we will automatically get the
3086 // active one on the highest level as we loop
3087 // over cells from lower levels first.
3089 std::vector<typename Triangulation<dim, spacedim>::cell_iterator>
3090 adjacent_cells(2 * triangulation.n_raw_faces(), dummy);
3091
3092 for (const auto &cell : triangulation.cell_iterators())
3093 for (auto f : cell->face_indices())
3094 {
3096 cell->face(f);
3097
3098 const unsigned int offset =
3099 (cell->direction_flag() ?
3100 left_right_offset[dim - 2][f][cell->face_orientation(f)] :
3101 1 -
3102 left_right_offset[dim - 2][f][cell->face_orientation(f)]);
3103
3104 adjacent_cells[2 * face->index() + offset] = cell;
3105
3106 // if this cell is not refined, but the
3107 // face is, then we'll have to set our
3108 // cell as neighbor for the child faces
3109 // as well. Fortunately the normal
3110 // orientation of children will be just
3111 // the same.
3112 if (dim == 2)
3113 {
3114 if (cell->is_active() && face->has_children())
3115 {
3116 adjacent_cells[2 * face->child(0)->index() + offset] =
3117 cell;
3118 adjacent_cells[2 * face->child(1)->index() + offset] =
3119 cell;
3120 }
3121 }
3122 else // -> dim == 3
3123 {
3124 // We need the same as in 2d
3125 // here. Furthermore, if the face is
3126 // refined with cut_x or cut_y then
3127 // those children again in the other
3128 // direction, and if this cell is
3129 // refined isotropically (along the
3130 // face) then the neighbor will
3131 // (probably) be refined as cut_x or
3132 // cut_y along the face. For those
3133 // neighboring children cells, their
3134 // neighbor will be the current,
3135 // inactive cell, as our children are
3136 // too fine to be neighbors. Catch that
3137 // case by also acting on inactive
3138 // cells with isotropic refinement
3139 // along the face. If the situation
3140 // described is not present, the data
3141 // will be overwritten later on when we
3142 // visit cells on finer levels, so no
3143 // harm will be done.
3144 if (face->has_children() &&
3145 (cell->is_active() ||
3147 cell->refinement_case(), f) ==
3149 {
3150 for (unsigned int c = 0; c < face->n_children(); ++c)
3151 adjacent_cells[2 * face->child(c)->index() + offset] =
3152 cell;
3153 if (face->child(0)->has_children())
3154 {
3155 adjacent_cells[2 * face->child(0)->child(0)->index() +
3156 offset] = cell;
3157 adjacent_cells[2 * face->child(0)->child(1)->index() +
3158 offset] = cell;
3159 }
3160 if (face->child(1)->has_children())
3161 {
3162 adjacent_cells[2 * face->child(1)->child(0)->index() +
3163 offset] = cell;
3164 adjacent_cells[2 * face->child(1)->child(1)->index() +
3165 offset] = cell;
3166 }
3167 } // if cell active and face refined
3168 } // else -> dim==3
3169 } // for all faces of all cells
3170
3171 // now loop again over all cells and set the
3172 // corresponding neighbor cell. Note, that we
3173 // have to use the opposite of the
3174 // left_right_offset in this case as we want
3175 // the offset of the neighbor, not our own.
3176 for (const auto &cell : triangulation.cell_iterators())
3177 for (auto f : cell->face_indices())
3178 {
3179 const unsigned int offset =
3180 (cell->direction_flag() ?
3181 left_right_offset[dim - 2][f][cell->face_orientation(f)] :
3182 1 -
3183 left_right_offset[dim - 2][f][cell->face_orientation(f)]);
3184 cell->set_neighbor(
3185 f, adjacent_cells[2 * cell->face(f)->index() + 1 - offset]);
3186 }
3187 }
3188
3189
3193 template <int dim, int spacedim>
3194 static void
3196 const std::vector<CellData<dim>> &cells,
3197 const SubCellData &subcelldata,
3199 {
3200 AssertThrow(vertices.size() > 0, ExcMessage("No vertices given"));
3201 AssertThrow(cells.size() > 0, ExcMessage("No cells given"));
3202
3203 // Check that all cells have positive volume.
3204#ifndef _MSC_VER
3205 // TODO: The following code does not compile with MSVC. Find a way
3206 // around it
3207 if (dim == spacedim)
3208 for (unsigned int cell_no = 0; cell_no < cells.size(); ++cell_no)
3209 {
3210 // If we should check for distorted cells, then we permit them
3211 // to exist. If a cell has negative measure, then it must be
3212 // distorted (the converse is not necessarily true); hence
3213 // throw an exception if no such cells should exist.
3215 {
3216 const double cell_measure = GridTools::cell_measure<spacedim>(
3217 vertices,
3218 ArrayView<const unsigned int>(cells[cell_no].vertices));
3219 AssertThrow(cell_measure > 0, ExcGridHasInvalidCell(cell_no));
3220 }
3221 }
3222#endif
3223
3224 // clear old content
3225 tria.levels.clear();
3226 tria.levels.push_back(
3227 std::make_unique<
3229
3230 if (dim > 1)
3231 tria.faces = std::make_unique<
3233
3234 // copy vertices
3235 tria.vertices = vertices;
3236 tria.vertices_used.assign(vertices.size(), true);
3237
3238 // compute connectivity
3239 const auto connectivity = build_connectivity<unsigned int>(cells);
3240 const unsigned int n_cell = cells.size();
3241
3242 // TriaObjects: lines
3243 if (dim >= 2)
3244 {
3245 auto &lines_0 = tria.faces->lines; // data structure to be filled
3246
3247 // get connectivity between quads and lines
3248 const auto &crs = connectivity.entity_to_entities(1, 0);
3249 const unsigned int n_lines = crs.ptr.size() - 1;
3250
3251 // allocate memory
3252 reserve_space_(lines_0, n_lines);
3253
3254 // loop over lines
3255 for (unsigned int line = 0; line < n_lines; ++line)
3256 for (unsigned int i = crs.ptr[line], j = 0; i < crs.ptr[line + 1];
3257 ++i, ++j)
3258 lines_0.cells[line * GeometryInfo<1>::faces_per_cell + j] =
3259 crs.col[i]; // set vertex indices
3260 }
3261
3262 // TriaObjects: quads
3263 if (dim == 3)
3264 {
3265 auto &quads_0 = tria.faces->quads; // data structures to be filled
3266 auto &faces = *tria.faces;
3267
3268 // get connectivity between quads and lines
3269 const auto &crs = connectivity.entity_to_entities(2, 1);
3270 const unsigned int n_quads = crs.ptr.size() - 1;
3271
3272 // allocate memory
3273 reserve_space_(quads_0, n_quads);
3274 reserve_space_(faces, 2 /*structdim*/, n_quads);
3275
3276 // loop over all quads -> entity type, line indices/orientations
3277 for (unsigned int q = 0, k = 0; q < n_quads; ++q)
3278 {
3279 // set entity type of quads
3280 faces.set_quad_type(q, connectivity.entity_types(2)[q]);
3281
3282 // loop over all its lines
3283 for (unsigned int i = crs.ptr[q], j = 0; i < crs.ptr[q + 1];
3284 ++i, ++j, ++k)
3285 {
3286 // set line index
3287 quads_0.cells[q * GeometryInfo<3>::lines_per_face + j] =
3288 crs.col[i];
3289
3290 // set line orientations
3291 const unsigned char combined_orientation =
3292 connectivity.entity_orientations(1)
3293 .get_combined_orientation(k);
3294 // it doesn't make sense to set any flags except
3295 // orientation for a line
3296 Assert(
3297 combined_orientation ==
3299 combined_orientation ==
3302 faces.quads_line_orientations
3304 combined_orientation ==
3306 }
3307 }
3308 }
3309
3310 // TriaObjects/TriaLevel: cell
3311 {
3312 auto &cells_0 = tria.levels[0]->cells; // data structure to be filled
3313 auto &level = *tria.levels[0];
3314
3315 // get connectivity between cells/faces and cells/cells
3316 const auto &crs = connectivity.entity_to_entities(dim, dim - 1);
3317 const auto &nei = connectivity.entity_to_entities(dim, dim);
3318
3319 // in 2d optional: since in in pure QUAD meshes same line
3320 // orientations can be guaranteed
3321 bool orientation_needed = false;
3322 if (dim == 3)
3323 orientation_needed = true;
3324 else if (dim == 2)
3325 {
3326 const auto &orientations = connectivity.entity_orientations(1);
3327 for (unsigned int i = 0; i < orientations.n_objects(); ++i)
3328 if (orientations.get_combined_orientation(i) !=
3330 {
3331 orientation_needed = true;
3332 break;
3333 }
3334 }
3335
3336 // allocate memory
3337 reserve_space_(cells_0, n_cell);
3338 reserve_space_(level, spacedim, n_cell, orientation_needed);
3339
3340 // loop over all cells
3341 for (unsigned int cell = 0; cell < n_cell; ++cell)
3342 {
3343 // set material ids
3344 cells_0.boundary_or_material_id[cell].material_id =
3345 cells[cell].material_id;
3346
3347 // set manifold ids
3348 cells_0.manifold_id[cell] = cells[cell].manifold_id;
3349
3350 // set entity types
3351 level.reference_cell[cell] = connectivity.entity_types(dim)[cell];
3352
3353 // loop over faces
3354 for (unsigned int i = crs.ptr[cell], j = 0; i < crs.ptr[cell + 1];
3355 ++i, ++j)
3356 {
3357 // set neighbor if not at boundary
3358 if (nei.col[i] != static_cast<unsigned int>(-1))
3359 level.neighbors[cell * GeometryInfo<dim>::faces_per_cell +
3360 j] = {0, nei.col[i]};
3361
3362 // set face indices
3363 cells_0.cells[cell * GeometryInfo<dim>::faces_per_cell + j] =
3364 crs.col[i];
3365
3366 // set face orientation if needed
3367 if (orientation_needed)
3368 {
3369 level.face_orientations.set_combined_orientation(
3371 connectivity.entity_orientations(dim - 1)
3372 .get_combined_orientation(i));
3373 }
3374 }
3375 }
3376 }
3377
3378 // TriaFaces: boundary id of boundary faces
3379 if (dim > 1)
3380 {
3381 auto &bids_face = dim == 3 ?
3382 tria.faces->quads.boundary_or_material_id :
3383 tria.faces->lines.boundary_or_material_id;
3384
3385 // count number of cells a face is belonging to
3386 std::vector<unsigned int> count(bids_face.size(), 0);
3387
3388 // get connectivity between cells/faces
3389 const auto &crs = connectivity.entity_to_entities(dim, dim - 1);
3390
3391 // count how many cells are adjacent to the same face
3392 for (unsigned int cell = 0; cell < cells.size(); ++cell)
3393 for (unsigned int i = crs.ptr[cell]; i < crs.ptr[cell + 1]; ++i)
3394 count[crs.col[i]]++;
3395
3396 // loop over all faces
3397 for (unsigned int face = 0; face < count.size(); ++face)
3398 {
3399 if (count[face] != 1) // inner face
3400 continue;
3401
3402 // boundary faces ...
3403 bids_face[face].boundary_id = 0;
3404
3405 if (dim != 3)
3406 continue;
3407
3408 // ... and the lines of quads in 3d
3409 const auto &crs = connectivity.entity_to_entities(2, 1);
3410 for (unsigned int i = crs.ptr[face]; i < crs.ptr[face + 1]; ++i)
3411 tria.faces->lines.boundary_or_material_id[crs.col[i]]
3412 .boundary_id = 0;
3413 }
3414 }
3415 else // 1d
3416 {
3417 static const unsigned int t_tba = static_cast<unsigned int>(-1);
3418 static const unsigned int t_inner = static_cast<unsigned int>(-2);
3419
3420 std::vector<unsigned int> type(vertices.size(), t_tba);
3421
3422 const auto &crs = connectivity.entity_to_entities(1, 0);
3423
3424 for (unsigned int cell = 0; cell < cells.size(); ++cell)
3425 for (unsigned int i = crs.ptr[cell], j = 0; i < crs.ptr[cell + 1];
3426 ++i, ++j)
3427 if (type[crs.col[i]] != t_inner)
3428 type[crs.col[i]] = type[crs.col[i]] == t_tba ? j : t_inner;
3429
3430 for (unsigned int face = 0; face < type.size(); ++face)
3431 {
3432 // note: we also treat manifolds here!?
3433 (*tria.vertex_to_manifold_id_map_1d)[face] =
3435 if (type[face] != t_inner && type[face] != t_tba)
3436 (*tria.vertex_to_boundary_id_map_1d)[face] = type[face];
3437 }
3438 }
3439
3440 // SubCellData: line
3441 if (dim >= 2)
3442 process_subcelldata(connectivity.entity_to_entities(1, 0),
3443 tria.faces->lines,
3444 subcelldata.boundary_lines,
3445 vertices);
3446
3447 // SubCellData: quad
3448 if (dim == 3)
3449 process_subcelldata(connectivity.entity_to_entities(2, 0),
3450 tria.faces->quads,
3451 subcelldata.boundary_quads,
3452 vertices);
3453 }
3454
3455
3456 template <int structdim, int spacedim, typename T>
3457 static void
3459 const CRS<T> &crs,
3460 TriaObjects &obj,
3461 const std::vector<CellData<structdim>> &boundary_objects_in,
3462 const std::vector<Point<spacedim>> &vertex_locations)
3463 {
3464 AssertDimension(obj.structdim, structdim);
3465
3466 if (boundary_objects_in.empty())
3467 return; // empty subcelldata -> nothing to do
3468
3469 // pre-sort subcelldata
3470 auto boundary_objects = boundary_objects_in;
3471
3472 // ... sort vertices
3473 for (auto &boundary_object : boundary_objects)
3474 std::sort(boundary_object.vertices.begin(),
3475 boundary_object.vertices.end());
3476
3477 // ... sort cells
3478 std::sort(boundary_objects.begin(),
3479 boundary_objects.end(),
3480 [](const auto &a, const auto &b) {
3481 return a.vertices < b.vertices;
3482 });
3483
3484 unsigned int counter = 0;
3485
3486 std::vector<unsigned int> key;
3488
3489 for (unsigned int o = 0; o < obj.n_objects(); ++o)
3490 {
3491 auto &boundary_id = obj.boundary_or_material_id[o].boundary_id;
3492 auto &manifold_id = obj.manifold_id[o];
3493
3494 // assert that object has not been visited yet and its value
3495 // has not been modified yet
3496 AssertThrow(boundary_id == 0 ||
3501
3502 // create key
3503 key.assign(crs.col.data() + crs.ptr[o],
3504 crs.col.data() + crs.ptr[o + 1]);
3505 std::sort(key.begin(), key.end());
3506
3507 // is subcelldata provided? -> binary search
3508 const auto subcell_object =
3509 std::lower_bound(boundary_objects.begin(),
3510 boundary_objects.end(),
3511 key,
3512 [&](const auto &cell, const auto &key) {
3513 return cell.vertices < key;
3514 });
3515
3516 // no subcelldata provided for this object
3517 if (subcell_object == boundary_objects.end() ||
3518 subcell_object->vertices != key)
3519 continue;
3520
3521 ++counter;
3522
3523 // set manifold id
3524 manifold_id = subcell_object->manifold_id;
3525
3526 // set boundary id
3527 if (subcell_object->boundary_id !=
3529 {
3530 (void)vertex_locations;
3533 ExcMessage(
3534 "The input arguments for creating a triangulation "
3535 "specified a boundary id for an internal face. This "
3536 "is not allowed."
3537 "\n\n"
3538 "The object in question has vertex indices " +
3539 [subcell_object]() {
3540 std::string s;
3541 for (const auto v : subcell_object->vertices)
3542 s += std::to_string(v) + ',';
3543 return s;
3544 }() +
3545 " which are located at positions " +
3546 [vertex_locations, subcell_object]() {
3547 std::ostringstream s;
3548 for (const auto v : subcell_object->vertices)
3549 s << '(' << vertex_locations[v] << ')';
3550 return s.str();
3551 }() +
3552 "."));
3553 boundary_id = subcell_object->boundary_id;
3554 }
3555 }
3556
3557 // make sure that all subcelldata entries have been processed
3558 // TODO: this is not guaranteed, why?
3559 // AssertDimension(counter, boundary_objects_in.size());
3560 (void)counter;
3561 }
3562
3563
3564
3565 static void
3567 const unsigned structdim,
3568 const unsigned int size)
3569 {
3570 const unsigned int dim = faces.dim;
3571
3572 const unsigned int max_lines_per_face = 2 * structdim;
3573
3574 if (dim == 3 && structdim == 2)
3575 {
3576 // quad entity types
3577 faces.quad_is_quadrilateral.assign(size, true);
3578
3579 // quad line orientations
3580 faces.quads_line_orientations.assign(size * max_lines_per_face,
3581 true);
3582 }
3583 }
3584
3585
3586
3587 static void
3589 const unsigned int spacedim,
3590 const unsigned int size,
3591 const bool orientation_needed)
3592 {
3593 const unsigned int dim = level.dim;
3594
3595 const unsigned int max_faces_per_cell = 2 * dim;
3596
3597 level.active_cell_indices.assign(size, numbers::invalid_unsigned_int);
3598 level.subdomain_ids.assign(size, 0);
3599 level.level_subdomain_ids.assign(size, 0);
3600
3601 level.refine_flags.assign(size, 0u);
3602 level.refine_choice.assign(size, 0u);
3603 level.coarsen_flags.assign(size, false);
3604
3605 level.parents.assign((size + 1) / 2, -1);
3606
3607 if (dim == spacedim - 1)
3608 level.direction_flags.assign(size, true);
3609
3610 level.neighbors.assign(size * max_faces_per_cell, {-1, -1});
3611
3612 level.reference_cell.assign(size, ReferenceCells::Invalid);
3613
3614 if (orientation_needed)
3615 level.face_orientations.reinit(size * max_faces_per_cell);
3616
3617
3618 level.global_active_cell_indices.assign(size,
3620 level.global_level_cell_indices.assign(size,
3622 }
3623
3624
3625
3626 static void
3627 reserve_space_(TriaObjects &obj, const unsigned int size)
3628 {
3629 const unsigned int structdim = obj.structdim;
3630
3631 const unsigned int max_children_per_cell = 1 << structdim;
3632 const unsigned int max_faces_per_cell = 2 * structdim;
3633
3634 obj.used.assign(size, true);
3635 obj.boundary_or_material_id.assign(
3636 size,
3638 BoundaryOrMaterialId());
3639 obj.manifold_id.assign(size, -1);
3640 obj.user_flags.assign(size, false);
3641 obj.user_data.resize(size);
3642
3643 if (structdim > 1) // TODO: why?
3644 obj.refinement_cases.assign(size, 0);
3645
3646 obj.children.assign(max_children_per_cell / 2 * size, -1);
3647
3648 obj.cells.assign(max_faces_per_cell * size, -1);
3649
3650 if (structdim <= 2)
3651 {
3652 obj.next_free_single = size - 1;
3653 obj.next_free_pair = 0;
3655 }
3656 else
3657 {
3658 obj.next_free_single = obj.next_free_pair = 0;
3659 }
3660 }
3661
3662
3678 template <int spacedim>
3679 static void
3682 std::vector<unsigned int> &,
3683 std::vector<unsigned int> &)
3684 {
3685 const unsigned int dim = 1;
3686
3687 // first we need to reset the
3688 // neighbor pointers of the
3689 // neighbors of this cell's
3690 // children to this cell. This is
3691 // different for one dimension,
3692 // since there neighbors can have a
3693 // refinement level differing from
3694 // that of this cell's children by
3695 // more than one level.
3696
3697 Assert(!cell->child(0)->has_children() &&
3698 !cell->child(1)->has_children(),
3700
3701 // first do it for the cells to the
3702 // left
3703 if (cell->neighbor(0).state() == IteratorState::valid)
3704 if (cell->neighbor(0)->has_children())
3705 {
3707 cell->neighbor(0);
3708 Assert(neighbor->level() == cell->level(), ExcInternalError());
3709
3710 // right child
3711 neighbor = neighbor->child(1);
3712 while (true)
3713 {
3714 Assert(neighbor->neighbor(1) == cell->child(0),
3716 neighbor->set_neighbor(1, cell);
3717
3718 // move on to further
3719 // children on the
3720 // boundary between this
3721 // cell and its neighbor
3722 if (neighbor->has_children())
3723 neighbor = neighbor->child(1);
3724 else
3725 break;
3726 }
3727 }
3728
3729 // now do it for the cells to the
3730 // left
3731 if (cell->neighbor(1).state() == IteratorState::valid)
3732 if (cell->neighbor(1)->has_children())
3733 {
3735 cell->neighbor(1);
3736 Assert(neighbor->level() == cell->level(), ExcInternalError());
3737
3738 // left child
3739 neighbor = neighbor->child(0);
3740 while (true)
3741 {
3742 Assert(neighbor->neighbor(0) == cell->child(1),
3744 neighbor->set_neighbor(0, cell);
3745
3746 // move on to further
3747 // children on the
3748 // boundary between this
3749 // cell and its neighbor
3750 if (neighbor->has_children())
3751 neighbor = neighbor->child(0);
3752 else
3753 break;
3754 }
3755 }
3756
3757
3758 // delete the vertex which will not
3759 // be needed anymore. This vertex
3760 // is the second of the first child
3761 triangulation.vertices_used[cell->child(0)->vertex_index(1)] = false;
3762
3763 // invalidate children. clear user
3764 // pointers, to avoid that they may
3765 // appear at unwanted places later
3766 // on...
3767 for (unsigned int child = 0; child < cell->n_children(); ++child)
3768 {
3769 cell->child(child)->clear_user_data();
3770 cell->child(child)->clear_user_flag();
3771 cell->child(child)->clear_used_flag();
3772 }
3773
3774
3775 // delete pointer to children
3776 cell->clear_children();
3777 cell->clear_user_flag();
3778 }
3779
3780
3781
3782 template <int spacedim>
3783 static void
3786 std::vector<unsigned int> &line_cell_count,
3787 std::vector<unsigned int> &)
3788 {
3789 const unsigned int dim = 2;
3790 const RefinementCase<dim> ref_case = cell->refinement_case();
3791
3792 Assert(line_cell_count.size() == triangulation.n_raw_lines(),
3794
3795 // vectors to hold all lines which
3796 // may be deleted
3797 std::vector<typename Triangulation<dim, spacedim>::line_iterator>
3798 lines_to_delete(0);
3799
3800 lines_to_delete.reserve(4 * 2 + 4);
3801
3802 // now we decrease the counters for
3803 // lines contained in the child
3804 // cells
3805 for (unsigned int c = 0; c < cell->n_children(); ++c)
3806 {
3808 cell->child(c);
3809 for (unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++l)
3810 --line_cell_count[child->line_index(l)];
3811 }
3812
3813
3814 // delete the vertex which will not
3815 // be needed anymore. This vertex
3816 // is the second of the second line
3817 // of the first child, if the cell
3818 // is refined with cut_xy, else there
3819 // is no inner vertex.
3820 // additionally delete unneeded inner
3821 // lines
3822 if (ref_case == RefinementCase<dim>::cut_xy)
3823 {
3825 .vertices_used[cell->child(0)->line(1)->vertex_index(1)] = false;
3826
3827 lines_to_delete.push_back(cell->child(0)->line(1));
3828 lines_to_delete.push_back(cell->child(0)->line(3));
3829 lines_to_delete.push_back(cell->child(3)->line(0));
3830 lines_to_delete.push_back(cell->child(3)->line(2));
3831 }
3832 else
3833 {
3834 unsigned int inner_face_no =
3835 ref_case == RefinementCase<dim>::cut_x ? 1 : 3;
3836
3837 // the inner line will not be
3838 // used any more
3839 lines_to_delete.push_back(cell->child(0)->line(inner_face_no));
3840 }
3841
3842 // invalidate children
3843 for (unsigned int child = 0; child < cell->n_children(); ++child)
3844 {
3845 cell->child(child)->clear_user_data();
3846 cell->child(child)->clear_user_flag();
3847 cell->child(child)->clear_used_flag();
3848 }
3849
3850
3851 // delete pointer to children
3852 cell->clear_children();
3853 cell->clear_refinement_case();
3854 cell->clear_user_flag();
3855
3856 // look at the refinement of outer
3857 // lines. if nobody needs those
3858 // anymore we can add them to the
3859 // list of lines to be deleted.
3860 for (unsigned int line_no = 0;
3861 line_no < GeometryInfo<dim>::lines_per_cell;
3862 ++line_no)
3863 {
3865 cell->line(line_no);
3866
3867 if (line->has_children())
3868 {
3869 // if one of the cell counters is
3870 // zero, the other has to be as well
3871
3872 Assert((line_cell_count[line->child_index(0)] == 0 &&
3873 line_cell_count[line->child_index(1)] == 0) ||
3874 (line_cell_count[line->child_index(0)] > 0 &&
3875 line_cell_count[line->child_index(1)] > 0),
3877
3878 if (line_cell_count[line->child_index(0)] == 0)
3879 {
3880 for (unsigned int c = 0; c < 2; ++c)
3881 Assert(!line->child(c)->has_children(),
3883
3884 // we may delete the line's
3885 // children and the middle vertex
3886 // as no cell references them
3887 // anymore
3889 .vertices_used[line->child(0)->vertex_index(1)] = false;
3890
3891 lines_to_delete.push_back(line->child(0));
3892 lines_to_delete.push_back(line->child(1));
3893
3894 line->clear_children();
3895 }
3896 }
3897 }
3898
3899 // finally, delete unneeded lines
3900
3901 // clear user pointers, to avoid that
3902 // they may appear at unwanted places
3903 // later on...
3904 // same for user flags, then finally
3905 // delete the lines
3906 typename std::vector<
3908 line = lines_to_delete.begin(),
3909 endline = lines_to_delete.end();
3910 for (; line != endline; ++line)
3911 {
3912 (*line)->clear_user_data();
3913 (*line)->clear_user_flag();
3914 (*line)->clear_used_flag();
3915 }
3916 }
3917
3918
3919
3920 template <int spacedim>
3921 static void
3924 std::vector<unsigned int> &line_cell_count,
3925 std::vector<unsigned int> &quad_cell_count)
3926 {
3927 const unsigned int dim = 3;
3928
3929 Assert(line_cell_count.size() == triangulation.n_raw_lines(),
3931 Assert(quad_cell_count.size() == triangulation.n_raw_quads(),
3933
3934 // first of all, we store the RefineCase of
3935 // this cell
3936 const RefinementCase<dim> ref_case = cell->refinement_case();
3937 // vectors to hold all lines and quads which
3938 // may be deleted
3939 std::vector<typename Triangulation<dim, spacedim>::line_iterator>
3940 lines_to_delete(0);
3941 std::vector<typename Triangulation<dim, spacedim>::quad_iterator>
3942 quads_to_delete(0);
3943
3944 lines_to_delete.reserve(12 * 2 + 6 * 4 + 6);
3945 quads_to_delete.reserve(6 * 4 + 12);
3946
3947 // now we decrease the counters for lines and
3948 // quads contained in the child cells
3949 for (unsigned int c = 0; c < cell->n_children(); ++c)
3950 {
3952 cell->child(c);
3953 const auto line_indices = TriaAccessorImplementation::
3954 Implementation::get_line_indices_of_cell(*child);
3955 for (const unsigned int l : cell->line_indices())
3956 --line_cell_count[line_indices[l]];
3957 for (auto f : GeometryInfo<dim>::face_indices())
3958 --quad_cell_count[child->quad_index(f)];
3959 }
3960
3961 //-------------------------------------
3962 // delete interior quads and lines and the
3963 // interior vertex, depending on the
3964 // refinement case of the cell
3965 //
3966 // for append quads and lines: only append
3967 // them to the list of objects to be deleted
3968
3969 switch (ref_case)
3970 {
3972 quads_to_delete.push_back(cell->child(0)->face(1));
3973 break;
3975 quads_to_delete.push_back(cell->child(0)->face(3));
3976 break;
3978 quads_to_delete.push_back(cell->child(0)->face(5));
3979 break;
3981 quads_to_delete.push_back(cell->child(0)->face(1));
3982 quads_to_delete.push_back(cell->child(0)->face(3));
3983 quads_to_delete.push_back(cell->child(3)->face(0));
3984 quads_to_delete.push_back(cell->child(3)->face(2));
3985
3986 lines_to_delete.push_back(cell->child(0)->line(11));
3987 break;
3989 quads_to_delete.push_back(cell->child(0)->face(1));
3990 quads_to_delete.push_back(cell->child(0)->face(5));
3991 quads_to_delete.push_back(cell->child(3)->face(0));
3992 quads_to_delete.push_back(cell->child(3)->face(4));
3993
3994 lines_to_delete.push_back(cell->child(0)->line(5));
3995 break;
3997 quads_to_delete.push_back(cell->child(0)->face(3));
3998 quads_to_delete.push_back(cell->child(0)->face(5));
3999 quads_to_delete.push_back(cell->child(3)->face(2));
4000 quads_to_delete.push_back(cell->child(3)->face(4));
4001
4002 lines_to_delete.push_back(cell->child(0)->line(7));
4003 break;
4005 quads_to_delete.push_back(cell->child(0)->face(1));
4006 quads_to_delete.push_back(cell->child(2)->face(1));
4007 quads_to_delete.push_back(cell->child(4)->face(1));
4008 quads_to_delete.push_back(cell->child(6)->face(1));
4009
4010 quads_to_delete.push_back(cell->child(0)->face(3));
4011 quads_to_delete.push_back(cell->child(1)->face(3));
4012 quads_to_delete.push_back(cell->child(4)->face(3));
4013 quads_to_delete.push_back(cell->child(5)->face(3));
4014
4015 quads_to_delete.push_back(cell->child(0)->face(5));
4016 quads_to_delete.push_back(cell->child(1)->face(5));
4017 quads_to_delete.push_back(cell->child(2)->face(5));
4018 quads_to_delete.push_back(cell->child(3)->face(5));
4019
4020 lines_to_delete.push_back(cell->child(0)->line(5));
4021 lines_to_delete.push_back(cell->child(0)->line(7));
4022 lines_to_delete.push_back(cell->child(0)->line(11));
4023 lines_to_delete.push_back(cell->child(7)->line(0));
4024 lines_to_delete.push_back(cell->child(7)->line(2));
4025 lines_to_delete.push_back(cell->child(7)->line(8));
4026 // delete the vertex which will not
4027 // be needed anymore. This vertex
4028 // is the vertex at the heart of
4029 // this cell, which is the sixth of
4030 // the first child
4031 triangulation.vertices_used[cell->child(0)->vertex_index(7)] =
4032 false;
4033 break;
4034 default:
4035 // only remaining case is
4036 // no_refinement, thus an error
4038 break;
4039 }
4040
4041
4042 // invalidate children
4043 for (unsigned int child = 0; child < cell->n_children(); ++child)
4044 {
4045 cell->child(child)->clear_user_data();
4046 cell->child(child)->clear_user_flag();
4047
4048 for (auto f : GeometryInfo<dim>::face_indices())
4049 // set flags denoting deviations from standard orientation of
4050 // faces back to initialization values
4051 cell->child(child)->set_combined_face_orientation(
4053
4054 cell->child(child)->clear_used_flag();
4055 }
4056
4057
4058 // delete pointer to children
4059 cell->clear_children();
4060 cell->clear_refinement_case();
4061 cell->clear_user_flag();
4062
4063 // so far we only looked at inner quads,
4064 // lines and vertices. Now we have to
4065 // consider outer ones as well. here, we have
4066 // to check, whether there are other cells
4067 // still needing these objects. otherwise we
4068 // can delete them. first for quads (and
4069 // their inner lines).
4070
4071 for (const unsigned int quad_no : GeometryInfo<dim>::face_indices())
4072 {
4074 cell->face(quad_no);
4075
4076 Assert(
4077 (GeometryInfo<dim>::face_refinement_case(ref_case, quad_no) &&
4078 quad->has_children()) ||
4079 GeometryInfo<dim>::face_refinement_case(ref_case, quad_no) ==
4082
4083 switch (quad->refinement_case())
4084 {
4085 case RefinementCase<dim - 1>::no_refinement:
4086 // nothing to do as the quad
4087 // is not refined
4088 break;
4089 case RefinementCase<dim - 1>::cut_x:
4090 case RefinementCase<dim - 1>::cut_y:
4091 {
4092 // if one of the cell counters is
4093 // zero, the other has to be as
4094 // well
4095 Assert((quad_cell_count[quad->child_index(0)] == 0 &&
4096 quad_cell_count[quad->child_index(1)] == 0) ||
4097 (quad_cell_count[quad->child_index(0)] > 0 &&
4098 quad_cell_count[quad->child_index(1)] > 0),
4100 // it might be, that the quad is
4101 // refined twice anisotropically,
4102 // first check, whether we may
4103 // delete possible grand_children
4104 unsigned int deleted_grandchildren = 0;
4105 unsigned int number_of_child_refinements = 0;
4106
4107 for (unsigned int c = 0; c < 2; ++c)
4108 if (quad->child(c)->has_children())
4109 {
4110 ++number_of_child_refinements;
4111 // if one of the cell counters is
4112 // zero, the other has to be as
4113 // well
4114 Assert(
4115 (quad_cell_count[quad->child(c)->child_index(0)] ==
4116 0 &&
4117 quad_cell_count[quad->child(c)->child_index(1)] ==
4118 0) ||
4119 (quad_cell_count[quad->child(c)->child_index(0)] >
4120 0 &&
4121 quad_cell_count[quad->child(c)->child_index(1)] >
4122 0),
4124 if (quad_cell_count[quad->child(c)->child_index(0)] ==
4125 0)
4126 {
4127 // Assert, that the two
4128 // anisotropic
4129 // refinements add up to
4130 // isotropic refinement
4131 Assert(quad->refinement_case() +
4132 quad->child(c)->refinement_case() ==
4135 // we may delete the
4136 // quad's children and
4137 // the inner line as no
4138 // cell references them
4139 // anymore
4140 quads_to_delete.push_back(
4141 quad->child(c)->child(0));
4142 quads_to_delete.push_back(
4143 quad->child(c)->child(1));
4144 if (quad->child(c)->refinement_case() ==
4146 lines_to_delete.push_back(
4147 quad->child(c)->child(0)->line(1));
4148 else
4149 lines_to_delete.push_back(
4150 quad->child(c)->child(0)->line(3));
4151 quad->child(c)->clear_children();
4152 quad->child(c)->clear_refinement_case();
4153 ++deleted_grandchildren;
4154 }
4155 }
4156 // if no grandchildren are left, we
4157 // may as well delete the
4158 // refinement of the inner line
4159 // between our children and the
4160 // corresponding vertex
4161 if (number_of_child_refinements > 0 &&
4162 deleted_grandchildren == number_of_child_refinements)
4163 {
4165 middle_line;
4166 if (quad->refinement_case() == RefinementCase<2>::cut_x)
4167 middle_line = quad->child(0)->line(1);
4168 else
4169 middle_line = quad->child(0)->line(3);
4170
4171 lines_to_delete.push_back(middle_line->child(0));
4172 lines_to_delete.push_back(middle_line->child(1));
4174 .vertices_used[middle_vertex_index<dim, spacedim>(
4175 middle_line)] = false;
4176 middle_line->clear_children();
4177 }
4178
4179 // now consider the direct children
4180 // of the given quad
4181 if (quad_cell_count[quad->child_index(0)] == 0)
4182 {
4183 // we may delete the quad's
4184 // children and the inner line
4185 // as no cell references them
4186 // anymore
4187 quads_to_delete.push_back(quad->child(0));
4188 quads_to_delete.push_back(quad->child(1));
4189 if (quad->refinement_case() == RefinementCase<2>::cut_x)
4190 lines_to_delete.push_back(quad->child(0)->line(1));
4191 else
4192 lines_to_delete.push_back(quad->child(0)->line(3));
4193
4194 // if the counters just dropped
4195 // to zero, otherwise the
4196 // children would have been
4197 // deleted earlier, then this
4198 // cell's children must have
4199 // contained the anisotropic
4200 // quad children. thus, if
4201 // those have again anisotropic
4202 // children, which are in
4203 // effect isotropic children of
4204 // the original quad, those are
4205 // still needed by a
4206 // neighboring cell and we
4207 // cannot delete them. instead,
4208 // we have to reset this quad's
4209 // refine case to isotropic and
4210 // set the children
4211 // accordingly.
4212 if (quad->child(0)->has_children())
4213 if (quad->refinement_case() ==
4215 {
4216 // now evereything is
4217 // quite complicated. we
4218 // have the children
4219 // numbered according to
4220 //
4221 // *---*---*
4222 // |n+1|m+1|
4223 // *---*---*
4224 // | n | m |
4225 // *---*---*
4226 //
4227 // from the original
4228 // anisotropic
4229 // refinement. we have to
4230 // reorder them as
4231 //
4232 // *---*---*
4233 // | m |m+1|
4234 // *---*---*
4235 // | n |n+1|
4236 // *---*---*
4237 //
4238 // for isotropic refinement.
4239 //
4240 // this is a bit ugly, of
4241 // course: loop over all
4242 // cells on all levels
4243 // and look for faces n+1
4244 // (switch_1) and m
4245 // (switch_2).
4246 const typename Triangulation<dim, spacedim>::
4247 quad_iterator switch_1 =
4248 quad->child(0)->child(1),
4249 switch_2 =
4250 quad->child(1)->child(0);
4251
4252 Assert(!switch_1->has_children(),
4254 Assert(!switch_2->has_children(),
4256
4257 const int switch_1_index = switch_1->index();
4258 const int switch_2_index = switch_2->index();
4259 for (unsigned int l = 0;
4260 l < triangulation.levels.size();
4261 ++l)
4262 for (unsigned int h = 0;
4263 h <
4264 triangulation.levels[l]->cells.n_objects();
4265 ++h)
4266 for (const unsigned int q :
4268 {
4269 const int index =
4271 ->cells.get_bounding_object_indices(
4272 h)[q];
4273 if (index == switch_1_index)
4274 triangulation.levels[l]
4275 ->cells.get_bounding_object_indices(
4276 h)[q] = switch_2_index;
4277 else if (index == switch_2_index)
4278 triangulation.levels[l]
4279 ->cells.get_bounding_object_indices(
4280 h)[q] = switch_1_index;
4281 }
4282 // now we have to copy
4283 // all information of the
4284 // two quads
4285 const int switch_1_lines[4] = {
4286 static_cast<signed int>(
4287 switch_1->line_index(0)),
4288 static_cast<signed int>(
4289 switch_1->line_index(1)),
4290 static_cast<signed int>(
4291 switch_1->line_index(2)),
4292 static_cast<signed int>(
4293 switch_1->line_index(3))};
4294 const bool switch_1_line_orientations[4] = {
4295 switch_1->line_orientation(0),
4296 switch_1->line_orientation(1),
4297 switch_1->line_orientation(2),
4298 switch_1->line_orientation(3)};
4299 const types::boundary_id switch_1_boundary_id =
4300 switch_1->boundary_id();
4301 const unsigned int switch_1_user_index =
4302 switch_1->user_index();
4303 const bool switch_1_user_flag =
4304 switch_1->user_flag_set();
4305
4306 switch_1->set_bounding_object_indices(
4307 {switch_2->line_index(0),
4308 switch_2->line_index(1),
4309 switch_2->line_index(2),
4310 switch_2->line_index(3)});
4311 switch_1->set_line_orientation(
4312 0, switch_2->line_orientation(0));
4313 switch_1->set_line_orientation(
4314 1, switch_2->line_orientation(1));
4315 switch_1->set_line_orientation(
4316 2, switch_2->line_orientation(2));
4317 switch_1->set_line_orientation(
4318 3, switch_2->line_orientation(3));
4319 switch_1->set_boundary_id_internal(
4320 switch_2->boundary_id());
4321 switch_1->set_manifold_id(
4322 switch_2->manifold_id());
4323 switch_1->set_user_index(switch_2->user_index());
4324 if (switch_2->user_flag_set())
4325 switch_1->set_user_flag();
4326 else
4327 switch_1->clear_user_flag();
4328
4329 switch_2->set_bounding_object_indices(
4330 {switch_1_lines[0],
4331 switch_1_lines[1],
4332 switch_1_lines[2],
4333 switch_1_lines[3]});
4334 switch_2->set_line_orientation(
4335 0, switch_1_line_orientations[0]);
4336 switch_2->set_line_orientation(
4337 1, switch_1_line_orientations[1]);
4338 switch_2->set_line_orientation(
4339 2, switch_1_line_orientations[2]);
4340 switch_2->set_line_orientation(
4341 3, switch_1_line_orientations[3]);
4342 switch_2->set_boundary_id_internal(
4343 switch_1_boundary_id);
4344 switch_2->set_manifold_id(
4345 switch_1->manifold_id());
4346 switch_2->set_user_index(switch_1_user_index);
4347 if (switch_1_user_flag)
4348 switch_2->set_user_flag();
4349 else
4350 switch_2->clear_user_flag();
4351
4352 const unsigned int child_0 =
4353 quad->child(0)->child_index(0);
4354 const unsigned int child_2 =
4355 quad->child(1)->child_index(0);
4356 quad->clear_children();
4357 quad->clear_refinement_case();
4358 quad->set_refinement_case(
4360 quad->set_children(0, child_0);
4361 quad->set_children(2, child_2);
4362 std::swap(quad_cell_count[child_0 + 1],
4363 quad_cell_count[child_2]);
4364 }
4365 else
4366 {
4367 // the face was refined
4368 // with cut_y, thus the
4369 // children are already
4370 // in correct order. we
4371 // only have to set them
4372 // correctly, deleting
4373 // the indirection of two
4374 // anisotropic refinement
4375 // and going directly
4376 // from the quad to
4377 // isotropic children
4378 const unsigned int child_0 =
4379 quad->child(0)->child_index(0);
4380 const unsigned int child_2 =
4381 quad->child(1)->child_index(0);
4382 quad->clear_children();
4383 quad->clear_refinement_case();
4384 quad->set_refinement_case(
4386 quad->set_children(0, child_0);
4387 quad->set_children(2, child_2);
4388 }
4389 else
4390 {
4391 quad->clear_children();
4392 quad->clear_refinement_case();
4393 }
4394 }
4395 break;
4396 }
4397 case RefinementCase<dim - 1>::cut_xy:
4398 {
4399 // if one of the cell counters is
4400 // zero, the others have to be as
4401 // well
4402
4403 Assert((quad_cell_count[quad->child_index(0)] == 0 &&
4404 quad_cell_count[quad->child_index(1)] == 0 &&
4405 quad_cell_count[quad->child_index(2)] == 0 &&
4406 quad_cell_count[quad->child_index(3)] == 0) ||
4407 (quad_cell_count[quad->child_index(0)] > 0 &&
4408 quad_cell_count[quad->child_index(1)] > 0 &&
4409 quad_cell_count[quad->child_index(2)] > 0 &&
4410 quad_cell_count[quad->child_index(3)] > 0),
4412
4413 if (quad_cell_count[quad->child_index(0)] == 0)
4414 {
4415 // we may delete the quad's
4416 // children, the inner lines
4417 // and the middle vertex as no
4418 // cell references them anymore
4419 lines_to_delete.push_back(quad->child(0)->line(1));
4420 lines_to_delete.push_back(quad->child(3)->line(0));
4421 lines_to_delete.push_back(quad->child(0)->line(3));
4422 lines_to_delete.push_back(quad->child(3)->line(2));
4423
4424 for (unsigned int child = 0; child < quad->n_children();
4425 ++child)
4426 quads_to_delete.push_back(quad->child(child));
4427
4429 .vertices_used[quad->child(0)->vertex_index(3)] =
4430 false;
4431
4432 quad->clear_children();
4433 quad->clear_refinement_case();
4434 }
4435 }
4436 break;
4437
4438 default:
4440 break;
4441 }
4442 }
4443
4444 // now we repeat a similar procedure
4445 // for the outer lines of this cell.
4446
4447 // if in debug mode: check that each
4448 // of the lines for which we consider
4449 // deleting the children in fact has
4450 // children (the bits/coarsening_3d
4451 // test tripped over this initially)
4452 for (unsigned int line_no = 0;
4453 line_no < GeometryInfo<dim>::lines_per_cell;
4454 ++line_no)
4455 {
4457 cell->line(line_no);
4458
4459 Assert(
4460 (GeometryInfo<dim>::line_refinement_case(ref_case, line_no) &&
4461 line->has_children()) ||
4462 GeometryInfo<dim>::line_refinement_case(ref_case, line_no) ==
4465
4466 if (line->has_children())
4467 {
4468 // if one of the cell counters is
4469 // zero, the other has to be as well
4470
4471 Assert((line_cell_count[line->child_index(0)] == 0 &&
4472 line_cell_count[line->child_index(1)] == 0) ||
4473 (line_cell_count[line->child_index(0)] > 0 &&
4474 line_cell_count[line->child_index(1)] > 0),
4476
4477 if (line_cell_count[line->child_index(0)] == 0)
4478 {
4479 for (unsigned int c = 0; c < 2; ++c)
4480 Assert(!line->child(c)->has_children(),
4482
4483 // we may delete the line's
4484 // children and the middle vertex
4485 // as no cell references them
4486 // anymore
4488 .vertices_used[line->child(0)->vertex_index(1)] = false;
4489
4490 lines_to_delete.push_back(line->child(0));
4491 lines_to_delete.push_back(line->child(1));
4492
4493 line->clear_children();
4494 }
4495 }
4496 }
4497
4498 // finally, delete unneeded quads and lines
4499
4500 // clear user pointers, to avoid that
4501 // they may appear at unwanted places
4502 // later on...
4503 // same for user flags, then finally
4504 // delete the quads and lines
4505 typename std::vector<
4507 line = lines_to_delete.begin(),
4508 endline = lines_to_delete.end();
4509 for (; line != endline; ++line)
4510 {
4511 (*line)->clear_user_data();
4512 (*line)->clear_user_flag();
4513 (*line)->clear_used_flag();
4514 }
4515
4516 typename std::vector<
4518 quad = quads_to_delete.begin(),
4519 endquad = quads_to_delete.end();
4520 for (; quad != endquad; ++quad)
4521 {
4522 (*quad)->clear_user_data();
4523 (*quad)->clear_children();
4524 (*quad)->clear_refinement_case();
4525 (*quad)->clear_user_flag();
4526 (*quad)->clear_used_flag();
4527 }
4528 }
4529
4530
4548 template <int spacedim>
4549 static void
4552 unsigned int &next_unused_vertex,
4554 &next_unused_line,
4556 &next_unused_cell,
4557 const typename Triangulation<2, spacedim>::cell_iterator &cell)
4558 {
4559 const unsigned int dim = 2;
4560 // clear refinement flag
4561 const RefinementCase<dim> ref_case = cell->refine_flag_set();
4562 cell->clear_refine_flag();
4563
4564 /* For the refinement process: since we go the levels up from the
4565 lowest, there are (unlike above) only two possibilities: a neighbor
4566 cell is on the same level or one level up (in both cases, it may or
4567 may not be refined later on, but we don't care here).
4568
4569 First:
4570 Set up an array of the 3x3 vertices, which are distributed on the
4571 cell (the array consists of indices into the @p{vertices} std::vector
4572
4573 2--7--3
4574 | | |
4575 4--8--5
4576 | | |
4577 0--6--1
4578
4579 note: in case of cut_x or cut_y not all these vertices are needed for
4580 the new cells
4581
4582 Second:
4583 Set up an array of the new lines (the array consists of iterator
4584 pointers into the lines arrays)
4585
4586 .-6-.-7-. The directions are: .->-.->-.
4587 1 9 3 ^ ^ ^
4588 .-10.11-. .->-.->-.
4589 0 8 2 ^ ^ ^
4590 .-4-.-5-. .->-.->-.
4591
4592 cut_x:
4593 .-4-.-5-.
4594 | | |
4595 0 6 1
4596 | | |
4597 .-2-.-3-.
4598
4599 cut_y:
4600 .---5---.
4601 1 3
4602 .---6---.
4603 0 2
4604 .---4---.
4605
4606
4607 Third:
4608 Set up an array of neighbors:
4609
4610 6 7
4611 .--.--.
4612 1| | |3
4613 .--.--.
4614 0| | |2
4615 .--.--.
4616 4 5
4617
4618 We need this array for two reasons: first to get the lines which will
4619 bound the four subcells (if the neighboring cell is refined, these
4620 lines already exist), and second to update neighborship information.
4621 Since if a neighbor is not refined, its neighborship record only
4622 points to the present, unrefined, cell rather than the children we
4623 are presently creating, we only need the neighborship information
4624 if the neighbor cells are refined. In all other cases, we store
4625 the unrefined neighbor address
4626
4627 We also need for every neighbor (if refined) which number among its
4628 neighbors the present (unrefined) cell has, since that number is to
4629 be replaced and because that also is the number of the subline which
4630 will be the interface between that neighbor and the to be created
4631 cell. We will store this number (between 0 and 3) in the field
4632 @p{neighbors_neighbor}.
4633
4634 It would be sufficient to use the children of the common line to the
4635 neighbor, if we only wanted to get the new sublines and the new
4636 vertex, but because we need to update the neighborship information of
4637 the two refined subcells of the neighbor, we need to search these
4638 anyway.
4639
4640 Convention:
4641 The created children are numbered like this:
4642
4643 .--.--.
4644 |2 . 3|
4645 .--.--.
4646 |0 | 1|
4647 .--.--.
4648 */
4649 // collect the indices of the eight surrounding vertices
4650 // 2--7--3
4651 // | | |
4652 // 4--8--5
4653 // | | |
4654 // 0--6--1
4655 int new_vertices[9];
4656 for (unsigned int vertex_no = 0; vertex_no < 4; ++vertex_no)
4657 new_vertices[vertex_no] = cell->vertex_index(vertex_no);
4658 for (unsigned int line_no = 0; line_no < 4; ++line_no)
4659 if (cell->line(line_no)->has_children())
4660 new_vertices[4 + line_no] =
4661 cell->line(line_no)->child(0)->vertex_index(1);
4662
4663 if (ref_case == RefinementCase<dim>::cut_xy)
4664 {
4665 // find the next
4666 // unused vertex and
4667 // allocate it for
4668 // the new vertex we
4669 // need here
4670 while (triangulation.vertices_used[next_unused_vertex] == true)
4671 ++next_unused_vertex;
4672 Assert(next_unused_vertex < triangulation.vertices.size(),
4673 ExcMessage(
4674 "Internal error: During refinement, the triangulation "
4675 "wants to access an element of the 'vertices' array "
4676 "but it turns out that the array is not large enough."));
4677 triangulation.vertices_used[next_unused_vertex] = true;
4678
4679 new_vertices[8] = next_unused_vertex;
4680
4681 // determine middle vertex by transfinite interpolation to be
4682 // consistent with what happens to quads in a
4683 // Triangulation<3,3> when they are refined
4684 triangulation.vertices[next_unused_vertex] =
4685 cell->center(true, true);
4686 }
4687
4688
4689 // Now the lines:
4691 unsigned int lmin = 8;
4692 unsigned int lmax = 12;
4693 if (ref_case != RefinementCase<dim>::cut_xy)
4694 {
4695 lmin = 6;
4696 lmax = 7;
4697 }
4698
4699 for (unsigned int l = lmin; l < lmax; ++l)
4700 {
4701 while (next_unused_line->used() == true)
4702 ++next_unused_line;
4703 new_lines[l] = next_unused_line;
4704 ++next_unused_line;
4705
4706 AssertIsNotUsed(new_lines[l]);
4707 }
4708
4709 if (ref_case == RefinementCase<dim>::cut_xy)
4710 {
4711 // .-6-.-7-.
4712 // 1 9 3
4713 // .-10.11-.
4714 // 0 8 2
4715 // .-4-.-5-.
4716
4717 // lines 0-7 already exist, create only the four interior
4718 // lines 8-11
4719 unsigned int l = 0;
4720 for (const unsigned int face_no : GeometryInfo<dim>::face_indices())
4721 for (unsigned int c = 0; c < 2; ++c, ++l)
4722 new_lines[l] = cell->line(face_no)->child(c);
4723 Assert(l == 8, ExcInternalError());
4724
4725 new_lines[8]->set_bounding_object_indices(
4726 {new_vertices[6], new_vertices[8]});
4727 new_lines[9]->set_bounding_object_indices(
4728 {new_vertices[8], new_vertices[7]});
4729 new_lines[10]->set_bounding_object_indices(
4730 {new_vertices[4], new_vertices[8]});
4731 new_lines[11]->set_bounding_object_indices(
4732 {new_vertices[8], new_vertices[5]});
4733 }
4734 else if (ref_case == RefinementCase<dim>::cut_x)
4735 {
4736 // .-4-.-5-.
4737 // | | |
4738 // 0 6 1
4739 // | | |
4740 // .-2-.-3-.
4741 new_lines[0] = cell->line(0);
4742 new_lines[1] = cell->line(1);
4743 new_lines[2] = cell->line(2)->child(0);
4744 new_lines[3] = cell->line(2)->child(1);
4745 new_lines[4] = cell->line(3)->child(0);
4746 new_lines[5] = cell->line(3)->child(1);
4747 new_lines[6]->set_bounding_object_indices(
4748 {new_vertices[6], new_vertices[7]});
4749 }
4750 else
4751 {
4753 // .---5---.
4754 // 1 3
4755 // .---6---.
4756 // 0 2
4757 // .---4---.
4758 new_lines[0] = cell->line(0)->child(0);
4759 new_lines[1] = cell->line(0)->child(1);
4760 new_lines[2] = cell->line(1)->child(0);
4761 new_lines[3] = cell->line(1)->child(1);
4762 new_lines[4] = cell->line(2);
4763 new_lines[5] = cell->line(3);
4764 new_lines[6]->set_bounding_object_indices(
4765 {new_vertices[4], new_vertices[5]});
4766 }
4767
4768 for (unsigned int l = lmin; l < lmax; ++l)
4769 {
4770 new_lines[l]->set_used_flag();
4771 new_lines[l]->clear_user_flag();
4772 new_lines[l]->clear_user_data();
4773 new_lines[l]->clear_children();
4774 // interior line
4775 new_lines[l]->set_boundary_id_internal(
4777 new_lines[l]->set_manifold_id(cell->manifold_id());
4778 }
4779
4780 // Now add the four (two)
4781 // new cells!
4784 while (next_unused_cell->used() == true)
4785 ++next_unused_cell;
4786
4787 const unsigned int n_children = GeometryInfo<dim>::n_children(ref_case);
4788 for (unsigned int i = 0; i < n_children; ++i)
4789 {
4790 AssertIsNotUsed(next_unused_cell);
4791 subcells[i] = next_unused_cell;
4792 ++next_unused_cell;
4793 if (i % 2 == 1 && i < n_children - 1)
4794 while (next_unused_cell->used() == true)
4795 ++next_unused_cell;
4796 }
4797
4798 if (ref_case == RefinementCase<dim>::cut_xy)
4799 {
4800 // children:
4801 // .--.--.
4802 // |2 . 3|
4803 // .--.--.
4804 // |0 | 1|
4805 // .--.--.
4806 // lines:
4807 // .-6-.-7-.
4808 // 1 9 3
4809 // .-10.11-.
4810 // 0 8 2
4811 // .-4-.-5-.
4812 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
4813 new_lines[8]->index(),
4814 new_lines[4]->index(),
4815 new_lines[10]->index()});
4816 subcells[1]->set_bounding_object_indices({new_lines[8]->index(),
4817 new_lines[2]->index(),
4818 new_lines[5]->index(),
4819 new_lines[11]->index()});
4820 subcells[2]->set_bounding_object_indices({new_lines[1]->index(),
4821 new_lines[9]->index(),
4822 new_lines[10]->index(),
4823 new_lines[6]->index()});
4824 subcells[3]->set_bounding_object_indices({new_lines[9]->index(),
4825 new_lines[3]->index(),
4826 new_lines[11]->index(),
4827 new_lines[7]->index()});
4828 }
4829 else if (ref_case == RefinementCase<dim>::cut_x)
4830 {
4831 // children:
4832 // .--.--.
4833 // | . |
4834 // .0 . 1.
4835 // | | |
4836 // .--.--.
4837 // lines:
4838 // .-4-.-5-.
4839 // | | |
4840 // 0 6 1
4841 // | | |
4842 // .-2-.-3-.
4843 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
4844 new_lines[6]->index(),
4845 new_lines[2]->index(),
4846 new_lines[4]->index()});
4847 subcells[1]->set_bounding_object_indices({new_lines[6]->index(),
4848 new_lines[1]->index(),
4849 new_lines[3]->index(),
4850 new_lines[5]->index()});
4851 }
4852 else
4853 {
4855 // children:
4856 // .-----.
4857 // | 1 |
4858 // .-----.
4859 // | 0 |
4860 // .-----.
4861 // lines:
4862 // .---5---.
4863 // 1 3
4864 // .---6---.
4865 // 0 2
4866 // .---4---.
4867 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
4868 new_lines[2]->index(),
4869 new_lines[4]->index(),
4870 new_lines[6]->index()});
4871 subcells[1]->set_bounding_object_indices({new_lines[1]->index(),
4872 new_lines[3]->index(),
4873 new_lines[6]->index(),
4874 new_lines[5]->index()});
4875 }
4876
4877 types::subdomain_id subdomainid = cell->subdomain_id();
4878
4879 for (unsigned int i = 0; i < n_children; ++i)
4880 {
4881 subcells[i]->set_used_flag();
4882 subcells[i]->clear_refine_flag();
4883 subcells[i]->clear_user_flag();
4884 subcells[i]->clear_user_data();
4885 subcells[i]->clear_children();
4886 // inherit material properties
4887 subcells[i]->set_material_id(cell->material_id());
4888 subcells[i]->set_manifold_id(cell->manifold_id());
4889 subcells[i]->set_subdomain_id(subdomainid);
4890
4891 if (i % 2 == 0)
4892 subcells[i]->set_parent(cell->index());
4893 }
4894
4895
4896
4897 // set child index for even children i=0,2 (0)
4898 for (unsigned int i = 0; i < n_children / 2; ++i)
4899 cell->set_children(2 * i, subcells[2 * i]->index());
4900 // set the refine case
4901 cell->set_refinement_case(ref_case);
4902
4903 // note that the
4904 // refinement flag was
4905 // already cleared at the
4906 // beginning of this function
4907
4908 if (dim == spacedim - 1)
4909 for (unsigned int c = 0; c < n_children; ++c)
4910 cell->child(c)->set_direction_flag(cell->direction_flag());
4911 }
4912
4913
4914
4915 template <int dim, int spacedim>
4918 const bool check_for_distorted_cells)
4919 {
4920 AssertDimension(dim, 2);
4921
4922 // Check whether a new level is needed. We have to check for
4923 // this on the highest level only
4924 for (const auto &cell : triangulation.active_cell_iterators_on_level(
4925 triangulation.levels.size() - 1))
4926 if (cell->refine_flag_set())
4927 {
4928 triangulation.levels.push_back(
4929 std::make_unique<
4931 break;
4932 }
4933
4936 line != triangulation.end_line();
4937 ++line)
4938 {
4939 line->clear_user_flag();
4940 line->clear_user_data();
4941 }
4942
4943 unsigned int n_single_lines = 0;
4944 unsigned int n_lines_in_pairs = 0;
4945 unsigned int needed_vertices = 0;
4946
4947 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
4948 {
4949 // count number of flagged cells on this level and compute
4950 // how many new vertices and new lines will be needed
4951 unsigned int needed_cells = 0;
4952
4953 for (const auto &cell :
4954 triangulation.active_cell_iterators_on_level(level))
4955 if (cell->refine_flag_set())
4956 {
4957 if (cell->reference_cell() == ReferenceCells::Triangle)
4958 {
4959 needed_cells += 4;
4960 needed_vertices += 0;
4961 n_single_lines += 3;
4962 }
4963 else if (cell->reference_cell() ==
4965 {
4966 needed_cells += 4;
4967 needed_vertices += 1;
4968 n_single_lines += 4;
4969 }
4970 else
4971 {
4973 }
4974
4975 for (const auto line_no : cell->face_indices())
4976 {
4977 auto line = cell->line(line_no);
4978 if (line->has_children() == false)
4979 line->set_user_flag();
4980 }
4981 }
4982
4983
4984 const unsigned int used_cells =
4985 std::count(triangulation.levels[level + 1]->cells.used.begin(),
4986 triangulation.levels[level + 1]->cells.used.end(),
4987 true);
4988
4989
4990 reserve_space(*triangulation.levels[level + 1],
4991 used_cells + needed_cells,
4992 2,
4993 spacedim);
4994
4995 reserve_space(triangulation.levels[level + 1]->cells,
4996 needed_cells,
4997 0);
4998 }
4999
5000 for (auto line = triangulation.begin_line();
5001 line != triangulation.end_line();
5002 ++line)
5003 if (line->user_flag_set())
5004 {
5005 Assert(line->has_children() == false, ExcInternalError());
5006 n_lines_in_pairs += 2;
5007 needed_vertices += 1;
5008 }
5009
5010 reserve_space(triangulation.faces->lines, n_lines_in_pairs, 0);
5011
5012 needed_vertices += std::count(triangulation.vertices_used.begin(),
5013 triangulation.vertices_used.end(),
5014 true);
5015
5016 if (needed_vertices > triangulation.vertices.size())
5017 {
5018 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
5019 triangulation.vertices_used.resize(needed_vertices, false);
5020 }
5021
5022 unsigned int next_unused_vertex = 0;
5023
5024 {
5027 endl = triangulation.end_line();
5029 next_unused_line = triangulation.begin_raw_line();
5030
5031 for (; line != endl; ++line)
5032 if (line->user_flag_set())
5033 {
5034 // This line needs to be refined. Find the next unused vertex
5035 // and set it appropriately
5036 while (triangulation.vertices_used[next_unused_vertex] == true)
5037 ++next_unused_vertex;
5038 Assert(next_unused_vertex < triangulation.vertices.size(),
5039 ExcMessage(
5040 "Internal error: During refinement, the triangulation "
5041 "wants to access an element of the 'vertices' array "
5042 "but it turns out that the array is not large "
5043 "enough."));
5044 triangulation.vertices_used[next_unused_vertex] = true;
5045
5046 triangulation.vertices[next_unused_vertex] = line->center(true);
5047
5048 bool pair_found = false;
5049 (void)pair_found;
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 bool pair_found = false;
5819 (void)pair_found;
5820 for (; next_unused_line != endl; ++next_unused_line)
5821 if (!next_unused_line->used() &&
5822 !(++next_unused_line)->used())
5823 {
5824 // go back to the first of the two unused
5825 // lines
5826 --next_unused_line;
5827 pair_found = true;
5828 break;
5829 }
5830 Assert(pair_found, ExcInternalError());
5831
5832 // there are now two consecutive unused lines, such
5833 // that the children of a line will be consecutive.
5834 // then set the child pointer of the present line
5835 line->set_children(0, next_unused_line->index());
5836
5837 // set the two new lines
5839 children[2] = {next_unused_line, ++next_unused_line};
5840 // some tests; if any of the iterators should be
5841 // invalid, then already dereferencing will fail
5842 AssertIsNotUsed(children[0]);
5843 AssertIsNotUsed(children[1]);
5844
5845 children[0]->set_bounding_object_indices(
5846 {line->vertex_index(0), next_unused_vertex});
5847 children[1]->set_bounding_object_indices(
5848 {next_unused_vertex, line->vertex_index(1)});
5849
5850 children[0]->set_used_flag();
5851 children[1]->set_used_flag();
5852 children[0]->clear_children();
5853 children[1]->clear_children();
5854 children[0]->clear_user_data();
5855 children[1]->clear_user_data();
5856 children[0]->clear_user_flag();
5857 children[1]->clear_user_flag();
5858
5859
5860 children[0]->set_boundary_id_internal(line->boundary_id());
5861 children[1]->set_boundary_id_internal(line->boundary_id());
5862
5863 children[0]->set_manifold_id(line->manifold_id());
5864 children[1]->set_manifold_id(line->manifold_id());
5865
5866 // finally clear flag indicating the need for
5867 // refinement
5868 line->clear_user_flag();
5869 }
5870 }
5871
5872
5873 // Now set up the new cells
5874
5875 // reserve space for inner lines (can be stored as single
5876 // lines)
5877 reserve_space(triangulation.faces->lines, 0, n_single_lines);
5878
5880 cells_with_distorted_children;
5881
5882 // reset next_unused_line, as now also single empty places in
5883 // the vector can be used
5885 next_unused_line = triangulation.begin_raw_line();
5886
5887 for (int level = 0;
5888 level < static_cast<int>(triangulation.levels.size()) - 1;
5889 ++level)
5890 {
5892 next_unused_cell = triangulation.begin_raw(level + 1);
5893
5894 for (const auto &cell :
5895 triangulation.active_cell_iterators_on_level(level))
5896 if (cell->refine_flag_set())
5897 {
5898 // actually set up the children and update neighbor
5899 // information
5900 create_children(triangulation,
5901 next_unused_vertex,
5902 next_unused_line,
5903 next_unused_cell,
5904 cell);
5905
5906 if (check_for_distorted_cells &&
5907 has_distorted_children<dim, spacedim>(cell))
5908 cells_with_distorted_children.distorted_cells.push_back(
5909 cell);
5910 // inform all listeners that cell refinement is done
5911 triangulation.signals.post_refinement_on_cell(cell);
5912 }
5913 }
5914
5915 return cells_with_distorted_children;
5916 }
5917
5918
5919 template <int spacedim>
5922 const bool check_for_distorted_cells)
5923 {
5924 static const int dim = 3;
5925 static const unsigned int X = numbers::invalid_unsigned_int;
5926 using raw_line_iterator =
5928 using raw_quad_iterator =
5930
5931 Assert(spacedim == 3, ExcNotImplemented());
5932
5933 Assert(triangulation.vertices.size() ==
5934 triangulation.vertices_used.size(),
5936
5937 // Check whether a new level is needed. We have to check for
5938 // this on the highest level only
5939 for (const auto &cell : triangulation.active_cell_iterators_on_level(
5940 triangulation.levels.size() - 1))
5941 if (cell->refine_flag_set())
5942 {
5943 triangulation.levels.push_back(
5944 std::make_unique<
5946 break;
5947 }
5948
5949 // first clear user flags for quads and lines; we're going to
5950 // use them to flag which lines and quads need refinement
5951 triangulation.faces->quads.clear_user_data();
5952 triangulation.faces->lines.clear_user_flags();
5953 triangulation.faces->quads.clear_user_flags();
5954
5955 // check how much space is needed on every level. We need not
5956 // check the highest level since either
5957 // - on the highest level no cells are flagged for refinement
5958 // - there are, but prepare_refinement added another empty
5959 // level which then is the highest level
5960
5961 // variables to hold the number of newly to be created
5962 // vertices, lines and quads. as these are stored globally,
5963 // declare them outside the loop over al levels. we need lines
5964 // and quads in pairs for refinement of old ones and lines and
5965 // quads, that can be stored as single ones, as they are newly
5966 // created in the inside of an existing cell
5967 unsigned int needed_vertices = 0;
5968 unsigned int needed_lines_single = 0;
5969 unsigned int needed_quads_single = 0;
5970 unsigned int needed_lines_pair = 0;
5971 unsigned int needed_quads_pair = 0;
5972 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5973 {
5974 unsigned int new_cells = 0;
5975
5976 for (const auto &cell :
5977 triangulation.active_cell_iterators_on_level(level))
5978 if (cell->refine_flag_set())
5979 {
5980 // Only support isotropic refinement
5981 Assert(cell->refine_flag_set() ==
5984
5985 // Now count up how many new cells, faces, edges, and vertices
5986 // we will need to allocate to do this refinement.
5987 new_cells += cell->reference_cell().n_isotropic_children();
5988
5989 if (cell->reference_cell() == ReferenceCells::Hexahedron)
5990 {
5991 ++needed_vertices;
5992 needed_lines_single += 6;
5993 needed_quads_single += 12;
5994 }
5995 else if (cell->reference_cell() ==
5997 {
5998 needed_lines_single += 1;
5999 needed_quads_single += 8;
6000 }
6001 else
6002 {
6004 }
6005
6006 // Also check whether we have to refine any of the faces and
6007 // edges that bound this cell. They may of course already be
6008 // refined, so we only *mark* them for refinement by setting
6009 // the user flags
6010 for (const auto face : cell->face_indices())
6011 if (cell->face(face)->n_children() == 0)
6012 cell->face(face)->set_user_flag();
6013 else
6014 Assert(cell->face(face)->n_children() ==
6015 cell->reference_cell()
6016 .face_reference_cell(face)
6017 .n_isotropic_children(),
6019
6020 for (const auto line : cell->line_indices())
6021 if (cell->line(line)->has_children() == false)
6022 cell->line(line)->set_user_flag();
6023 else
6024 Assert(cell->line(line)->n_children() == 2,
6026 }
6027
6028 const unsigned int used_cells =
6029 std::count(triangulation.levels[level + 1]->cells.used.begin(),
6030 triangulation.levels[level + 1]->cells.used.end(),
6031 true);
6032
6033 if (triangulation.all_reference_cells_are_hyper_cube())
6034 reserve_space(*triangulation.levels[level + 1],
6035 used_cells + new_cells,
6036 3,
6037 spacedim,
6038 false);
6039 else
6040 reserve_space(*triangulation.levels[level + 1],
6041 used_cells + new_cells,
6042 3,
6043 spacedim,
6044 true);
6045
6046 reserve_space(triangulation.levels[level + 1]->cells, new_cells);
6047 }
6048
6049 // now count the quads and lines which were flagged for
6050 // refinement
6053 quad != triangulation.end_quad();
6054 ++quad)
6055 {
6056 if (quad->user_flag_set() == false)
6057 continue;
6058
6059 if (quad->reference_cell() == ReferenceCells::Quadrilateral)
6060 {
6061 needed_quads_pair += 4;
6062 needed_lines_pair += 4;
6063 needed_vertices += 1;
6064 }
6065 else if (quad->reference_cell() == ReferenceCells::Triangle)
6066 {
6067 needed_quads_pair += 4;
6068 needed_lines_single += 3;
6069 }
6070 else
6071 {
6073 }
6074 }
6075
6078 line != triangulation.end_line();
6079 ++line)
6080 {
6081 if (line->user_flag_set() == false)
6082 continue;
6083
6084 needed_lines_pair += 2;
6085 needed_vertices += 1;
6086 }
6087
6088 reserve_space(triangulation.faces->lines,
6089 needed_lines_pair,
6090 needed_lines_single);
6092 needed_quads_pair,
6093 needed_quads_single);
6094 reserve_space(triangulation.faces->quads,
6095 needed_quads_pair,
6096 needed_quads_single);
6097
6098
6099 // add to needed vertices how many vertices are already in use
6100 needed_vertices += std::count(triangulation.vertices_used.begin(),
6101 triangulation.vertices_used.end(),
6102 true);
6103
6104 if (needed_vertices > triangulation.vertices.size())
6105 {
6106 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
6107 triangulation.vertices_used.resize(needed_vertices, false);
6108 }
6109
6110 //-----------------------------------------
6111 // Before we start with the actual refinement, we do some
6112 // sanity checks if in debug mode. especially, we try to catch
6113 // the notorious problem with lines being twice refined,
6114 // i.e. there are cells adjacent at one line ("around the
6115 // edge", but not at a face), with two cells differing by more
6116 // than one refinement level
6117 //
6118 // this check is very simple to implement here, since we have
6119 // all lines flagged if they shall be refined
6120#ifdef DEBUG
6121 for (const auto &cell : triangulation.active_cell_iterators())
6122 if (!cell->refine_flag_set())
6123 for (unsigned int line_n = 0; line_n < cell->n_lines(); ++line_n)
6124 if (cell->line(line_n)->has_children())
6125 for (unsigned int c = 0; c < 2; ++c)
6126 Assert(cell->line(line_n)->child(c)->user_flag_set() == false,
6128#endif
6129
6130 unsigned int current_vertex = 0;
6131
6132 // helper function - find the next available vertex number and mark it
6133 // as used.
6134 auto get_next_unused_vertex = [](const unsigned int current_vertex,
6135 std::vector<bool> &vertices_used) {
6136 unsigned int next_vertex = current_vertex;
6137 while (next_vertex < vertices_used.size() &&
6138 vertices_used[next_vertex] == true)
6139 ++next_vertex;
6140 Assert(next_vertex < vertices_used.size(), ExcInternalError());
6141 vertices_used[next_vertex] = true;
6142
6143 return next_vertex;
6144 };
6145
6146 // LINES
6147 {
6150 endl = triangulation.end_line();
6151 raw_line_iterator next_unused_line = triangulation.begin_raw_line();
6152
6153 for (; line != endl; ++line)
6154 {
6155 if (line->user_flag_set() == false)
6156 continue;
6157
6158 next_unused_line =
6159 triangulation.faces->lines.template next_free_pair_object<1>(
6161 Assert(next_unused_line.state() == IteratorState::valid,
6163
6164 // now we found two consecutive unused lines, such
6165 // that the children of a line will be consecutive.
6166 // then set the child pointer of the present line
6167 line->set_children(0, next_unused_line->index());
6168
6169 const std::array<raw_line_iterator, 2> children{
6170 {next_unused_line, ++next_unused_line}};
6171
6172 AssertIsNotUsed(children[0]);
6173 AssertIsNotUsed(children[1]);
6174
6175 current_vertex =
6176 get_next_unused_vertex(current_vertex,
6177 triangulation.vertices_used);
6178 triangulation.vertices[current_vertex] = line->center(true);
6179
6180 children[0]->set_bounding_object_indices(
6181 {line->vertex_index(0), current_vertex});
6182 children[1]->set_bounding_object_indices(
6183 {current_vertex, line->vertex_index(1)});
6184
6185 const auto manifold_id = line->manifold_id();
6186 const auto boundary_id = line->boundary_id();
6187 for (const auto &child : children)
6188 {
6189 child->set_used_flag();
6190 child->clear_children();
6191 child->clear_user_data();
6192 child->clear_user_flag();
6193 child->set_boundary_id_internal(boundary_id);
6194 child->set_manifold_id(manifold_id);
6195 }
6196
6197 line->clear_user_flag();
6198 }
6199 }
6200
6201 // QUADS
6202 {
6204 quad = triangulation.begin_quad(),
6205 endq = triangulation.end_quad();
6206
6207 for (; quad != endq; ++quad)
6208 {
6209 if (quad->user_flag_set() == false)
6210 continue;
6211
6212 const auto reference_face_type = quad->reference_cell();
6213
6214 // 1) create new lines (property is set later)
6215 // maximum of 4 new lines (4 quadrilateral, 3 triangle)
6216 std::array<raw_line_iterator, 4> new_lines;
6217 if (reference_face_type == ReferenceCells::Quadrilateral)
6218 {
6219 for (unsigned int l = 0; l < 2; ++l)
6220 {
6221 auto next_unused_line =
6222 triangulation.faces->lines
6223 .template next_free_pair_object<1>(triangulation);
6224 new_lines[2 * l] = next_unused_line;
6225 new_lines[2 * l + 1] = ++next_unused_line;
6226 }
6227 }
6228 else if (reference_face_type == ReferenceCells::Triangle)
6229 {
6230 for (unsigned int l = 0; l < 3; ++l)
6231 new_lines[l] =
6232 triangulation.faces->lines
6233 .template next_free_single_object<1>(triangulation);
6234 }
6235 else
6236 {
6238 }
6239
6240 for (const unsigned int line : quad->line_indices())
6241 {
6242 AssertIsNotUsed(new_lines[line]);
6243 (void)line;
6244 }
6245
6246 // 2) create new quads (properties are set below). Both triangles
6247 // and quads are divided in four.
6248 std::array<raw_quad_iterator, 4> new_quads;
6249 for (unsigned int q = 0; q < 2; ++q)
6250 {
6251 auto next_unused_quad =
6252 triangulation.faces->quads
6253 .template next_free_pair_object<2>(triangulation);
6254
6255 new_quads[2 * q] = next_unused_quad;
6256 new_quads[2 * q + 1] = ++next_unused_quad;
6257
6258 quad->set_children(2 * q, new_quads[2 * q]->index());
6259 }
6260 quad->set_refinement_case(RefinementCase<2>::cut_xy);
6261
6262 for (const auto &quad : new_quads)
6263 {
6264 AssertIsNotUsed(quad);
6265 (void)quad;
6266 }
6267
6268 // 3) set vertex indices and set new vertex
6269
6270 // Maximum of 9 vertices per refined quad (9 for Quadrilateral, 6
6271 // for Triangle)
6272 std::array<unsigned int, 9> vertex_indices = {};
6273 unsigned int k = 0;
6274 for (const auto i : quad->vertex_indices())
6275 vertex_indices[k++] = quad->vertex_index(i);
6276
6277 for (const auto i : quad->line_indices())
6278 vertex_indices[k++] = quad->line(i)->child(0)->vertex_index(1);
6279
6280 if (reference_face_type == ReferenceCells::Quadrilateral)
6281 {
6282 current_vertex =
6283 get_next_unused_vertex(current_vertex,
6284 triangulation.vertices_used);
6285 vertex_indices[k++] = current_vertex;
6286
6287 triangulation.vertices[current_vertex] =
6288 quad->center(true, true);
6289 }
6290
6291 // 4) set new lines on quads and their properties
6292 std::array<raw_line_iterator, 12> lines;
6293 unsigned int n_lines = 0;
6294 for (unsigned int l = 0; l < quad->n_lines(); ++l)
6295 for (unsigned int c = 0; c < 2; ++c)
6296 {
6297 static constexpr ::ndarray<unsigned int, 2, 2> index =
6298 {{// child 0, line_orientation=false and true
6299 {{1, 0}},
6300 // child 1, line_orientation=false and true
6301 {{0, 1}}}};
6302
6303 lines[n_lines++] =
6304 quad->line(l)->child(index[c][quad->line_orientation(l)]);
6305 }
6306
6307 for (unsigned int l = 0; l < quad->n_lines(); ++l)
6308 lines[n_lines++] = new_lines[l];
6309
6310 std::array<int, 12> line_indices;
6311 for (unsigned int i = 0; i < n_lines; ++i)
6312 line_indices[i] = lines[i]->index();
6313
6314 static constexpr ::ndarray<unsigned int, 12, 2>
6315 line_vertices_quad{{{{0, 4}},
6316 {{4, 2}},
6317 {{1, 5}},
6318 {{5, 3}},
6319 {{0, 6}},
6320 {{6, 1}},
6321 {{2, 7}},
6322 {{7, 3}},
6323 {{6, 8}},
6324 {{8, 7}},
6325 {{4, 8}},
6326 {{8, 5}}}};
6327
6328 static constexpr ::ndarray<unsigned int, 4, 4>
6329 quad_lines_quad{{{{0, 8, 4, 10}},
6330 {{8, 2, 5, 11}},
6331 {{1, 9, 10, 6}},
6332 {{9, 3, 11, 7}}}};
6333
6334 static constexpr ::ndarray<unsigned int, 12, 2>
6335 line_vertices_tri{{{{0, 3}},
6336 {{3, 1}},
6337 {{1, 4}},
6338 {{4, 2}},
6339 {{2, 5}},
6340 {{5, 0}},
6341 {{3, 4}},
6342 {{4, 5}},
6343 {{3, 5}},
6344 {{X, X}},
6345 {{X, X}},
6346 {{X, X}}}};
6347
6348 static constexpr ::ndarray<unsigned int, 4, 4>
6349 quad_lines_tri{{{{0, 8, 5, X}},
6350 {{1, 2, 6, X}},
6351 {{7, 3, 4, X}},
6352 {{6, 7, 8, X}}}};
6353
6354 static constexpr ::ndarray<unsigned int, 4, 4, 2>
6355 quad_line_vertices_tri{
6356 {{{{{0, 3}}, {{3, 5}}, {{5, 0}}, {{X, X}}}},
6357 {{{{3, 1}}, {{1, 4}}, {{4, 3}}, {{X, X}}}},
6358 {{{{5, 4}}, {{4, 2}}, {{2, 5}}, {{X, X}}}},
6359 {{{{3, 4}}, {{4, 5}}, {{5, 3}}, {{X, X}}}}}};
6360
6361 const auto &line_vertices =
6362 (reference_face_type == ReferenceCells::Quadrilateral) ?
6363 line_vertices_quad :
6364 line_vertices_tri;
6365 const auto &quad_lines =
6366 (reference_face_type == ReferenceCells::Quadrilateral) ?
6367 quad_lines_quad :
6368 quad_lines_tri;
6369
6370 for (unsigned int i = 0, j = 2 * quad->n_lines();
6371 i < quad->n_lines();
6372 ++i, ++j)
6373 {
6374 auto &new_line = new_lines[i];
6375 new_line->set_bounding_object_indices(
6376 {vertex_indices[line_vertices[j][0]],
6377 vertex_indices[line_vertices[j][1]]});
6378 new_line->set_used_flag();
6379 new_line->clear_user_flag();
6380 new_line->clear_user_data();
6381 new_line->clear_children();
6382 new_line->set_boundary_id_internal(quad->boundary_id());
6383 new_line->set_manifold_id(quad->manifold_id());
6384 }
6385
6386 // 5) set properties of quads
6387 for (unsigned int i = 0; i < new_quads.size(); ++i)
6388 {
6389 auto &new_quad = new_quads[i];
6390
6391 // TODO: we assume here that all children have the same type
6392 // as the parent
6393 triangulation.faces->set_quad_type(new_quad->index(),
6394 reference_face_type);
6395
6396 if (reference_face_type == ReferenceCells::Triangle)
6397 new_quad->set_bounding_object_indices(
6398 {line_indices[quad_lines[i][0]],
6399 line_indices[quad_lines[i][1]],
6400 line_indices[quad_lines[i][2]]});
6401 else if (reference_face_type == ReferenceCells::Quadrilateral)
6402 new_quad->set_bounding_object_indices(
6403 {line_indices[quad_lines[i][0]],
6404 line_indices[quad_lines[i][1]],
6405 line_indices[quad_lines[i][2]],
6406 line_indices[quad_lines[i][3]]});
6407 else
6409
6410 new_quad->set_used_flag();
6411 new_quad->clear_user_flag();
6412 new_quad->clear_user_data();
6413 new_quad->clear_children();
6414 new_quad->set_boundary_id_internal(quad->boundary_id());
6415 new_quad->set_manifold_id(quad->manifold_id());
6416
6417#ifdef DEBUG
6418 std::set<unsigned int> s;
6419#endif
6420
6421 // ... and fix orientation of lines of face for triangles,
6422 // using an expensive algorithm, quadrilaterals are treated
6423 // a few lines below by a cheaper algorithm
6424 if (reference_face_type == ReferenceCells::Triangle)
6425 {
6426 for (const auto f : new_quad->line_indices())
6427 {
6428 const std::array<unsigned int, 2> vertices_0 = {
6429 {lines[quad_lines[i][f]]->vertex_index(0),
6430 lines[quad_lines[i][f]]->vertex_index(1)}};
6431
6432 const std::array<unsigned int, 2> vertices_1 = {
6433 {vertex_indices[quad_line_vertices_tri[i][f][0]],
6434 vertex_indices[quad_line_vertices_tri[i][f][1]]}};
6435
6436 const auto orientation =
6438 make_array_view(vertices_0),
6439 make_array_view(vertices_1));
6440
6441#ifdef DEBUG
6442 for (const auto i : vertices_0)
6443 s.insert(i);
6444 for (const auto i : vertices_1)
6445 s.insert(i);
6446#endif
6447
6448 new_quad->set_line_orientation(
6449 f,
6450 orientation ==
6452 default_combined_face_orientation());
6453 }
6454#ifdef DEBUG
6455 AssertDimension(s.size(), 3);
6456#endif
6457 }
6458 }
6459
6460 // fix orientation of lines of faces for quadrilaterals with
6461 // cheap algorithm
6462 if (reference_face_type == ReferenceCells::Quadrilateral)
6463 {
6464 static constexpr ::ndarray<unsigned int, 4, 2>
6465 quad_child_boundary_lines{
6466 {{{0, 2}}, {{1, 3}}, {{0, 1}}, {{2, 3}}}};
6467
6468 for (unsigned int i = 0; i < 4; ++i)
6469 for (unsigned int j = 0; j < 2; ++j)
6470 new_quads[quad_child_boundary_lines[i][j]]
6471 ->set_line_orientation(i, quad->line_orientation(i));
6472 }
6473
6474 quad->clear_user_flag();
6475 }
6476 }
6477
6479 cells_with_distorted_children;
6480
6483 for (unsigned int level = 0; level != triangulation.levels.size() - 1;
6484 ++level)
6485 {
6487 next_unused_hex = triangulation.begin_raw_hex(level + 1);
6488 Assert(hex == triangulation.end() ||
6489 hex->level() >= static_cast<int>(level),
6491
6492 for (; hex != triangulation.end() &&
6493 hex->level() == static_cast<int>(level);
6494 ++hex)
6495 {
6496 if (hex->refine_flag_set() ==
6498 continue;
6499
6500 const auto &reference_cell_type = hex->reference_cell();
6501
6502 const RefinementCase<dim> ref_case = hex->refine_flag_set();
6503 hex->clear_refine_flag();
6504 hex->set_refinement_case(ref_case);
6505
6506 unsigned int n_new_lines = 0;
6507 unsigned int n_new_quads = 0;
6508 unsigned int n_new_hexes = 0;
6509
6510 if (reference_cell_type == ReferenceCells::Hexahedron)
6511 {
6512 n_new_lines = 6;
6513 n_new_quads = 12;
6514 n_new_hexes = 8;
6515 }
6516 else if (reference_cell_type == ReferenceCells::Tetrahedron)
6517 {
6518 n_new_lines = 1;
6519 n_new_quads = 8;
6520 n_new_hexes = 8;
6521 }
6522 else
6524
6525 std::array<raw_line_iterator, 6> new_lines;
6526 for (unsigned int i = 0; i < n_new_lines; ++i)
6527 {
6528 new_lines[i] =
6529 triangulation.faces->lines
6530 .template next_free_single_object<1>(triangulation);
6531
6532 AssertIsNotUsed(new_lines[i]);
6533 new_lines[i]->set_used_flag();
6534 new_lines[i]->clear_user_flag();
6535 new_lines[i]->clear_user_data();
6536 new_lines[i]->clear_children();
6537 new_lines[i]->set_boundary_id_internal(
6539 new_lines[i]->set_manifold_id(hex->manifold_id());
6540 }
6541
6542 std::array<raw_quad_iterator, 12> new_quads;
6543 for (unsigned int i = 0; i < n_new_quads; ++i)
6544 {
6545 new_quads[i] =
6546 triangulation.faces->quads
6547 .template next_free_single_object<2>(triangulation);
6548
6549 auto &new_quad = new_quads[i];
6550
6551 // TODO: faces of children have the same type as the faces
6552 // of the parent
6553 triangulation.faces->set_quad_type(
6554 new_quad->index(),
6555 reference_cell_type.face_reference_cell(0));
6556
6557 AssertIsNotUsed(new_quad);
6558 new_quad->set_used_flag();
6559 new_quad->clear_user_flag();
6560 new_quad->clear_user_data();
6561 new_quad->clear_children();
6562 new_quad->set_boundary_id_internal(
6564 new_quad->set_manifold_id(hex->manifold_id());
6565 for (const auto j : new_quads[i]->line_indices())
6566 new_quad->set_line_orientation(j, true);
6567 }
6568
6569 // we always get 8 children per refined cell
6570 std::array<
6572 8>
6573 new_hexes;
6574 {
6575 for (unsigned int i = 0; i < n_new_hexes; ++i)
6576 {
6577 if (i % 2 == 0)
6578 next_unused_hex =
6579 triangulation.levels[level + 1]->cells.next_free_hex(
6580 triangulation, level + 1);
6581 else
6582 ++next_unused_hex;
6583
6584 new_hexes[i] = next_unused_hex;
6585
6586 auto &new_hex = new_hexes[i];
6587
6588 // children have the same type as the parent
6589 triangulation.levels[new_hex->level()]
6590 ->reference_cell[new_hex->index()] =
6591 reference_cell_type;
6592
6593 AssertIsNotUsed(new_hex);
6594 new_hex->set_used_flag();
6595 new_hex->clear_user_flag();
6596 new_hex->clear_user_data();
6597 new_hex->clear_children();
6598 new_hex->set_material_id(hex->material_id());
6599 new_hex->set_manifold_id(hex->manifold_id());
6600 new_hex->set_subdomain_id(hex->subdomain_id());
6601
6602 if (i % 2)
6603 new_hex->set_parent(hex->index());
6604
6605 // set the orientation flag to its default state for all
6606 // faces initially. later on go the other way round and
6607 // reset faces that are at the boundary of the mother cube
6608 for (const auto f : new_hex->face_indices())
6609 new_hex->set_combined_face_orientation(
6610 f,
6612 }
6613 for (unsigned int i = 0; i < n_new_hexes / 2; ++i)
6614 hex->set_children(2 * i, new_hexes[2 * i]->index());
6615 }
6616
6617 {
6618 // load vertex indices
6619 std::array<unsigned int, 27> vertex_indices = {};
6620
6621 {
6622 unsigned int k = 0;
6623
6624 // avoid a compiler warning by fixing the max number of
6625 // loop iterations to 8
6626 const unsigned int n_vertices =
6627 std::min(hex->n_vertices(), 8u);
6628 for (unsigned int i = 0; i < n_vertices; ++i)
6629 vertex_indices[k++] = hex->vertex_index(i);
6630
6631 const std::array<unsigned int, 12> line_indices =
6632 TriaAccessorImplementation::Implementation::
6633 get_line_indices_of_cell(*hex);
6634
6635 // For the tetrahedron the parent consists of the vertices
6636 // 0,1,2,3, the new vertices 4-9 are defined as the
6637 // midpoints of the edges: 4 -> (0,1), 5 -> (1,2), 6 ->
6638 // (2,0), 7 -> (0,3), 8 -> (1,3), 9 -> (2,3).
6639 // Order is defined by the reference cell, see
6640 // https://dealii.org/developer/doxygen/deal.II/group__simplex.html#simplex_reference_cells.
6641
6642 // Avoid a compiler warning by fixing the max number of loop
6643 // iterations to 12
6644 const unsigned int n_lines = std::min(hex->n_lines(), 12u);
6645 for (unsigned int l = 0; l < n_lines; ++l)
6646 {
6647 raw_line_iterator line(&triangulation,
6648 0,
6649 line_indices[l]);
6650 vertex_indices[k++] = line->child(0)->vertex_index(1);
6651 }
6652
6653 if (reference_cell_type == ReferenceCells::Hexahedron)
6654 {
6655 for (const unsigned int i : hex->face_indices())
6656 vertex_indices[k++] =
6657 hex->face(i)->child(0)->vertex_index(3);
6658
6659 // Set single new vertex in the center
6660 current_vertex =
6661 get_next_unused_vertex(current_vertex,
6662 triangulation.vertices_used);
6663 vertex_indices[k++] = current_vertex;
6664
6665 triangulation.vertices[current_vertex] =
6666 hex->center(true, true);
6667 }
6668 }
6669
6670 unsigned int chosen_line_tetrahedron = 0;
6671 // set up new lines
6672 if (reference_cell_type == ReferenceCells::Hexahedron)
6673 {
6674 static constexpr ::ndarray<unsigned int, 6, 2>
6675 new_line_vertices = {{{{22, 26}},
6676 {{26, 23}},
6677 {{20, 26}},
6678 {{26, 21}},
6679 {{24, 26}},
6680 {{26, 25}}}};
6681 for (unsigned int i = 0; i < n_new_lines; ++i)
6682 new_lines[i]->set_bounding_object_indices(
6683 {vertex_indices[new_line_vertices[i][0]],
6684 vertex_indices[new_line_vertices[i][1]]});
6685 }
6686 else if (reference_cell_type == ReferenceCells::Tetrahedron)
6687 {
6688 // in the tetrahedron case, we have the three
6689 // possibilities (6,8), (5,7), (4,9) -> pick the
6690 // shortest line to guarantee the best possible aspect
6691 // ratios
6692 static constexpr ::ndarray<unsigned int, 3, 2>
6693 new_line_vertices = {{{{6, 8}}, {{5, 7}}, {{4, 9}}}};
6694
6695 // choose line to cut either by refinement case or by
6696 // shortest distance between edge midpoints
6697 std::uint8_t refinement_choice = hex->refine_choice();
6698 if (refinement_choice ==
6699 static_cast<char>(
6701 {
6702 const auto &vertices = triangulation.get_vertices();
6703 double min_distance =
6704 std::numeric_limits<double>::infinity();
6705 for (unsigned int i = 0; i < new_line_vertices.size();
6706 ++i)
6707 {
6708 const double current_distance =
6709 vertices
6710 [vertex_indices[new_line_vertices[i][0]]]
6711 .distance(
6713 [new_line_vertices[i][1]]]);
6714 if (current_distance < min_distance)
6715 {
6716 chosen_line_tetrahedron = i;
6717 min_distance = current_distance;
6718 }
6719 }
6720 }
6721 else if (refinement_choice ==
6722 static_cast<char>(
6724 chosen_line_tetrahedron = 0;
6725 else if (refinement_choice ==
6726 static_cast<char>(
6728 chosen_line_tetrahedron = 1;
6729 else if (refinement_choice ==
6730 static_cast<char>(
6732 chosen_line_tetrahedron = 2;
6733 else
6735
6736 hex->set_refinement_case(
6737 RefinementCase<dim>(chosen_line_tetrahedron + 1));
6738
6739 new_lines[0]->set_bounding_object_indices(
6741 [new_line_vertices[chosen_line_tetrahedron][0]],
6743 [new_line_vertices[chosen_line_tetrahedron][1]]});
6744 }
6745
6746 // set up new quads
6747 {
6748 boost::container::small_vector<raw_line_iterator, 30>
6749 relevant_lines;
6750
6751 if (reference_cell_type == ReferenceCells::Hexahedron)
6752 {
6753 relevant_lines.resize(30);
6754 for (unsigned int f = 0, k = 0; f < 6; ++f)
6755 for (unsigned int c = 0; c < 4; ++c, ++k)
6756 {
6757 static constexpr ::
6758 ndarray<unsigned int, 4, 2>
6759 temp = {
6760 {{{0, 1}}, {{3, 0}}, {{0, 3}}, {{3, 2}}}};
6761
6762 relevant_lines[k] =
6763 hex->face(f)
6764 ->isotropic_child(
6766 standard_to_real_face_vertex(
6767 temp[c][0],
6768 hex->face_orientation(f),
6769 hex->face_flip(f),
6770 hex->face_rotation(f)))
6771 ->line(GeometryInfo<dim>::
6772 standard_to_real_face_line(
6773 temp[c][1],
6774 hex->face_orientation(f),
6775 hex->face_flip(f),
6776 hex->face_rotation(f)));
6777 }
6778
6779 for (unsigned int i = 0, k = 24; i < 6; ++i, ++k)
6780 relevant_lines[k] = new_lines[i];
6781 }
6782 else if (reference_cell_type == ReferenceCells::Tetrahedron)
6783 {
6784 // The order of the lines is defined by the ordering
6785 // of the faces of the reference cell and the ordering
6786 // of the lines within a face.
6787 // Each face is split into 4 child triangles, the
6788 // relevant lines are defined by the vertices of the
6789 // center triangles: 0 -> (4,5), 1 -> (5,6), 2 -> (4,6),
6790 // 3 -> (4,7), 4 -> (7,8), 5 -> (4,8), 6 -> (6,9), 7 ->
6791 // (9,7), 8 -> (6,7), 9 -> (5,8), 10 -> (8,9), 11 ->
6792 // (5,9), Line 12 is determined by
6793 // chosen_line_tetrahedron i.e. (6,8), (5,7) or (4,9)
6794
6795 relevant_lines.resize(13);
6796
6797 unsigned int k = 0;
6798 for (unsigned int f = 0; f < 4; ++f)
6799 for (unsigned int l = 0; l < 3; ++l, ++k)
6800 {
6801 // TODO: add comment
6802 static const std::
6803 array<std::array<unsigned int, 3>, 6>
6804 table = {{{{1, 0, 2}}, // 0
6805 {{0, 1, 2}},
6806 {{0, 2, 1}}, // 2
6807 {{1, 2, 0}},
6808 {{2, 1, 0}}, // 4
6809 {{2, 0, 1}}}};
6810
6811 const unsigned char combined_orientation =
6812 hex->combined_face_orientation(f);
6813 relevant_lines[k] =
6814 hex->face(f)
6815 ->child(3 /*center triangle*/)
6816 ->line(table[combined_orientation][l]);
6817 }
6818
6819 relevant_lines[k++] = new_lines[0];
6820 AssertDimension(k, 13);
6821 }
6822 else
6824
6825 boost::container::small_vector<unsigned int, 30>
6826 relevant_line_indices(relevant_lines.size());
6827 for (unsigned int i = 0; i < relevant_line_indices.size();
6828 ++i)
6829 relevant_line_indices[i] = relevant_lines[i]->index();
6830
6831 // It is easierst to start at table cell_vertices,
6832 // there the vertices are listed which build up the
6833 // 8 child tets. To build the child tets, 8 new faces are
6834 // needed. The the vertices, which define the lines of these
6835 // new faces are listed in table_tet. Now only the
6836 // corresponding index of the lines and quads have to be
6837 // listed in new_quad_lines_tet and cell_quads_tet.
6838 const auto &new_quad_lines =
6839 hex->reference_cell().new_isotropic_child_face_lines(
6840 chosen_line_tetrahedron);
6841
6842 // The first 4 define the faces which cut off the
6843 // parent tetrahedron at the edges. the numbers are the
6844 // index of the relevant_lines defined above the last 4
6845 // faces cut apart the remaining octahedron, such that all
6846 // of these contain line number 12. the ordering of the
6847 // faces is arbitrary, the ordering within the faces has to
6848 // follow the righthand convention for triangles
6849 // The table defines the vertices of the lines above
6850 // see relevant_lines for mapping between line indices and
6851 // vertex numbering
6852 const auto &table =
6853 hex->reference_cell()
6854 .new_isotropic_child_face_line_vertices(
6855 chosen_line_tetrahedron);
6856
6857 static constexpr ::ndarray<unsigned int, 4, 2>
6858 representative_lines{
6859 {{{0, 2}}, {{2, 0}}, {{3, 3}}, {{1, 1}}}};
6860
6861 for (unsigned int q = 0; q < n_new_quads; ++q)
6862 {
6863 auto &new_quad = new_quads[q];
6864
6865 if (new_quad->n_lines() == 3)
6866 new_quad->set_bounding_object_indices(
6867 {relevant_line_indices[new_quad_lines[q][0]],
6868 relevant_line_indices[new_quad_lines[q][1]],
6869 relevant_line_indices[new_quad_lines[q][2]]});
6870 else if (new_quad->n_lines() == 4)
6871 new_quad->set_bounding_object_indices(
6872 {relevant_line_indices[new_quad_lines[q][0]],
6873 relevant_line_indices[new_quad_lines[q][1]],
6874 relevant_line_indices[new_quad_lines[q][2]],
6875 relevant_line_indices[new_quad_lines[q][3]]});
6876 else
6878
6879 // On hexes, we must only determine a single line
6880 // according to the representative_lines array above
6881 // (this saves expensive operations), for tets we do
6882 // all lines manually
6883 const unsigned int n_compute_lines =
6884 reference_cell_type == ReferenceCells::Hexahedron ?
6885 1 :
6886 new_quad->n_lines();
6887 for (unsigned int line = 0; line < n_compute_lines;
6888 ++line)
6889 {
6890 const unsigned int l =
6891 (reference_cell_type ==
6893 representative_lines[q % 4][0] :
6894 line;
6895
6896 const std::array<unsigned int, 2> vertices_0 = {
6897 {relevant_lines[new_quad_lines[q][l]]
6898 ->vertex_index(0),
6899 relevant_lines[new_quad_lines[q][l]]
6900 ->vertex_index(1)}};
6901
6902 const std::array<unsigned int, 2> vertices_1 = {
6903 {vertex_indices[table[q][l][0]],
6904 vertex_indices[table[q][l][1]]}};
6905
6906 const auto orientation =
6908 make_array_view(vertices_0),
6909 make_array_view(vertices_1));
6910
6911 new_quad->set_line_orientation(
6912 l,
6913 orientation ==
6915 default_combined_face_orientation());
6916
6917 // on a hex, inject the status of the current line
6918 // also to the line on the other quad along the
6919 // same direction
6920 if (reference_cell_type ==
6922 new_quads[representative_lines[q % 4][1] + q -
6923 (q % 4)]
6924 ->set_line_orientation(
6925 l,
6926 orientation ==
6928 default_combined_face_orientation());
6929 }
6930 }
6931 }
6932
6933 // set up new hex
6934 {
6935 std::array<int, 36> quad_indices;
6936
6937 if (reference_cell_type == ReferenceCells::Hexahedron)
6938 {
6939 for (unsigned int i = 0; i < n_new_quads; ++i)
6940 quad_indices[i] = new_quads[i]->index();
6941
6942 for (unsigned int f = 0, k = n_new_quads; f < 6; ++f)
6943 for (unsigned int c = 0; c < 4; ++c, ++k)
6944 quad_indices[k] =
6945 hex->face(f)->isotropic_child_index(
6947 c,
6948 hex->face_orientation(f),
6949 hex->face_flip(f),
6950 hex->face_rotation(f)));
6951 }
6952 else if (reference_cell_type == ReferenceCells::Tetrahedron)
6953 {
6954 // list of the indices of the surfaces which define the
6955 // 8 new tets. the indices 0-7 are the new quads defined
6956 // above (so 0-3 cut off the corners and 4-7 separate
6957 // the remaining octahedral), the indices between 8-11
6958 // are the children of the first face, from 12-15 of the
6959 // second, etc.
6960 for (unsigned int i = 0; i < n_new_quads; ++i)
6961 quad_indices[i] = new_quads[i]->index();
6962
6963 for (unsigned int f = 0, k = n_new_quads; f < 4; ++f)
6964 for (unsigned int c = 0; c < 4; ++c, ++k)
6965 {
6966 const unsigned char combined_orientation =
6967 hex->combined_face_orientation(f);
6968 quad_indices[k] = hex->face(f)->child_index(
6969 (c == 3) ? 3 :
6970 reference_cell_type
6971 .standard_to_real_face_vertex(
6972 c, f, combined_orientation));
6973 }
6974 }
6975 else
6976 {
6978 }
6979
6980 // indices of the faces which define the new tets
6981 // the ordering of the tets is arbitrary
6982 // the first 4 determine the tets cutting of the corners
6983 // the last 4 are ordered after their appearance in the
6984 // faces.
6985 // the ordering within the faces is determined by
6986 // convention for the tetrahedron unit cell, see
6987 // cell_vertices_tet below
6988 const auto &cell_quads =
6989 hex->reference_cell().new_isotropic_child_cell_faces(
6990 chosen_line_tetrahedron);
6991
6992 for (unsigned int c = 0;
6993 c < GeometryInfo<dim>::max_children_per_cell;
6994 ++c)
6995 {
6996 auto &new_hex = new_hexes[c];
6997
6998 if (new_hex->n_faces() == 4)
6999 {
7000 new_hex->set_bounding_object_indices(
7001 {quad_indices[cell_quads[c][0]],
7002 quad_indices[cell_quads[c][1]],
7003 quad_indices[cell_quads[c][2]],
7004 quad_indices[cell_quads[c][3]]});
7005
7006
7007 // for tets, we need to go through the faces and
7008 // figure the orientation out the hard way
7009 for (const auto f : new_hex->face_indices())
7010 {
7011 const auto &face = new_hex->face(f);
7012
7013 Assert(face->n_vertices() == 3,
7015
7016 const std::array<unsigned int, 3> vertices_0 = {
7017 {face->vertex_index(0),
7018 face->vertex_index(1),
7019 face->vertex_index(2)}};
7020
7021 // the 8 child tets are each defined by 4
7022 // vertices the ordering of the tets has to be
7023 // consistent with above the ordering within the
7024 // tets is given by the reference tet i.e.
7025 // looking at the fifth line the first 3
7026 // vertices are given by face 11, the last
7027 // vertex is the remaining of the tet
7028 const auto new_hex_vertices =
7029 hex->reference_cell()
7030 .new_isotropic_child_cell_vertices(
7031 chosen_line_tetrahedron)[c];
7032
7033 // arrange after vertices of the faces of the
7034 // unit cell
7035 const std::array<unsigned int, 3> vertices_1 = {
7036 {
7038 [new_hex_vertices
7040 .face_to_cell_vertices(f, 0, 1)]],
7042 [new_hex_vertices
7044 .face_to_cell_vertices(f, 1, 1)]],
7046 [new_hex_vertices
7048 .face_to_cell_vertices(f, 2, 1)]],
7049 }};
7050
7051 new_hex->set_combined_face_orientation(
7052 f,
7053 face->reference_cell()
7054 .get_combined_orientation(
7055 make_array_view(vertices_1),
7056 make_array_view(vertices_0)));
7057 }
7058 }
7059 else if (new_hex->n_faces() == 6)
7060 new_hex->set_bounding_object_indices(
7061 {quad_indices[cell_quads[c][0]],
7062 quad_indices[cell_quads[c][1]],
7063 quad_indices[cell_quads[c][2]],
7064 quad_indices[cell_quads[c][3]],
7065 quad_indices[cell_quads[c][4]],
7066 quad_indices[cell_quads[c][5]]});
7067 else
7069 }
7070
7071 // for hexes, we can simply inherit the orientation values
7072 // from the parent on the outer faces; the inner faces can
7073 // be skipped as their orientation is always the default
7074 // one set above
7075 static constexpr ::ndarray<unsigned int, 6, 4>
7076 face_to_child_indices_hex{{{{0, 2, 4, 6}},
7077 {{1, 3, 5, 7}},
7078 {{0, 1, 4, 5}},
7079 {{2, 3, 6, 7}},
7080 {{0, 1, 2, 3}},
7081 {{4, 5, 6, 7}}}};
7082 if (hex->n_faces() == 6)
7083 for (const auto f : hex->face_indices())
7084 {
7085 const unsigned char combined_orientation =
7086 hex->combined_face_orientation(f);
7087 for (unsigned int c = 0; c < 4; ++c)
7088 new_hexes[face_to_child_indices_hex[f][c]]
7089 ->set_combined_face_orientation(
7090 f, combined_orientation);
7091 }
7092 }
7093 }
7094
7095 if (check_for_distorted_cells &&
7096 has_distorted_children<dim, spacedim>(hex))
7097 cells_with_distorted_children.distorted_cells.push_back(hex);
7098
7099 triangulation.signals.post_refinement_on_cell(hex);
7100 }
7101 }
7102
7103 triangulation.faces->quads.clear_user_data();
7104
7105 return cells_with_distorted_children;
7106 }
7107
7112 template <int spacedim>
7115 const bool check_for_distorted_cells)
7116 {
7117 const unsigned int dim = 3;
7118
7119 {
7120 bool flag_isotropic_mesh = true;
7122 cell = triangulation.begin(),
7123 endc = triangulation.end();
7124 for (; cell != endc; ++cell)
7125 if (cell->used())
7126 if (triangulation.get_anisotropic_refinement_flag() ||
7127 cell->refine_flag_set() == RefinementCase<dim>::cut_x ||
7128 cell->refine_flag_set() == RefinementCase<dim>::cut_y ||
7129 cell->refine_flag_set() == RefinementCase<dim>::cut_z ||
7130 cell->refine_flag_set() == RefinementCase<dim>::cut_xy ||
7131 cell->refine_flag_set() == RefinementCase<dim>::cut_xz ||
7132 cell->refine_flag_set() == RefinementCase<dim>::cut_yz)
7133 {
7134 flag_isotropic_mesh = false;
7135 break;
7136 }
7137
7138 if (flag_isotropic_mesh)
7139 return execute_refinement_isotropic(triangulation,
7140 check_for_distorted_cells);
7141 }
7142
7143 // this function probably also works for spacedim>3 but it
7144 // isn't tested. it will probably be necessary to pull new
7145 // vertices onto the manifold just as we do for the other
7146 // functions above.
7147 Assert(spacedim == 3, ExcNotImplemented());
7148
7149 // Check whether a new level is needed. We have to check for
7150 // this on the highest level only
7151 for (const auto &cell : triangulation.active_cell_iterators_on_level(
7152 triangulation.levels.size() - 1))
7153 if (cell->refine_flag_set())
7154 {
7155 triangulation.levels.push_back(
7156 std::make_unique<
7158 break;
7159 }
7160
7161
7162 // first clear user flags for quads and lines; we're going to
7163 // use them to flag which lines and quads need refinement
7164 triangulation.faces->quads.clear_user_data();
7165
7168 line != triangulation.end_line();
7169 ++line)
7170 line->clear_user_flag();
7173 quad != triangulation.end_quad();
7174 ++quad)
7175 quad->clear_user_flag();
7176
7177 // create an array of face refine cases. User indices of faces
7178 // will be set to values corresponding with indices in this
7179 // array.
7180 const RefinementCase<dim - 1> face_refinement_cases[4] = {
7181 RefinementCase<dim - 1>::no_refinement,
7182 RefinementCase<dim - 1>::cut_x,
7183 RefinementCase<dim - 1>::cut_y,
7184 RefinementCase<dim - 1>::cut_xy};
7185
7186 // check how much space is needed on every level. We need not
7187 // check the highest level since either
7188 // - on the highest level no cells are flagged for refinement
7189 // - there are, but prepare_refinement added another empty
7190 // level which then is the highest level
7191
7192 // variables to hold the number of newly to be created
7193 // vertices, lines and quads. as these are stored globally,
7194 // declare them outside the loop over al levels. we need lines
7195 // and quads in pairs for refinement of old ones and lines and
7196 // quads, that can be stored as single ones, as they are newly
7197 // created in the inside of an existing cell
7198 unsigned int needed_vertices = 0;
7199 unsigned int needed_lines_single = 0;
7200 unsigned int needed_quads_single = 0;
7201 unsigned int needed_lines_pair = 0;
7202 unsigned int needed_quads_pair = 0;
7203 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
7204 {
7205 // count number of flagged cells on this level and compute
7206 // how many new vertices and new lines will be needed
7207 unsigned int new_cells = 0;
7208
7209 for (const auto &acell :
7210 triangulation.active_cell_iterators_on_level(level))
7211 if (acell->refine_flag_set())
7212 {
7213 RefinementCase<dim> ref_case = acell->refine_flag_set();
7214
7215 // now for interior vertices, lines and quads, which
7216 // are needed in any case
7217 if (ref_case == RefinementCase<dim>::cut_x ||
7218 ref_case == RefinementCase<dim>::cut_y ||
7219 ref_case == RefinementCase<dim>::cut_z)
7220 {
7221 ++needed_quads_single;
7222 new_cells += 2;
7223 triangulation.anisotropic_refinement = true;
7224 }
7225 else if (ref_case == RefinementCase<dim>::cut_xy ||
7226 ref_case == RefinementCase<dim>::cut_xz ||
7227 ref_case == RefinementCase<dim>::cut_yz)
7228 {
7229 ++needed_lines_single;
7230 needed_quads_single += 4;
7231 new_cells += 4;
7232 triangulation.anisotropic_refinement = true;
7233 }
7234 else if (ref_case == RefinementCase<dim>::cut_xyz)
7235 {
7236 ++needed_vertices;
7237 needed_lines_single += 6;
7238 needed_quads_single += 12;
7239 new_cells += 8;
7240 }
7241 else
7242 {
7243 // we should never get here
7245 }
7246
7247 // mark all faces for refinement; checking locally
7248 // if and how the neighbor would like to refine
7249 // these is difficult so we only flag them and after
7250 // visiting all cells, we decide which faces need
7251 // which refinement;
7252 for (const unsigned int face :
7254 {
7256 aface = acell->face(face);
7257 // get the RefineCase this faces has for the
7258 // given RefineCase of the cell
7259 RefinementCase<dim - 1> face_ref_case =
7261 ref_case,
7262 face,
7263 acell->face_orientation(face),
7264 acell->face_flip(face),
7265 acell->face_rotation(face));
7266 // only do something, if this face has to be
7267 // refined
7268 if (face_ref_case)
7269 {
7270 if (face_ref_case ==
7272 {
7273 if (aface->n_active_descendants() < 4)
7274 // we use user_flags to denote needed
7275 // isotropic refinement
7276 aface->set_user_flag();
7277 }
7278 else if (aface->refinement_case() != face_ref_case)
7279 // we use user_indices to denote needed
7280 // anisotropic refinement. note, that we
7281 // can have at most one anisotropic
7282 // refinement case for this face, as
7283 // otherwise prepare_refinement() would
7284 // have changed one of the cells to yield
7285 // isotropic refinement at this
7286 // face. therefore we set the user_index
7287 // uniquely
7288 {
7289 Assert(aface->refinement_case() ==
7291 dim - 1>::isotropic_refinement ||
7292 aface->refinement_case() ==
7295 aface->set_user_index(face_ref_case);
7296 }
7297 }
7298 } // for all faces
7299
7300 // flag all lines, that have to be refined
7301 for (unsigned int line = 0;
7302 line < GeometryInfo<dim>::lines_per_cell;
7303 ++line)
7305 line) &&
7306 !acell->line(line)->has_children())
7307 acell->line(line)->set_user_flag();
7308
7309 } // if refine_flag set and for all cells on this level
7310
7311
7312 // count number of used cells on the next higher level
7313 const unsigned int used_cells =
7314 std::count(triangulation.levels[level + 1]->cells.used.begin(),
7315 triangulation.levels[level + 1]->cells.used.end(),
7316 true);
7317
7318
7319 // reserve space for the used_cells cells already existing
7320 // on the next higher level as well as for the
7321 // 8*flagged_cells that will be created on that level
7322 reserve_space(*triangulation.levels[level + 1],
7323 used_cells + new_cells,
7324 3,
7325 spacedim);
7326 // reserve space for 8*flagged_cells new hexes on the next
7327 // higher level
7328 reserve_space(triangulation.levels[level + 1]->cells, new_cells);
7329 } // for all levels
7330 // now count the quads and lines which were flagged for
7331 // refinement
7334 quad != triangulation.end_quad();
7335 ++quad)
7336 {
7337 if (quad->user_flag_set())
7338 {
7339 // isotropic refinement: 1 interior vertex, 4 quads
7340 // and 4 interior lines. we store the interior lines
7341 // in pairs in case the face is already or will be
7342 // refined anisotropically
7343 needed_quads_pair += 4;
7344 needed_lines_pair += 4;
7345 needed_vertices += 1;
7346 }
7347 if (quad->user_index())
7348 {
7349 // anisotropic refinement: 1 interior
7350 // line and two quads
7351 needed_quads_pair += 2;
7352 needed_lines_single += 1;
7353 // there is a kind of complicated situation here which
7354 // requires our attention. if the quad is refined
7355 // isotropcally, two of the interior lines will get a
7356 // new mother line - the interior line of our
7357 // anisotropically refined quad. if those two lines
7358 // are not consecutive, we cannot do so and have to
7359 // replace them by two lines that are consecutive. we
7360 // try to avoid that situation, but it may happen
7361 // nevertheless through repeated refinement and
7362 // coarsening. thus we have to check here, as we will
7363 // need some additional space to store those new lines
7364 // in case we need them...
7365 if (quad->has_children())
7366 {
7367 Assert(quad->refinement_case() ==
7370 if ((face_refinement_cases[quad->user_index()] ==
7372 (quad->child(0)->line_index(1) + 1 !=
7373 quad->child(2)->line_index(1))) ||
7374 (face_refinement_cases[quad->user_index()] ==
7376 (quad->child(0)->line_index(3) + 1 !=
7377 quad->child(1)->line_index(3))))
7378 needed_lines_pair += 2;
7379 }
7380 }
7381 }
7382
7385 line != triangulation.end_line();
7386 ++line)
7387 if (line->user_flag_set())
7388 {
7389 needed_lines_pair += 2;
7390 needed_vertices += 1;
7391 }
7392
7393 // reserve space for needed_lines new lines stored in pairs
7394 reserve_space(triangulation.faces->lines,
7395 needed_lines_pair,
7396 needed_lines_single);
7397 // reserve space for needed_quads new quads stored in pairs
7399 needed_quads_pair,
7400 needed_quads_single);
7401 reserve_space(triangulation.faces->quads,
7402 needed_quads_pair,
7403 needed_quads_single);
7404
7405
7406 // add to needed vertices how many vertices are already in use
7407 needed_vertices += std::count(triangulation.vertices_used.begin(),
7408 triangulation.vertices_used.end(),
7409 true);
7410 // if we need more vertices: create them, if not: leave the
7411 // array as is, since shrinking is not really possible because
7412 // some of the vertices at the end may be in use
7413 if (needed_vertices > triangulation.vertices.size())
7414 {
7415 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
7416 triangulation.vertices_used.resize(needed_vertices, false);
7417 }
7418
7419
7420 //-----------------------------------------
7421 // Before we start with the actual refinement, we do some
7422 // sanity checks if in debug mode. especially, we try to catch
7423 // the notorious problem with lines being twice refined,
7424 // i.e. there are cells adjacent at one line ("around the
7425 // edge", but not at a face), with two cells differing by more
7426 // than one refinement level
7427 //
7428 // this check is very simple to implement here, since we have
7429 // all lines flagged if they shall be refined
7430#ifdef DEBUG
7431 for (const auto &cell : triangulation.active_cell_iterators())
7432 if (!cell->refine_flag_set())
7433 for (unsigned int line = 0;
7434 line < GeometryInfo<dim>::lines_per_cell;
7435 ++line)
7436 if (cell->line(line)->has_children())
7437 for (unsigned int c = 0; c < 2; ++c)
7438 Assert(cell->line(line)->child(c)->user_flag_set() == false,
7440#endif
7441
7442 //-----------------------------------------
7443 // Do refinement on every level
7444 //
7445 // To make life a bit easier, we first refine those lines and
7446 // quads that were flagged for refinement and then compose the
7447 // newly to be created cells.
7448 //
7449 // index of next unused vertex
7450 unsigned int next_unused_vertex = 0;
7451
7452 // first for lines
7453 {
7454 // only active objects can be refined further
7457 endl = triangulation.end_line();
7459 next_unused_line = triangulation.begin_raw_line();
7460
7461 for (; line != endl; ++line)
7462 if (line->user_flag_set())
7463 {
7464 // this line needs to be refined
7465
7466 // find the next unused vertex and set it
7467 // appropriately
7468 while (triangulation.vertices_used[next_unused_vertex] == true)
7469 ++next_unused_vertex;
7470 Assert(
7471 next_unused_vertex < triangulation.vertices.size(),
7472 ExcMessage(
7473 "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."));
7474 triangulation.vertices_used[next_unused_vertex] = true;
7475
7476 triangulation.vertices[next_unused_vertex] = line->center(true);
7477
7478 // now that we created the right point, make up the
7479 // two child lines (++ takes care of the end of the
7480 // vector)
7481 next_unused_line =
7482 triangulation.faces->lines.template next_free_pair_object<1>(
7484 Assert(next_unused_line.state() == IteratorState::valid,
7486
7487 // now we found two consecutive unused lines, such
7488 // that the children of a line will be consecutive.
7489 // then set the child pointer of the present line
7490 line->set_children(0, next_unused_line->index());
7491
7492 // set the two new lines
7494 children[2] = {next_unused_line, ++next_unused_line};
7495
7496 // some tests; if any of the iterators should be
7497 // invalid, then already dereferencing will fail
7498 AssertIsNotUsed(children[0]);
7499 AssertIsNotUsed(children[1]);
7500
7501 children[0]->set_bounding_object_indices(
7502 {line->vertex_index(0), next_unused_vertex});
7503 children[1]->set_bounding_object_indices(
7504 {next_unused_vertex, line->vertex_index(1)});
7505
7506 children[0]->set_used_flag();
7507 children[1]->set_used_flag();
7508 children[0]->clear_children();
7509 children[1]->clear_children();
7510 children[0]->clear_user_data();
7511 children[1]->clear_user_data();
7512 children[0]->clear_user_flag();
7513 children[1]->clear_user_flag();
7514
7515 children[0]->set_boundary_id_internal(line->boundary_id());
7516 children[1]->set_boundary_id_internal(line->boundary_id());
7517
7518 children[0]->set_manifold_id(line->manifold_id());
7519 children[1]->set_manifold_id(line->manifold_id());
7520
7521 // finally clear flag
7522 // indicating the need
7523 // for refinement
7524 line->clear_user_flag();
7525 }
7526 }
7527
7528
7529 //-------------------------------------
7530 // now refine marked quads
7531 //-------------------------------------
7532
7533 // here we encounter several cases:
7534
7535 // a) the quad is unrefined and shall be refined isotropically
7536
7537 // b) the quad is unrefined and shall be refined
7538 // anisotropically
7539
7540 // c) the quad is unrefined and shall be refined both
7541 // anisotropically and isotropically (this is reduced to case
7542 // b) and then case b) for the children again)
7543
7544 // d) the quad is refined anisotropically and shall be refined
7545 // isotropically (this is reduced to case b) for the
7546 // anisotropic children)
7547
7548 // e) the quad is refined isotropically and shall be refined
7549 // anisotropically (this is transformed to case c), however we
7550 // might have to renumber/rename children...)
7551
7552 // we need a loop in cases c) and d), as the anisotropic
7553 // children might have a lower index than the mother quad
7554 for (unsigned int loop = 0; loop < 2; ++loop)
7555 {
7556 // usually, only active objects can be refined
7557 // further. however, in cases d) and e) that is not true,
7558 // so we have to use 'normal' iterators here
7560 quad = triangulation.begin_quad(),
7561 endq = triangulation.end_quad();
7563 next_unused_line = triangulation.begin_raw_line();
7565 next_unused_quad = triangulation.begin_raw_quad();
7566
7567 for (; quad != endq; ++quad)
7568 {
7569 if (quad->user_index())
7570 {
7571 RefinementCase<dim - 1> aniso_quad_ref_case =
7572 face_refinement_cases[quad->user_index()];
7573 // there is one unlikely event here, where we
7574 // already have refind the face: if the face was
7575 // refined anisotropically and we want to refine
7576 // it isotropically, both children are flagged for
7577 // anisotropic refinement. however, if those
7578 // children were already flagged for anisotropic
7579 // refinement, they might already be processed and
7580 // refined.
7581 if (aniso_quad_ref_case == quad->refinement_case())
7582 continue;
7583
7584 Assert(quad->refinement_case() ==
7586 quad->refinement_case() ==
7589
7590 // this quad needs to be refined anisotropically
7591 Assert(quad->user_index() ==
7593 quad->user_index() ==
7596
7597 // make the new line interior to the quad
7599 new_line;
7600
7601 new_line =
7602 triangulation.faces->lines
7603 .template next_free_single_object<1>(triangulation);
7604 AssertIsNotUsed(new_line);
7605
7606 // first collect the
7607 // indices of the vertices:
7608 // *--1--*
7609 // | | |
7610 // | | | cut_x
7611 // | | |
7612 // *--0--*
7613 //
7614 // *-----*
7615 // | |
7616 // 0-----1 cut_y
7617 // | |
7618 // *-----*
7619 unsigned int vertex_indices[2];
7620 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
7621 {
7622 vertex_indices[0] =
7623 quad->line(2)->child(0)->vertex_index(1);
7624 vertex_indices[1] =
7625 quad->line(3)->child(0)->vertex_index(1);
7626 }
7627 else
7628 {
7629 vertex_indices[0] =
7630 quad->line(0)->child(0)->vertex_index(1);
7631 vertex_indices[1] =
7632 quad->line(1)->child(0)->vertex_index(1);
7633 }
7634
7635 new_line->set_bounding_object_indices(
7637 new_line->set_used_flag();
7638 new_line->clear_user_flag();
7639 new_line->clear_user_data();
7640 new_line->clear_children();
7641 new_line->set_boundary_id_internal(quad->boundary_id());
7642 new_line->set_manifold_id(quad->manifold_id());
7643
7644 // child 0 and 1 of a line are switched if the
7645 // line orientation is false. set up a miniature
7646 // table, indicating which child to take for line
7647 // orientations false and true. first index: child
7648 // index in standard orientation, second index:
7649 // line orientation
7650 const unsigned int index[2][2] = {
7651 {1, 0}, // child 0, line_orientation=false and true
7652 {0, 1}}; // child 1, line_orientation=false and true
7653
7654 // find some space (consecutive) for the two newly
7655 // to be created quads.
7657 new_quads[2];
7658
7659 next_unused_quad =
7660 triangulation.faces->quads
7661 .template next_free_pair_object<2>(triangulation);
7662 new_quads[0] = next_unused_quad;
7663 AssertIsNotUsed(new_quads[0]);
7664
7665 ++next_unused_quad;
7666 new_quads[1] = next_unused_quad;
7667 AssertIsNotUsed(new_quads[1]);
7668
7669 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
7670 {
7671 new_quads[0]->set_bounding_object_indices(
7672 {static_cast<int>(quad->line_index(0)),
7673 new_line->index(),
7674 quad->line(2)
7675 ->child(index[0][quad->line_orientation(2)])
7676 ->index(),
7677 quad->line(3)
7678 ->child(index[0][quad->line_orientation(3)])
7679 ->index()});
7680 new_quads[1]->set_bounding_object_indices(
7681 {new_line->index(),
7682 static_cast<int>(quad->line_index(1)),
7683 quad->line(2)
7684 ->child(index[1][quad->line_orientation(2)])
7685 ->index(),
7686 quad->line(3)
7687 ->child(index[1][quad->line_orientation(3)])
7688 ->index()});
7689 }
7690 else
7691 {
7692 new_quads[0]->set_bounding_object_indices(
7693 {quad->line(0)
7694 ->child(index[0][quad->line_orientation(0)])
7695 ->index(),
7696 quad->line(1)
7697 ->child(index[0][quad->line_orientation(1)])
7698 ->index(),
7699 static_cast<int>(quad->line_index(2)),
7700 new_line->index()});
7701 new_quads[1]->set_bounding_object_indices(
7702 {quad->line(0)
7703 ->child(index[1][quad->line_orientation(0)])
7704 ->index(),
7705 quad->line(1)
7706 ->child(index[1][quad->line_orientation(1)])
7707 ->index(),
7708 new_line->index(),
7709 static_cast<int>(quad->line_index(3))});
7710 }
7711
7712 for (const auto &new_quad : new_quads)
7713 {
7714 new_quad->set_used_flag();
7715 new_quad->clear_user_flag();
7716 new_quad->clear_user_data();
7717 new_quad->clear_children();
7718 new_quad->set_boundary_id_internal(quad->boundary_id());
7719 new_quad->set_manifold_id(quad->manifold_id());
7720 // set all line orientations to true, change
7721 // this after the loop, as we have to consider
7722 // different lines for each child
7723 for (unsigned int j = 0;
7724 j < GeometryInfo<dim>::lines_per_face;
7725 ++j)
7726 new_quad->set_line_orientation(j, true);
7727 }
7728 // now set the line orientation of children of
7729 // outer lines correctly, the lines in the
7730 // interior of the refined quad are automatically
7731 // oriented conforming to the standard
7732 new_quads[0]->set_line_orientation(
7733 0, quad->line_orientation(0));
7734 new_quads[0]->set_line_orientation(
7735 2, quad->line_orientation(2));
7736 new_quads[1]->set_line_orientation(
7737 1, quad->line_orientation(1));
7738 new_quads[1]->set_line_orientation(
7739 3, quad->line_orientation(3));
7740 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
7741 {
7742 new_quads[0]->set_line_orientation(
7743 3, quad->line_orientation(3));
7744 new_quads[1]->set_line_orientation(
7745 2, quad->line_orientation(2));
7746 }
7747 else
7748 {
7749 new_quads[0]->set_line_orientation(
7750 1, quad->line_orientation(1));
7751 new_quads[1]->set_line_orientation(
7752 0, quad->line_orientation(0));
7753 }
7754
7755 // test, whether this face is refined
7756 // isotropically already. if so, set the correct
7757 // children pointers.
7758 if (quad->refinement_case() ==
7759 RefinementCase<dim - 1>::cut_xy)
7760 {
7761 // we will put a new refinemnt level of
7762 // anisotropic refinement between the
7763 // unrefined and isotropically refined quad
7764 // ending up with the same fine quads but
7765 // introducing anisotropically refined ones as
7766 // children of the unrefined quad and mother
7767 // cells of the original fine ones.
7768
7769 // this process includes the creation of a new
7770 // middle line which we will assign as the
7771 // mother line of two of the existing inner
7772 // lines. If those inner lines are not
7773 // consecutive in memory, we won't find them
7774 // later on, so we have to create new ones
7775 // instead and replace all occurrences of the
7776 // old ones with those new ones. As this is
7777 // kind of ugly, we hope we don't have to do
7778 // it often...
7780 old_child[2];
7781 if (aniso_quad_ref_case ==
7783 {
7784 old_child[0] = quad->child(0)->line(1);
7785 old_child[1] = quad->child(2)->line(1);
7786 }
7787 else
7788 {
7789 Assert(aniso_quad_ref_case ==
7792
7793 old_child[0] = quad->child(0)->line(3);
7794 old_child[1] = quad->child(1)->line(3);
7795 }
7796
7797 if (old_child[0]->index() + 1 != old_child[1]->index())
7798 {
7799 // this is exactly the ugly case we taked
7800 // about. so, no coimplaining, lets get
7801 // two new lines and copy all info
7802 typename Triangulation<dim,
7803 spacedim>::raw_line_iterator
7804 new_child[2];
7805
7806 new_child[0] = new_child[1] =
7807 triangulation.faces->lines
7808 .template next_free_pair_object<1>(
7810 ++new_child[1];
7811
7812 new_child[0]->set_used_flag();
7813 new_child[1]->set_used_flag();
7814
7815 const int old_index_0 = old_child[0]->index(),
7816 old_index_1 = old_child[1]->index(),
7817 new_index_0 = new_child[0]->index(),
7818 new_index_1 = new_child[1]->index();
7819
7820 // loop over all quads and replace the old
7821 // lines
7822 for (unsigned int q = 0;
7823 q < triangulation.faces->quads.n_objects();
7824 ++q)
7825 for (unsigned int l = 0;
7826 l < GeometryInfo<dim>::lines_per_face;
7827 ++l)
7828 {
7829 const int this_index =
7830 triangulation.faces->quads
7831 .get_bounding_object_indices(q)[l];
7832 if (this_index == old_index_0)
7833 triangulation.faces->quads
7834 .get_bounding_object_indices(q)[l] =
7835 new_index_0;
7836 else if (this_index == old_index_1)
7837 triangulation.faces->quads
7838 .get_bounding_object_indices(q)[l] =
7839 new_index_1;
7840 }
7841 // now we have to copy all information of
7842 // the two lines
7843 for (unsigned int i = 0; i < 2; ++i)
7844 {
7845 Assert(!old_child[i]->has_children(),
7847
7848 new_child[i]->set_bounding_object_indices(
7849 {old_child[i]->vertex_index(0),
7850 old_child[i]->vertex_index(1)});
7851 new_child[i]->set_boundary_id_internal(
7852 old_child[i]->boundary_id());
7853 new_child[i]->set_manifold_id(
7854 old_child[i]->manifold_id());
7855 new_child[i]->set_user_index(
7856 old_child[i]->user_index());
7857 if (old_child[i]->user_flag_set())
7858 new_child[i]->set_user_flag();
7859 else
7860 new_child[i]->clear_user_flag();
7861
7862 new_child[i]->clear_children();
7863
7864 old_child[i]->clear_user_flag();
7865 old_child[i]->clear_user_index();
7866 old_child[i]->clear_used_flag();
7867 }
7868 }
7869 // now that we cared about the lines, go on
7870 // with the quads themselves, where we might
7871 // encounter similar situations...
7872 if (aniso_quad_ref_case ==
7874 {
7875 new_line->set_children(
7876 0, quad->child(0)->line_index(1));
7877 Assert(new_line->child(1) ==
7878 quad->child(2)->line(1),
7880 // now evereything is quite
7881 // complicated. we have the children
7882 // numbered according to
7883 //
7884 // *---*---*
7885 // |n+2|n+3|
7886 // *---*---*
7887 // | n |n+1|
7888 // *---*---*
7889 //
7890 // from the original isotropic
7891 // refinement. we have to reorder them as
7892 //
7893 // *---*---*
7894 // |n+1|n+3|
7895 // *---*---*
7896 // | n |n+2|
7897 // *---*---*
7898 //
7899 // such that n and n+1 are consecutive
7900 // children of m and n+2 and n+3 are
7901 // consecutive children of m+1, where m
7902 // and m+1 are given as in
7903 //
7904 // *---*---*
7905 // | | |
7906 // | m |m+1|
7907 // | | |
7908 // *---*---*
7909 //
7910 // this is a bit ugly, of course: loop
7911 // over all cells on all levels and look
7912 // for faces n+1 (switch_1) and n+2
7913 // (switch_2).
7914 const typename Triangulation<dim, spacedim>::
7915 quad_iterator switch_1 = quad->child(1),
7916 switch_2 = quad->child(2);
7917 const int switch_1_index = switch_1->index();
7918 const int switch_2_index = switch_2->index();
7919 for (unsigned int l = 0;
7920 l < triangulation.levels.size();
7921 ++l)
7922 for (unsigned int h = 0;
7923 h <
7924 triangulation.levels[l]->cells.n_objects();
7925 ++h)
7926 for (const unsigned int q :
7928 {
7929 const int face_index =
7931 ->cells.get_bounding_object_indices(
7932 h)[q];
7933 if (face_index == switch_1_index)
7934 triangulation.levels[l]
7935 ->cells.get_bounding_object_indices(
7936 h)[q] = switch_2_index;
7937 else if (face_index == switch_2_index)
7938 triangulation.levels[l]
7939 ->cells.get_bounding_object_indices(
7940 h)[q] = switch_1_index;
7941 }
7942 // now we have to copy all information of
7943 // the two quads
7944 const unsigned int switch_1_lines[4] = {
7945 switch_1->line_index(0),
7946 switch_1->line_index(1),
7947 switch_1->line_index(2),
7948 switch_1->line_index(3)};
7949 const bool switch_1_line_orientations[4] = {
7950 switch_1->line_orientation(0),
7951 switch_1->line_orientation(1),
7952 switch_1->line_orientation(2),
7953 switch_1->line_orientation(3)};
7954 const types::boundary_id switch_1_boundary_id =
7955 switch_1->boundary_id();
7956 const unsigned int switch_1_user_index =
7957 switch_1->user_index();
7958 const bool switch_1_user_flag =
7959 switch_1->user_flag_set();
7960 const RefinementCase<dim - 1>
7961 switch_1_refinement_case =
7962 switch_1->refinement_case();
7963 const int switch_1_first_child_pair =
7964 (switch_1_refinement_case ?
7965 switch_1->child_index(0) :
7966 -1);
7967 const int switch_1_second_child_pair =
7968 (switch_1_refinement_case ==
7969 RefinementCase<dim - 1>::cut_xy ?
7970 switch_1->child_index(2) :
7971 -1);
7972
7973 switch_1->set_bounding_object_indices(
7974 {switch_2->line_index(0),
7975 switch_2->line_index(1),
7976 switch_2->line_index(2),
7977 switch_2->line_index(3)});
7978 switch_1->set_line_orientation(
7979 0, switch_2->line_orientation(0));
7980 switch_1->set_line_orientation(
7981 1, switch_2->line_orientation(1));
7982 switch_1->set_line_orientation(
7983 2, switch_2->line_orientation(2));
7984 switch_1->set_line_orientation(
7985 3, switch_2->line_orientation(3));
7986 switch_1->set_boundary_id_internal(
7987 switch_2->boundary_id());
7988 switch_1->set_manifold_id(switch_2->manifold_id());
7989 switch_1->set_user_index(switch_2->user_index());
7990 if (switch_2->user_flag_set())
7991 switch_1->set_user_flag();
7992 else
7993 switch_1->clear_user_flag();
7994 switch_1->clear_refinement_case();
7995 switch_1->set_refinement_case(
7996 switch_2->refinement_case());
7997 switch_1->clear_children();
7998 if (switch_2->refinement_case())
7999 switch_1->set_children(0,
8000 switch_2->child_index(0));
8001 if (switch_2->refinement_case() ==
8002 RefinementCase<dim - 1>::cut_xy)
8003 switch_1->set_children(2,
8004 switch_2->child_index(2));
8005
8006 switch_2->set_bounding_object_indices(
8007 {switch_1_lines[0],
8008 switch_1_lines[1],
8009 switch_1_lines[2],
8010 switch_1_lines[3]});
8011 switch_2->set_line_orientation(
8012 0, switch_1_line_orientations[0]);
8013 switch_2->set_line_orientation(
8014 1, switch_1_line_orientations[1]);
8015 switch_2->set_line_orientation(
8016 2, switch_1_line_orientations[2]);
8017 switch_2->set_line_orientation(
8018 3, switch_1_line_orientations[3]);
8019 switch_2->set_boundary_id_internal(
8020 switch_1_boundary_id);
8021 switch_2->set_manifold_id(switch_1->manifold_id());
8022 switch_2->set_user_index(switch_1_user_index);
8023 if (switch_1_user_flag)
8024 switch_2->set_user_flag();
8025 else
8026 switch_2->clear_user_flag();
8027 switch_2->clear_refinement_case();
8028 switch_2->set_refinement_case(
8029 switch_1_refinement_case);
8030 switch_2->clear_children();
8031 switch_2->set_children(0,
8032 switch_1_first_child_pair);
8033 switch_2->set_children(2,
8034 switch_1_second_child_pair);
8035
8036 new_quads[0]->set_refinement_case(
8038 new_quads[0]->set_children(0, quad->child_index(0));
8039 new_quads[1]->set_refinement_case(
8041 new_quads[1]->set_children(0, quad->child_index(2));
8042 }
8043 else
8044 {
8045 new_quads[0]->set_refinement_case(
8047 new_quads[0]->set_children(0, quad->child_index(0));
8048 new_quads[1]->set_refinement_case(
8050 new_quads[1]->set_children(0, quad->child_index(2));
8051 new_line->set_children(
8052 0, quad->child(0)->line_index(3));
8053 Assert(new_line->child(1) ==
8054 quad->child(1)->line(3),
8056 }
8057 quad->clear_children();
8058 }
8059
8060 // note these quads as children to the present one
8061 quad->set_children(0, new_quads[0]->index());
8062
8063 quad->set_refinement_case(aniso_quad_ref_case);
8064
8065 // finally clear flag indicating the need for
8066 // refinement
8067 quad->clear_user_data();
8068 } // if (anisotropic refinement)
8069
8070 if (quad->user_flag_set())
8071 {
8072 // this quad needs to be refined isotropically
8073
8074 // first of all: we only get here in the first run
8075 // of the loop
8076 Assert(loop == 0, ExcInternalError());
8077
8078 // find the next unused vertex. we'll need this in
8079 // any case
8080 while (triangulation.vertices_used[next_unused_vertex] ==
8081 true)
8082 ++next_unused_vertex;
8083 Assert(
8084 next_unused_vertex < triangulation.vertices.size(),
8085 ExcMessage(
8086 "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."));
8087
8088 // now: if the quad is refined anisotropically
8089 // already, set the anisotropic refinement flag
8090 // for both children. Additionally, we have to
8091 // refine the inner line, as it is an outer line
8092 // of the two (anisotropic) children
8093 const RefinementCase<dim - 1> quad_ref_case =
8094 quad->refinement_case();
8095
8096 if (quad_ref_case == RefinementCase<dim - 1>::cut_x ||
8097 quad_ref_case == RefinementCase<dim - 1>::cut_y)
8098 {
8099 // set the 'opposite' refine case for children
8100 quad->child(0)->set_user_index(
8101 RefinementCase<dim - 1>::cut_xy - quad_ref_case);
8102 quad->child(1)->set_user_index(
8103 RefinementCase<dim - 1>::cut_xy - quad_ref_case);
8104 // refine the inner line
8106 middle_line;
8107 if (quad_ref_case == RefinementCase<dim - 1>::cut_x)
8108 middle_line = quad->child(0)->line(1);
8109 else
8110 middle_line = quad->child(0)->line(3);
8111
8112 // if the face has been refined
8113 // anisotropically in the last refinement step
8114 // it might be, that it is flagged already and
8115 // that the middle line is thus refined
8116 // already. if not create children.
8117 if (!middle_line->has_children())
8118 {
8119 // set the middle vertex
8120 // appropriately. double refinement of
8121 // quads can only happen in the interior
8122 // of the domain, so we need not care
8123 // about boundary quads here
8124 triangulation.vertices[next_unused_vertex] =
8125 middle_line->center(true);
8126 triangulation.vertices_used[next_unused_vertex] =
8127 true;
8128
8129 // now search a slot for the two
8130 // child lines
8131 next_unused_line =
8132 triangulation.faces->lines
8133 .template next_free_pair_object<1>(
8135
8136 // set the child pointer of the present
8137 // line
8138 middle_line->set_children(
8139 0, next_unused_line->index());
8140
8141 // set the two new lines
8142 const typename Triangulation<dim, spacedim>::
8143 raw_line_iterator children[2] = {
8144 next_unused_line, ++next_unused_line};
8145
8146 // some tests; if any of the iterators
8147 // should be invalid, then already
8148 // dereferencing will fail
8149 AssertIsNotUsed(children[0]);
8150 AssertIsNotUsed(children[1]);
8151
8152 children[0]->set_bounding_object_indices(
8153 {middle_line->vertex_index(0),
8154 next_unused_vertex});
8155 children[1]->set_bounding_object_indices(
8156 {next_unused_vertex,
8157 middle_line->vertex_index(1)});
8158
8159 children[0]->set_used_flag();
8160 children[1]->set_used_flag();
8161 children[0]->clear_children();
8162 children[1]->clear_children();
8163 children[0]->clear_user_data();
8164 children[1]->clear_user_data();
8165 children[0]->clear_user_flag();
8166 children[1]->clear_user_flag();
8167
8168 children[0]->set_boundary_id_internal(
8169 middle_line->boundary_id());
8170 children[1]->set_boundary_id_internal(
8171 middle_line->boundary_id());
8172
8173 children[0]->set_manifold_id(
8174 middle_line->manifold_id());
8175 children[1]->set_manifold_id(
8176 middle_line->manifold_id());
8177 }
8178 // now remove the flag from the quad and go to
8179 // the next quad, the actual refinement of the
8180 // quad takes place later on in this pass of
8181 // the loop or in the next one
8182 quad->clear_user_flag();
8183 continue;
8184 } // if (several refinement cases)
8185
8186 // if we got here, we have an unrefined quad and
8187 // have to do the usual work like in an purely
8188 // isotropic refinement
8189 Assert(quad_ref_case ==
8192
8193 // set the middle vertex appropriately: it might be that
8194 // the quad itself is not at the boundary, but that one of
8195 // its lines actually is. in this case, the newly created
8196 // vertices at the centers of the lines are not
8197 // necessarily the mean values of the adjacent vertices,
8198 // so do not compute the new vertex as the mean value of
8199 // the 4 vertices of the face, but rather as a weighted
8200 // mean value of the 8 vertices which we already have (the
8201 // four old ones, and the four ones inserted as middle
8202 // points for the four lines). summing up some more points
8203 // is generally cheaper than first asking whether one of
8204 // the lines is at the boundary
8205 //
8206 // note that the exact weights are chosen such as to
8207 // minimize the distortion of the four new quads from the
8208 // optimal shape. their description uses the formulas
8209 // underlying the TransfiniteInterpolationManifold
8210 // implementation
8211 triangulation.vertices[next_unused_vertex] =
8212 quad->center(true, true);
8213 triangulation.vertices_used[next_unused_vertex] = true;
8214
8215 // now that we created the right point, make up
8216 // the four lines interior to the quad (++ takes
8217 // care of the end of the vector)
8219 new_lines[4];
8220
8221 for (unsigned int i = 0; i < 4; ++i)
8222 {
8223 if (i % 2 == 0)
8224 // search a free pair of lines for 0. and
8225 // 2. line, so that two of them end up
8226 // together, which is necessary if later on
8227 // we want to refine the quad
8228 // anisotropically and the two lines end up
8229 // as children of new line
8230 next_unused_line =
8231 triangulation.faces->lines
8232 .template next_free_pair_object<1>(triangulation);
8233
8234 new_lines[i] = next_unused_line;
8235 ++next_unused_line;
8236
8237 AssertIsNotUsed(new_lines[i]);
8238 }
8239
8240 // set the data of the four lines. first collect
8241 // the indices of the five vertices:
8242 //
8243 // *--3--*
8244 // | | |
8245 // 0--4--1
8246 // | | |
8247 // *--2--*
8248 //
8249 // the lines are numbered as follows:
8250 //
8251 // *--*--*
8252 // | 1 |
8253 // *2-*-3*
8254 // | 0 |
8255 // *--*--*
8256
8257 const unsigned int vertex_indices[5] = {
8258 quad->line(0)->child(0)->vertex_index(1),
8259 quad->line(1)->child(0)->vertex_index(1),
8260 quad->line(2)->child(0)->vertex_index(1),
8261 quad->line(3)->child(0)->vertex_index(1),
8262 next_unused_vertex};
8263
8264 new_lines[0]->set_bounding_object_indices(
8266 new_lines[1]->set_bounding_object_indices(
8268 new_lines[2]->set_bounding_object_indices(
8270 new_lines[3]->set_bounding_object_indices(
8272
8273 for (const auto &new_line : new_lines)
8274 {
8275 new_line->set_used_flag();
8276 new_line->clear_user_flag();
8277 new_line->clear_user_data();
8278 new_line->clear_children();
8279 new_line->set_boundary_id_internal(quad->boundary_id());
8280 new_line->set_manifold_id(quad->manifold_id());
8281 }
8282
8283 // now for the quads. again, first collect some
8284 // data about the indices of the lines, with the
8285 // following numbering:
8286 //
8287 // .-6-.-7-.
8288 // 1 9 3
8289 // .-10.11-.
8290 // 0 8 2
8291 // .-4-.-5-.
8292
8293 // child 0 and 1 of a line are switched if the
8294 // line orientation is false. set up a miniature
8295 // table, indicating which child to take for line
8296 // orientations false and true. first index: child
8297 // index in standard orientation, second index:
8298 // line orientation
8299 const unsigned int index[2][2] = {
8300 {1, 0}, // child 0, line_orientation=false and true
8301 {0, 1}}; // child 1, line_orientation=false and true
8302
8303 const int line_indices[12] = {
8304 quad->line(0)
8305 ->child(index[0][quad->line_orientation(0)])
8306 ->index(),
8307 quad->line(0)
8308 ->child(index[1][quad->line_orientation(0)])
8309 ->index(),
8310 quad->line(1)
8311 ->child(index[0][quad->line_orientation(1)])
8312 ->index(),
8313 quad->line(1)
8314 ->child(index[1][quad->line_orientation(1)])
8315 ->index(),
8316 quad->line(2)
8317 ->child(index[0][quad->line_orientation(2)])
8318 ->index(),
8319 quad->line(2)
8320 ->child(index[1][quad->line_orientation(2)])
8321 ->index(),
8322 quad->line(3)
8323 ->child(index[0][quad->line_orientation(3)])
8324 ->index(),
8325 quad->line(3)
8326 ->child(index[1][quad->line_orientation(3)])
8327 ->index(),
8328 new_lines[0]->index(),
8329 new_lines[1]->index(),
8330 new_lines[2]->index(),
8331 new_lines[3]->index()};
8332
8333 // find some space (consecutive)
8334 // for the first two newly to be
8335 // created quads.
8337 new_quads[4];
8338
8339 next_unused_quad =
8340 triangulation.faces->quads
8341 .template next_free_pair_object<2>(triangulation);
8342
8343 new_quads[0] = next_unused_quad;
8344 AssertIsNotUsed(new_quads[0]);
8345
8346 ++next_unused_quad;
8347 new_quads[1] = next_unused_quad;
8348 AssertIsNotUsed(new_quads[1]);
8349
8350 next_unused_quad =
8351 triangulation.faces->quads
8352 .template next_free_pair_object<2>(triangulation);
8353 new_quads[2] = next_unused_quad;
8354 AssertIsNotUsed(new_quads[2]);
8355
8356 ++next_unused_quad;
8357 new_quads[3] = next_unused_quad;
8358 AssertIsNotUsed(new_quads[3]);
8359
8360 // note these quads as children to the present one
8361 quad->set_children(0, new_quads[0]->index());
8362 quad->set_children(2, new_quads[2]->index());
8363 quad->set_refinement_case(RefinementCase<2>::cut_xy);
8364
8365 new_quads[0]->set_bounding_object_indices(
8366 {line_indices[0],
8367 line_indices[8],
8368 line_indices[4],
8369 line_indices[10]});
8370 new_quads[1]->set_bounding_object_indices(
8371 {line_indices[8],
8372 line_indices[2],
8373 line_indices[5],
8374 line_indices[11]});
8375 new_quads[2]->set_bounding_object_indices(
8376 {line_indices[1],
8377 line_indices[9],
8378 line_indices[10],
8379 line_indices[6]});
8380 new_quads[3]->set_bounding_object_indices(
8381 {line_indices[9],
8382 line_indices[3],
8383 line_indices[11],
8384 line_indices[7]});
8385 for (const auto &new_quad : new_quads)
8386 {
8387 new_quad->set_used_flag();
8388 new_quad->clear_user_flag();
8389 new_quad->clear_user_data();
8390 new_quad->clear_children();
8391 new_quad->set_boundary_id_internal(quad->boundary_id());
8392 new_quad->set_manifold_id(quad->manifold_id());
8393 // set all line orientations to true, change
8394 // this after the loop, as we have to consider
8395 // different lines for each child
8396 for (unsigned int j = 0;
8397 j < GeometryInfo<dim>::lines_per_face;
8398 ++j)
8399 new_quad->set_line_orientation(j, true);
8400 }
8401 // now set the line orientation of children of
8402 // outer lines correctly, the lines in the
8403 // interior of the refined quad are automatically
8404 // oriented conforming to the standard
8405 new_quads[0]->set_line_orientation(
8406 0, quad->line_orientation(0));
8407 new_quads[0]->set_line_orientation(
8408 2, quad->line_orientation(2));
8409 new_quads[1]->set_line_orientation(
8410 1, quad->line_orientation(1));
8411 new_quads[1]->set_line_orientation(
8412 2, quad->line_orientation(2));
8413 new_quads[2]->set_line_orientation(
8414 0, quad->line_orientation(0));
8415 new_quads[2]->set_line_orientation(
8416 3, quad->line_orientation(3));
8417 new_quads[3]->set_line_orientation(
8418 1, quad->line_orientation(1));
8419 new_quads[3]->set_line_orientation(
8420 3, quad->line_orientation(3));
8421
8422 // finally clear flag indicating the need for
8423 // refinement
8424 quad->clear_user_flag();
8425 } // if (isotropic refinement)
8426 } // for all quads
8427 } // looped two times over all quads, all quads refined now
8428
8429 //---------------------------------
8430 // Now, finally, set up the new
8431 // cells
8432 //---------------------------------
8433
8435 cells_with_distorted_children;
8436
8437 for (unsigned int level = 0; level != triangulation.levels.size() - 1;
8438 ++level)
8439 {
8440 // only active objects can be refined further; remember
8441 // that we won't operate on the finest level, so
8442 // triangulation.begin_*(level+1) is allowed
8445 endh = triangulation.begin_active_hex(level + 1);
8447 next_unused_hex = triangulation.begin_raw_hex(level + 1);
8448
8449 for (; hex != endh; ++hex)
8450 if (hex->refine_flag_set())
8451 {
8452 // this hex needs to be refined
8453
8454 // clear flag indicating the need for refinement. do
8455 // it here already, since we can't do it anymore
8456 // once the cell has children
8457 const RefinementCase<dim> ref_case = hex->refine_flag_set();
8458 hex->clear_refine_flag();
8459 hex->set_refinement_case(ref_case);
8460
8461 // depending on the refine case we might have to
8462 // create additional vertices, lines and quads
8463 // interior of the hex before the actual children
8464 // can be set up.
8465
8466 // in a first step: reserve the needed space for
8467 // lines, quads and hexes and initialize them
8468 // correctly
8469
8470 unsigned int n_new_lines = 0;
8471 unsigned int n_new_quads = 0;
8472 unsigned int n_new_hexes = 0;
8473 switch (ref_case)
8474 {
8478 n_new_lines = 0;
8479 n_new_quads = 1;
8480 n_new_hexes = 2;
8481 break;
8485 n_new_lines = 1;
8486 n_new_quads = 4;
8487 n_new_hexes = 4;
8488 break;
8490 n_new_lines = 6;
8491 n_new_quads = 12;
8492 n_new_hexes = 8;
8493 break;
8494 default:
8496 break;
8497 }
8498
8499 // find some space for the newly to be created
8500 // interior lines and initialize them.
8501 std::vector<
8503 new_lines(n_new_lines);
8504 for (unsigned int i = 0; i < n_new_lines; ++i)
8505 {
8506 new_lines[i] =
8507 triangulation.faces->lines
8508 .template next_free_single_object<1>(triangulation);
8509
8510 AssertIsNotUsed(new_lines[i]);
8511 new_lines[i]->set_used_flag();
8512 new_lines[i]->clear_user_flag();
8513 new_lines[i]->clear_user_data();
8514 new_lines[i]->clear_children();
8515 // interior line
8516 new_lines[i]->set_boundary_id_internal(
8518 // they inherit geometry description of the hex they
8519 // belong to
8520 new_lines[i]->set_manifold_id(hex->manifold_id());
8521 }
8522
8523 // find some space for the newly to be created
8524 // interior quads and initialize them.
8525 std::vector<
8527 new_quads(n_new_quads);
8528 for (unsigned int i = 0; i < n_new_quads; ++i)
8529 {
8530 new_quads[i] =
8531 triangulation.faces->quads
8532 .template next_free_single_object<2>(triangulation);
8533
8534 AssertIsNotUsed(new_quads[i]);
8535 new_quads[i]->set_used_flag();
8536 new_quads[i]->clear_user_flag();
8537 new_quads[i]->clear_user_data();
8538 new_quads[i]->clear_children();
8539 // interior quad
8540 new_quads[i]->set_boundary_id_internal(
8542 // they inherit geometry description of the hex they
8543 // belong to
8544 new_quads[i]->set_manifold_id(hex->manifold_id());
8545 // set all line orientation flags to true by
8546 // default, change this afterwards, if necessary
8547 for (unsigned int j = 0;
8548 j < GeometryInfo<dim>::lines_per_face;
8549 ++j)
8550 new_quads[i]->set_line_orientation(j, true);
8551 }
8552
8553 types::subdomain_id subdomainid = hex->subdomain_id();
8554
8555 // find some space for the newly to be created hexes
8556 // and initialize them.
8557 std::vector<
8559 new_hexes(n_new_hexes);
8560 for (unsigned int i = 0; i < n_new_hexes; ++i)
8561 {
8562 if (i % 2 == 0)
8563 next_unused_hex =
8564 triangulation.levels[level + 1]->cells.next_free_hex(
8565 triangulation, level + 1);
8566 else
8567 ++next_unused_hex;
8568
8569 new_hexes[i] = next_unused_hex;
8570
8571 AssertIsNotUsed(new_hexes[i]);
8572 new_hexes[i]->set_used_flag();
8573 new_hexes[i]->clear_user_flag();
8574 new_hexes[i]->clear_user_data();
8575 new_hexes[i]->clear_children();
8576 // inherit material
8577 // properties
8578 new_hexes[i]->set_material_id(hex->material_id());
8579 new_hexes[i]->set_manifold_id(hex->manifold_id());
8580 new_hexes[i]->set_subdomain_id(subdomainid);
8581
8582 if (i % 2)
8583 new_hexes[i]->set_parent(hex->index());
8584 // set the face_orientation flag to true for all
8585 // faces initially, as this is the default value
8586 // which is true for all faces interior to the
8587 // hex. later on go the other way round and
8588 // reset faces that are at the boundary of the
8589 // mother cube
8590 //
8591 // the same is true for the face_flip and
8592 // face_rotation flags. however, the latter two
8593 // are set to false by default as this is the
8594 // standard value
8595 for (const unsigned int f :
8597 new_hexes[i]->set_combined_face_orientation(
8598 f,
8600 }
8601 // note these hexes as children to the present cell
8602 for (unsigned int i = 0; i < n_new_hexes / 2; ++i)
8603 hex->set_children(2 * i, new_hexes[2 * i]->index());
8604
8605 // we have to take into account whether the
8606 // different faces are oriented correctly or in the
8607 // opposite direction, so store that up front
8608
8609 // face_orientation
8610 const bool f_or[6] = {hex->face_orientation(0),
8611 hex->face_orientation(1),
8612 hex->face_orientation(2),
8613 hex->face_orientation(3),
8614 hex->face_orientation(4),
8615 hex->face_orientation(5)};
8616
8617 // face_flip
8618 const bool f_fl[6] = {hex->face_flip(0),
8619 hex->face_flip(1),
8620 hex->face_flip(2),
8621 hex->face_flip(3),
8622 hex->face_flip(4),
8623 hex->face_flip(5)};
8624
8625 // face_rotation
8626 const bool f_ro[6] = {hex->face_rotation(0),
8627 hex->face_rotation(1),
8628 hex->face_rotation(2),
8629 hex->face_rotation(3),
8630 hex->face_rotation(4),
8631 hex->face_rotation(5)};
8632
8633 // combined orientation
8634 const unsigned char f_co[6] = {
8635 hex->combined_face_orientation(0),
8636 hex->combined_face_orientation(1),
8637 hex->combined_face_orientation(2),
8638 hex->combined_face_orientation(3),
8639 hex->combined_face_orientation(4),
8640 hex->combined_face_orientation(5)};
8641
8642 // little helper table, indicating, whether the
8643 // child with index 0 or with index 1 can be found
8644 // at the standard origin of an anisotropically
8645 // refined quads in real orientation index 1:
8646 // (RefineCase - 1) index 2: face_flip
8647
8648 // index 3: face rotation
8649 // note: face orientation has no influence
8650 const unsigned int child_at_origin[2][2][2] = {
8651 {{0, 0}, // RefinementCase<dim>::cut_x, face_flip=false,
8652 // face_rotation=false and true
8653 {1, 1}}, // RefinementCase<dim>::cut_x, face_flip=true,
8654 // face_rotation=false and true
8655 {{0, 1}, // RefinementCase<dim>::cut_y, face_flip=false,
8656 // face_rotation=false and true
8657 {1, 0}}}; // RefinementCase<dim>::cut_y, face_flip=true,
8658 // face_rotation=false and true
8659
8660 //-------------------------------------
8661 //
8662 // in the following we will do the same thing for
8663 // each refinement case: create a new vertex (if
8664 // needed), create new interior lines (if needed),
8665 // create new interior quads and afterwards build
8666 // the children hexes out of these and the existing
8667 // subfaces of the outer quads (which have been
8668 // created above). However, even if the steps are
8669 // quite similar, the actual work strongly depends
8670 // on the actual refinement case. therefore, we use
8671 // separate blocks of code for each of these cases,
8672 // which hopefully increases the readability to some
8673 // extend.
8674
8675 switch (ref_case)
8676 {
8678 {
8679 //----------------------------
8680 //
8681 // RefinementCase<dim>::cut_x
8682 //
8683 // the refined cube will look
8684 // like this:
8685 //
8686 // *----*----*
8687 // / / /|
8688 // / / / |
8689 // / / / |
8690 // *----*----* |
8691 // | | | |
8692 // | | | *
8693 // | | | /
8694 // | | | /
8695 // | | |/
8696 // *----*----*
8697 //
8698 // again, first collect some data about the
8699 // indices of the lines, with the following
8700 // numbering:
8701
8702 // face 2: front plane
8703 // (note: x,y exchanged)
8704 // *---*---*
8705 // | | |
8706 // | 0 |
8707 // | | |
8708 // *---*---*
8709 // m0
8710 // face 3: back plane
8711 // (note: x,y exchanged)
8712 // m1
8713 // *---*---*
8714 // | | |
8715 // | 1 |
8716 // | | |
8717 // *---*---*
8718 // face 4: bottom plane
8719 // *---*---*
8720 // / / /
8721 // / 2 /
8722 // / / /
8723 // *---*---*
8724 // m0
8725 // face 5: top plane
8726 // m1
8727 // *---*---*
8728 // / / /
8729 // / 3 /
8730 // / / /
8731 // *---*---*
8732
8733 // set up a list of line iterators first. from
8734 // this, construct lists of line_indices and
8735 // line orientations later on
8736 const typename Triangulation<dim, spacedim>::
8737 raw_line_iterator lines[4] = {
8738 hex->face(2)->child(0)->line(
8739 (hex->face(2)->refinement_case() ==
8741 1 :
8742 3), // 0
8743 hex->face(3)->child(0)->line(
8744 (hex->face(3)->refinement_case() ==
8746 1 :
8747 3), // 1
8748 hex->face(4)->child(0)->line(
8749 (hex->face(4)->refinement_case() ==
8751 1 :
8752 3), // 2
8753 hex->face(5)->child(0)->line(
8754 (hex->face(5)->refinement_case() ==
8756 1 :
8757 3) // 3
8758 };
8759
8760 unsigned int line_indices[4];
8761 for (unsigned int i = 0; i < 4; ++i)
8762 line_indices[i] = lines[i]->index();
8763
8764 // the orientation of lines for the inner quads
8765 // is quite tricky. as these lines are newly
8766 // created ones and thus have no parents, they
8767 // cannot inherit this property. set up an array
8768 // and fill it with the respective values
8769 bool line_orientation[4];
8770
8771 // the middle vertex marked as m0 above is the
8772 // start vertex for lines 0 and 2 in standard
8773 // orientation, whereas m1 is the end vertex of
8774 // lines 1 and 3 in standard orientation
8775 const unsigned int middle_vertices[2] = {
8776 hex->line(2)->child(0)->vertex_index(1),
8777 hex->line(7)->child(0)->vertex_index(1)};
8778
8779 for (unsigned int i = 0; i < 4; ++i)
8780 if (lines[i]->vertex_index(i % 2) ==
8781 middle_vertices[i % 2])
8782 line_orientation[i] = true;
8783 else
8784 {
8785 // it must be the other
8786 // way round then
8787 Assert(lines[i]->vertex_index((i + 1) % 2) ==
8788 middle_vertices[i % 2],
8790 line_orientation[i] = false;
8791 }
8792
8793 // set up the new quad, line numbering is as
8794 // indicated above
8795 new_quads[0]->set_bounding_object_indices(
8796 {line_indices[0],
8797 line_indices[1],
8798 line_indices[2],
8799 line_indices[3]});
8800
8801 new_quads[0]->set_line_orientation(
8802 0, line_orientation[0]);
8803 new_quads[0]->set_line_orientation(
8804 1, line_orientation[1]);
8805 new_quads[0]->set_line_orientation(
8806 2, line_orientation[2]);
8807 new_quads[0]->set_line_orientation(
8808 3, line_orientation[3]);
8809
8810 // the quads are numbered as follows:
8811 //
8812 // planes in the interior of the old hex:
8813 //
8814 // *
8815 // /|
8816 // / | x
8817 // / | *-------* *---------*
8818 // * | | | / /
8819 // | 0 | | | / /
8820 // | * | | / /
8821 // | / *-------*y *---------*x
8822 // | /
8823 // |/
8824 // *
8825 //
8826 // children of the faces of the old hex
8827 //
8828 // *---*---* *---*---*
8829 // /| | | / / /|
8830 // / | | | / 9 / 10/ |
8831 // / | 5 | 6 | / / / |
8832 // * | | | *---*---* |
8833 // | 1 *---*---* | | | 2 *
8834 // | / / / | | | /
8835 // | / 7 / 8 / | 3 | 4 | /
8836 // |/ / / | | |/
8837 // *---*---* *---*---*
8838 //
8839 // note that we have to take care of the
8840 // orientation of faces.
8841 const int quad_indices[11] = {
8842 new_quads[0]->index(), // 0
8843
8844 hex->face(0)->index(), // 1
8845
8846 hex->face(1)->index(), // 2
8847
8848 hex->face(2)->child_index(
8849 child_at_origin[hex->face(2)->refinement_case() -
8850 1][f_fl[2]][f_ro[2]]), // 3
8851 hex->face(2)->child_index(
8852 1 -
8853 child_at_origin[hex->face(2)->refinement_case() -
8854 1][f_fl[2]][f_ro[2]]),
8855
8856 hex->face(3)->child_index(
8857 child_at_origin[hex->face(3)->refinement_case() -
8858 1][f_fl[3]][f_ro[3]]), // 5
8859 hex->face(3)->child_index(
8860 1 -
8861 child_at_origin[hex->face(3)->refinement_case() -
8862 1][f_fl[3]][f_ro[3]]),
8863
8864 hex->face(4)->child_index(
8865 child_at_origin[hex->face(4)->refinement_case() -
8866 1][f_fl[4]][f_ro[4]]), // 7
8867 hex->face(4)->child_index(
8868 1 -
8869 child_at_origin[hex->face(4)->refinement_case() -
8870 1][f_fl[4]][f_ro[4]]),
8871
8872 hex->face(5)->child_index(
8873 child_at_origin[hex->face(5)->refinement_case() -
8874 1][f_fl[5]][f_ro[5]]), // 9
8875 hex->face(5)->child_index(
8876 1 -
8877 child_at_origin[hex->face(5)->refinement_case() -
8878 1][f_fl[5]][f_ro[5]])
8879
8880 };
8881
8882 new_hexes[0]->set_bounding_object_indices(
8883 {quad_indices[1],
8884 quad_indices[0],
8885 quad_indices[3],
8886 quad_indices[5],
8887 quad_indices[7],
8888 quad_indices[9]});
8889 new_hexes[1]->set_bounding_object_indices(
8890 {quad_indices[0],
8891 quad_indices[2],
8892 quad_indices[4],
8893 quad_indices[6],
8894 quad_indices[8],
8895 quad_indices[10]});
8896 break;
8897 }
8898
8900 {
8901 //----------------------------
8902 //
8903 // RefinementCase<dim>::cut_y
8904 //
8905 // the refined cube will look like this:
8906 //
8907 // *---------*
8908 // / /|
8909 // *---------* |
8910 // / /| |
8911 // *---------* | |
8912 // | | | |
8913 // | | | *
8914 // | | |/
8915 // | | *
8916 // | |/
8917 // *---------*
8918 //
8919 // again, first collect some data about the
8920 // indices of the lines, with the following
8921 // numbering:
8922
8923 // face 0: left plane
8924 // *
8925 // /|
8926 // * |
8927 // /| |
8928 // * | |
8929 // | 0 |
8930 // | | *
8931 // | |/
8932 // | *m0
8933 // |/
8934 // *
8935 // face 1: right plane
8936 // *
8937 // /|
8938 // m1* |
8939 // /| |
8940 // * | |
8941 // | 1 |
8942 // | | *
8943 // | |/
8944 // | *
8945 // |/
8946 // *
8947 // face 4: bottom plane
8948 // *-------*
8949 // / /
8950 // m0*---2---*
8951 // / /
8952 // *-------*
8953 // face 5: top plane
8954 // *-------*
8955 // / /
8956 // *---3---*m1
8957 // / /
8958 // *-------*
8959
8960 // set up a list of line iterators first. from
8961 // this, construct lists of line_indices and
8962 // line orientations later on
8963 const typename Triangulation<dim, spacedim>::
8964 raw_line_iterator lines[4] = {
8965 hex->face(0)->child(0)->line(
8966 (hex->face(0)->refinement_case() ==
8968 1 :
8969 3), // 0
8970 hex->face(1)->child(0)->line(
8971 (hex->face(1)->refinement_case() ==
8973 1 :
8974 3), // 1
8975 hex->face(4)->child(0)->line(
8976 (hex->face(4)->refinement_case() ==
8978 1 :
8979 3), // 2
8980 hex->face(5)->child(0)->line(
8981 (hex->face(5)->refinement_case() ==
8983 1 :
8984 3) // 3
8985 };
8986
8987 unsigned int line_indices[4];
8988 for (unsigned int i = 0; i < 4; ++i)
8989 line_indices[i] = lines[i]->index();
8990
8991 // the orientation of lines for the inner quads
8992 // is quite tricky. as these lines are newly
8993 // created ones and thus have no parents, they
8994 // cannot inherit this property. set up an array
8995 // and fill it with the respective values
8996 bool line_orientation[4];
8997
8998 // the middle vertex marked as m0 above is the
8999 // start vertex for lines 0 and 2 in standard
9000 // orientation, whereas m1 is the end vertex of
9001 // lines 1 and 3 in standard orientation
9002 const unsigned int middle_vertices[2] = {
9003 hex->line(0)->child(0)->vertex_index(1),
9004 hex->line(5)->child(0)->vertex_index(1)};
9005
9006 for (unsigned int i = 0; i < 4; ++i)
9007 if (lines[i]->vertex_index(i % 2) ==
9008 middle_vertices[i % 2])
9009 line_orientation[i] = true;
9010 else
9011 {
9012 // it must be the other way round then
9013 Assert(lines[i]->vertex_index((i + 1) % 2) ==
9014 middle_vertices[i % 2],
9016 line_orientation[i] = false;
9017 }
9018
9019 // set up the new quad, line numbering is as
9020 // indicated above
9021 new_quads[0]->set_bounding_object_indices(
9022 {line_indices[2],
9023 line_indices[3],
9024 line_indices[0],
9025 line_indices[1]});
9026
9027 new_quads[0]->set_line_orientation(
9028 0, line_orientation[2]);
9029 new_quads[0]->set_line_orientation(
9030 1, line_orientation[3]);
9031 new_quads[0]->set_line_orientation(
9032 2, line_orientation[0]);
9033 new_quads[0]->set_line_orientation(
9034 3, line_orientation[1]);
9035
9036 // the quads are numbered as follows:
9037 //
9038 // planes in the interior of the old hex:
9039 //
9040 // *
9041 // /|
9042 // / | x
9043 // / | *-------* *---------*
9044 // * | | | / /
9045 // | | | 0 | / /
9046 // | * | | / /
9047 // | / *-------*y *---------*x
9048 // | /
9049 // |/
9050 // *
9051 //
9052 // children of the faces of the old hex
9053 //
9054 // *-------* *-------*
9055 // /| | / 10 /|
9056 // * | | *-------* |
9057 // /| | 6 | / 9 /| |
9058 // * |2| | *-------* |4|
9059 // | | *-------* | | | *
9060 // |1|/ 8 / | |3|/
9061 // | *-------* | 5 | *
9062 // |/ 7 / | |/
9063 // *-------* *-------*
9064 //
9065 // note that we have to take care of the
9066 // orientation of faces.
9067 const int quad_indices[11] = {
9068 new_quads[0]->index(), // 0
9069
9070 hex->face(0)->child_index(
9071 child_at_origin[hex->face(0)->refinement_case() -
9072 1][f_fl[0]][f_ro[0]]), // 1
9073 hex->face(0)->child_index(
9074 1 -
9075 child_at_origin[hex->face(0)->refinement_case() -
9076 1][f_fl[0]][f_ro[0]]),
9077
9078 hex->face(1)->child_index(
9079 child_at_origin[hex->face(1)->refinement_case() -
9080 1][f_fl[1]][f_ro[1]]), // 3
9081 hex->face(1)->child_index(
9082 1 -
9083 child_at_origin[hex->face(1)->refinement_case() -
9084 1][f_fl[1]][f_ro[1]]),
9085
9086 hex->face(2)->index(), // 5
9087
9088 hex->face(3)->index(), // 6
9089
9090 hex->face(4)->child_index(
9091 child_at_origin[hex->face(4)->refinement_case() -
9092 1][f_fl[4]][f_ro[4]]), // 7
9093 hex->face(4)->child_index(
9094 1 -
9095 child_at_origin[hex->face(4)->refinement_case() -
9096 1][f_fl[4]][f_ro[4]]),
9097
9098 hex->face(5)->child_index(
9099 child_at_origin[hex->face(5)->refinement_case() -
9100 1][f_fl[5]][f_ro[5]]), // 9
9101 hex->face(5)->child_index(
9102 1 -
9103 child_at_origin[hex->face(5)->refinement_case() -
9104 1][f_fl[5]][f_ro[5]])
9105
9106 };
9107
9108 new_hexes[0]->set_bounding_object_indices(
9109 {quad_indices[1],
9110 quad_indices[3],
9111 quad_indices[5],
9112 quad_indices[0],
9113 quad_indices[7],
9114 quad_indices[9]});
9115 new_hexes[1]->set_bounding_object_indices(
9116 {quad_indices[2],
9117 quad_indices[4],
9118 quad_indices[0],
9119 quad_indices[6],
9120 quad_indices[8],
9121 quad_indices[10]});
9122 break;
9123 }
9124
9126 {
9127 //----------------------------
9128 //
9129 // RefinementCase<dim>::cut_z
9130 //
9131 // the refined cube will look like this:
9132 //
9133 // *---------*
9134 // / /|
9135 // / / |
9136 // / / *
9137 // *---------* /|
9138 // | | / |
9139 // | |/ *
9140 // *---------* /
9141 // | | /
9142 // | |/
9143 // *---------*
9144 //
9145 // again, first collect some data about the
9146 // indices of the lines, with the following
9147 // numbering:
9148
9149 // face 0: left plane
9150 // *
9151 // /|
9152 // / |
9153 // / *
9154 // * /|
9155 // | 0 |
9156 // |/ *
9157 // m0* /
9158 // | /
9159 // |/
9160 // *
9161 // face 1: right plane
9162 // *
9163 // /|
9164 // / |
9165 // / *m1
9166 // * /|
9167 // | 1 |
9168 // |/ *
9169 // * /
9170 // | /
9171 // |/
9172 // *
9173 // face 2: front plane
9174 // (note: x,y exchanged)
9175 // *-------*
9176 // | |
9177 // m0*---2---*
9178 // | |
9179 // *-------*
9180 // face 3: back plane
9181 // (note: x,y exchanged)
9182 // *-------*
9183 // | |
9184 // *---3---*m1
9185 // | |
9186 // *-------*
9187
9188 // set up a list of line iterators first. from
9189 // this, construct lists of line_indices and
9190 // line orientations later on
9191 const typename Triangulation<dim, spacedim>::
9192 raw_line_iterator lines[4] = {
9193 hex->face(0)->child(0)->line(
9194 (hex->face(0)->refinement_case() ==
9196 1 :
9197 3), // 0
9198 hex->face(1)->child(0)->line(
9199 (hex->face(1)->refinement_case() ==
9201 1 :
9202 3), // 1
9203 hex->face(2)->child(0)->line(
9204 (hex->face(2)->refinement_case() ==
9206 1 :
9207 3), // 2
9208 hex->face(3)->child(0)->line(
9209 (hex->face(3)->refinement_case() ==
9211 1 :
9212 3) // 3
9213 };
9214
9215 unsigned int line_indices[4];
9216 for (unsigned int i = 0; i < 4; ++i)
9217 line_indices[i] = lines[i]->index();
9218
9219 // the orientation of lines for the inner quads
9220 // is quite tricky. as these lines are newly
9221 // created ones and thus have no parents, they
9222 // cannot inherit this property. set up an array
9223 // and fill it with the respective values
9224 bool line_orientation[4];
9225
9226 // the middle vertex marked as m0 above is the
9227 // start vertex for lines 0 and 2 in standard
9228 // orientation, whereas m1 is the end vertex of
9229 // lines 1 and 3 in standard orientation
9230 const unsigned int middle_vertices[2] = {
9231 middle_vertex_index<dim, spacedim>(hex->line(8)),
9232 middle_vertex_index<dim, spacedim>(hex->line(11))};
9233
9234 for (unsigned int i = 0; i < 4; ++i)
9235 if (lines[i]->vertex_index(i % 2) ==
9236 middle_vertices[i % 2])
9237 line_orientation[i] = true;
9238 else
9239 {
9240 // it must be the other way round then
9241 Assert(lines[i]->vertex_index((i + 1) % 2) ==
9242 middle_vertices[i % 2],
9244 line_orientation[i] = false;
9245 }
9246
9247 // set up the new quad, line numbering is as
9248 // indicated above
9249 new_quads[0]->set_bounding_object_indices(
9250 {line_indices[0],
9251 line_indices[1],
9252 line_indices[2],
9253 line_indices[3]});
9254
9255 new_quads[0]->set_line_orientation(
9256 0, line_orientation[0]);
9257 new_quads[0]->set_line_orientation(
9258 1, line_orientation[1]);
9259 new_quads[0]->set_line_orientation(
9260 2, line_orientation[2]);
9261 new_quads[0]->set_line_orientation(
9262 3, line_orientation[3]);
9263
9264 // the quads are numbered as follows:
9265 //
9266 // planes in the interior of the old hex:
9267 //
9268 // *
9269 // /|
9270 // / | x
9271 // / | *-------* *---------*
9272 // * | | | / /
9273 // | | | | / 0 /
9274 // | * | | / /
9275 // | / *-------*y *---------*x
9276 // | /
9277 // |/
9278 // *
9279 //
9280 // children of the faces of the old hex
9281 //
9282 // *---*---* *-------*
9283 // /| 8 | / /|
9284 // / | | / 10 / |
9285 // / *-------* / / *
9286 // * 2/| | *-------* 4/|
9287 // | / | 7 | | 6 | / |
9288 // |/1 *-------* | |/3 *
9289 // * / / *-------* /
9290 // | / 9 / | | /
9291 // |/ / | 5 |/
9292 // *-------* *---*---*
9293 //
9294 // note that we have to take care of the
9295 // orientation of faces.
9296 const int quad_indices[11] = {
9297 new_quads[0]->index(), // 0
9298
9299 hex->face(0)->child_index(
9300 child_at_origin[hex->face(0)->refinement_case() -
9301 1][f_fl[0]][f_ro[0]]), // 1
9302 hex->face(0)->child_index(
9303 1 -
9304 child_at_origin[hex->face(0)->refinement_case() -
9305 1][f_fl[0]][f_ro[0]]),
9306
9307 hex->face(1)->child_index(
9308 child_at_origin[hex->face(1)->refinement_case() -
9309 1][f_fl[1]][f_ro[1]]), // 3
9310 hex->face(1)->child_index(
9311 1 -
9312 child_at_origin[hex->face(1)->refinement_case() -
9313 1][f_fl[1]][f_ro[1]]),
9314
9315 hex->face(2)->child_index(
9316 child_at_origin[hex->face(2)->refinement_case() -
9317 1][f_fl[2]][f_ro[2]]), // 5
9318 hex->face(2)->child_index(
9319 1 -
9320 child_at_origin[hex->face(2)->refinement_case() -
9321 1][f_fl[2]][f_ro[2]]),
9322
9323 hex->face(3)->child_index(
9324 child_at_origin[hex->face(3)->refinement_case() -
9325 1][f_fl[3]][f_ro[3]]), // 7
9326 hex->face(3)->child_index(
9327 1 -
9328 child_at_origin[hex->face(3)->refinement_case() -
9329 1][f_fl[3]][f_ro[3]]),
9330
9331 hex->face(4)->index(), // 9
9332
9333 hex->face(5)->index() // 10
9334 };
9335
9336 new_hexes[0]->set_bounding_object_indices(
9337 {quad_indices[1],
9338 quad_indices[3],
9339 quad_indices[5],
9340 quad_indices[7],
9341 quad_indices[9],
9342 quad_indices[0]});
9343 new_hexes[1]->set_bounding_object_indices(
9344 {quad_indices[2],
9345 quad_indices[4],
9346 quad_indices[6],
9347 quad_indices[8],
9348 quad_indices[0],
9349 quad_indices[10]});
9350 break;
9351 }
9352
9354 {
9355 //----------------------------
9356 //
9357 // RefinementCase<dim>::cut_xy
9358 //
9359 // the refined cube will look like this:
9360 //
9361 // *----*----*
9362 // / / /|
9363 // *----*----* |
9364 // / / /| |
9365 // *----*----* | |
9366 // | | | | |
9367 // | | | | *
9368 // | | | |/
9369 // | | | *
9370 // | | |/
9371 // *----*----*
9372 //
9373
9374 // first, create the new internal line
9375 new_lines[0]->set_bounding_object_indices(
9376 {middle_vertex_index<dim, spacedim>(hex->face(4)),
9377 middle_vertex_index<dim, spacedim>(hex->face(5))});
9378
9379 // again, first collect some data about the
9380 // indices of the lines, with the following
9381 // numbering:
9382
9383 // face 0: left plane
9384 // *
9385 // /|
9386 // * |
9387 // /| |
9388 // * | |
9389 // | 0 |
9390 // | | *
9391 // | |/
9392 // | *
9393 // |/
9394 // *
9395 // face 1: right plane
9396 // *
9397 // /|
9398 // * |
9399 // /| |
9400 // * | |
9401 // | 1 |
9402 // | | *
9403 // | |/
9404 // | *
9405 // |/
9406 // *
9407 // face 2: front plane
9408 // (note: x,y exchanged)
9409 // *---*---*
9410 // | | |
9411 // | 2 |
9412 // | | |
9413 // *-------*
9414 // face 3: back plane
9415 // (note: x,y exchanged)
9416 // *---*---*
9417 // | | |
9418 // | 3 |
9419 // | | |
9420 // *---*---*
9421 // face 4: bottom plane
9422 // *---*---*
9423 // / 5 /
9424 // *-6-*-7-*
9425 // / 4 /
9426 // *---*---*
9427 // face 5: top plane
9428 // *---*---*
9429 // / 9 /
9430 // *10-*-11*
9431 // / 8 /
9432 // *---*---*
9433 // middle planes
9434 // *-------* *---*---*
9435 // / / | | |
9436 // / / | 12 |
9437 // / / | | |
9438 // *-------* *---*---*
9439
9440 // set up a list of line iterators first. from
9441 // this, construct lists of line_indices and
9442 // line orientations later on
9443 const typename Triangulation<
9444 dim,
9445 spacedim>::raw_line_iterator lines[13] = {
9446 hex->face(0)->child(0)->line(
9447 (hex->face(0)->refinement_case() ==
9449 1 :
9450 3), // 0
9451 hex->face(1)->child(0)->line(
9452 (hex->face(1)->refinement_case() ==
9454 1 :
9455 3), // 1
9456 hex->face(2)->child(0)->line(
9457 (hex->face(2)->refinement_case() ==
9459 1 :
9460 3), // 2
9461 hex->face(3)->child(0)->line(
9462 (hex->face(3)->refinement_case() ==
9464 1 :
9465 3), // 3
9466
9467 hex->face(4)
9468 ->isotropic_child(
9470 0, f_or[4], f_fl[4], f_ro[4]))
9471 ->line(
9473 1, f_or[4], f_fl[4], f_ro[4])), // 4
9474 hex->face(4)
9475 ->isotropic_child(
9477 3, f_or[4], f_fl[4], f_ro[4]))
9478 ->line(
9480 0, f_or[4], f_fl[4], f_ro[4])), // 5
9481 hex->face(4)
9482 ->isotropic_child(
9484 0, f_or[4], f_fl[4], f_ro[4]))
9485 ->line(
9487 3, f_or[4], f_fl[4], f_ro[4])), // 6
9488 hex->face(4)
9489 ->isotropic_child(
9491 3, f_or[4], f_fl[4], f_ro[4]))
9492 ->line(
9494 2, f_or[4], f_fl[4], f_ro[4])), // 7
9495
9496 hex->face(5)
9497 ->isotropic_child(
9499 0, f_or[5], f_fl[5], f_ro[5]))
9500 ->line(
9502 1, f_or[5], f_fl[5], f_ro[5])), // 8
9503 hex->face(5)
9504 ->isotropic_child(
9506 3, f_or[5], f_fl[5], f_ro[5]))
9507 ->line(
9509 0, f_or[5], f_fl[5], f_ro[5])), // 9
9510 hex->face(5)
9511 ->isotropic_child(
9513 0, f_or[5], f_fl[5], f_ro[5]))
9514 ->line(
9516 3, f_or[5], f_fl[5], f_ro[5])), // 10
9517 hex->face(5)
9518 ->isotropic_child(
9520 3, f_or[5], f_fl[5], f_ro[5]))
9521 ->line(
9523 2, f_or[5], f_fl[5], f_ro[5])), // 11
9524
9525 new_lines[0] // 12
9526 };
9527
9528 unsigned int line_indices[13];
9529 for (unsigned int i = 0; i < 13; ++i)
9530 line_indices[i] = lines[i]->index();
9531
9532 // the orientation of lines for the inner quads
9533 // is quite tricky. as these lines are newly
9534 // created ones and thus have no parents, they
9535 // cannot inherit this property. set up an array
9536 // and fill it with the respective values
9537 bool line_orientation[13];
9538
9539 // the middle vertices of the lines of our
9540 // bottom face
9541 const unsigned int middle_vertices[4] = {
9542 hex->line(0)->child(0)->vertex_index(1),
9543 hex->line(1)->child(0)->vertex_index(1),
9544 hex->line(2)->child(0)->vertex_index(1),
9545 hex->line(3)->child(0)->vertex_index(1),
9546 };
9547
9548 // note: for lines 0 to 3 the orientation of the
9549 // line is 'true', if vertex 0 is on the bottom
9550 // face
9551 for (unsigned int i = 0; i < 4; ++i)
9552 if (lines[i]->vertex_index(0) == middle_vertices[i])
9553 line_orientation[i] = true;
9554 else
9555 {
9556 // it must be the other way round then
9557 Assert(lines[i]->vertex_index(1) ==
9558 middle_vertices[i],
9560 line_orientation[i] = false;
9561 }
9562
9563 // note: for lines 4 to 11 (inner lines of the
9564 // outer quads) the following holds: the second
9565 // vertex of the even lines in standard
9566 // orientation is the vertex in the middle of
9567 // the quad, whereas for odd lines the first
9568 // vertex is the same middle vertex.
9569 for (unsigned int i = 4; i < 12; ++i)
9570 if (lines[i]->vertex_index((i + 1) % 2) ==
9571 middle_vertex_index<dim, spacedim>(
9572 hex->face(3 + i / 4)))
9573 line_orientation[i] = true;
9574 else
9575 {
9576 // it must be the other way
9577 // round then
9578 Assert(lines[i]->vertex_index(i % 2) ==
9579 (middle_vertex_index<dim, spacedim>(
9580 hex->face(3 + i / 4))),
9582 line_orientation[i] = false;
9583 }
9584 // for the last line the line orientation is
9585 // always true, since it was just constructed
9586 // that way
9587 line_orientation[12] = true;
9588
9589 // set up the 4 quads, numbered as follows (left
9590 // quad numbering, right line numbering
9591 // extracted from above)
9592 //
9593 // * *
9594 // /| 9|
9595 // * | * |
9596 // y/| | 8| 3
9597 // * |1| * | |
9598 // | | |x | 12|
9599 // |0| * | | *
9600 // | |/ 2 |5
9601 // | * | *
9602 // |/ |4
9603 // * *
9604 //
9605 // x
9606 // *---*---* *10-*-11*
9607 // | | | | | |
9608 // | 2 | 3 | 0 12 1
9609 // | | | | | |
9610 // *---*---*y *-6-*-7-*
9611
9612 new_quads[0]->set_bounding_object_indices(
9613 {line_indices[2],
9614 line_indices[12],
9615 line_indices[4],
9616 line_indices[8]});
9617 new_quads[1]->set_bounding_object_indices(
9618 {line_indices[12],
9619 line_indices[3],
9620 line_indices[5],
9621 line_indices[9]});
9622 new_quads[2]->set_bounding_object_indices(
9623 {line_indices[6],
9624 line_indices[10],
9625 line_indices[0],
9626 line_indices[12]});
9627 new_quads[3]->set_bounding_object_indices(
9628 {line_indices[7],
9629 line_indices[11],
9630 line_indices[12],
9631 line_indices[1]});
9632
9633 new_quads[0]->set_line_orientation(
9634 0, line_orientation[2]);
9635 new_quads[0]->set_line_orientation(
9636 2, line_orientation[4]);
9637 new_quads[0]->set_line_orientation(
9638 3, line_orientation[8]);
9639
9640 new_quads[1]->set_line_orientation(
9641 1, line_orientation[3]);
9642 new_quads[1]->set_line_orientation(
9643 2, line_orientation[5]);
9644 new_quads[1]->set_line_orientation(
9645 3, line_orientation[9]);
9646
9647 new_quads[2]->set_line_orientation(
9648 0, line_orientation[6]);
9649 new_quads[2]->set_line_orientation(
9650 1, line_orientation[10]);
9651 new_quads[2]->set_line_orientation(
9652 2, line_orientation[0]);
9653
9654 new_quads[3]->set_line_orientation(
9655 0, line_orientation[7]);
9656 new_quads[3]->set_line_orientation(
9657 1, line_orientation[11]);
9658 new_quads[3]->set_line_orientation(
9659 3, line_orientation[1]);
9660
9661 // the quads are numbered as follows:
9662 //
9663 // planes in the interior of the old hex:
9664 //
9665 // *
9666 // /|
9667 // * | x
9668 // /| | *---*---* *---------*
9669 // * |1| | | | / /
9670 // | | | | 2 | 3 | / /
9671 // |0| * | | | / /
9672 // | |/ *---*---*y *---------*x
9673 // | *
9674 // |/
9675 // *
9676 //
9677 // children of the faces of the old hex
9678 //
9679 // *---*---* *---*---*
9680 // /| | | /18 / 19/|
9681 // * |10 | 11| /---/---* |
9682 // /| | | | /16 / 17/| |
9683 // * |5| | | *---*---* |7|
9684 // | | *---*---* | | | | *
9685 // |4|/14 / 15/ | | |6|/
9686 // | *---/---/ | 8 | 9 | *
9687 // |/12 / 13/ | | |/
9688 // *---*---* *---*---*
9689 //
9690 // note that we have to take care of the
9691 // orientation of faces.
9692 const int quad_indices[20] = {
9693 new_quads[0]->index(), // 0
9694 new_quads[1]->index(),
9695 new_quads[2]->index(),
9696 new_quads[3]->index(),
9697
9698 hex->face(0)->child_index(
9699 child_at_origin[hex->face(0)->refinement_case() -
9700 1][f_fl[0]][f_ro[0]]), // 4
9701 hex->face(0)->child_index(
9702 1 -
9703 child_at_origin[hex->face(0)->refinement_case() -
9704 1][f_fl[0]][f_ro[0]]),
9705
9706 hex->face(1)->child_index(
9707 child_at_origin[hex->face(1)->refinement_case() -
9708 1][f_fl[1]][f_ro[1]]), // 6
9709 hex->face(1)->child_index(
9710 1 -
9711 child_at_origin[hex->face(1)->refinement_case() -
9712 1][f_fl[1]][f_ro[1]]),
9713
9714 hex->face(2)->child_index(
9715 child_at_origin[hex->face(2)->refinement_case() -
9716 1][f_fl[2]][f_ro[2]]), // 8
9717 hex->face(2)->child_index(
9718 1 -
9719 child_at_origin[hex->face(2)->refinement_case() -
9720 1][f_fl[2]][f_ro[2]]),
9721
9722 hex->face(3)->child_index(
9723 child_at_origin[hex->face(3)->refinement_case() -
9724 1][f_fl[3]][f_ro[3]]), // 10
9725 hex->face(3)->child_index(
9726 1 -
9727 child_at_origin[hex->face(3)->refinement_case() -
9728 1][f_fl[3]][f_ro[3]]),
9729
9730 hex->face(4)->isotropic_child_index(
9732 0, f_or[4], f_fl[4], f_ro[4])), // 12
9733 hex->face(4)->isotropic_child_index(
9735 1, f_or[4], f_fl[4], f_ro[4])),
9736 hex->face(4)->isotropic_child_index(
9738 2, f_or[4], f_fl[4], f_ro[4])),
9739 hex->face(4)->isotropic_child_index(
9741 3, f_or[4], f_fl[4], f_ro[4])),
9742
9743 hex->face(5)->isotropic_child_index(
9745 0, f_or[5], f_fl[5], f_ro[5])), // 16
9746 hex->face(5)->isotropic_child_index(
9748 1, f_or[5], f_fl[5], f_ro[5])),
9749 hex->face(5)->isotropic_child_index(
9751 2, f_or[5], f_fl[5], f_ro[5])),
9752 hex->face(5)->isotropic_child_index(
9754 3, f_or[5], f_fl[5], f_ro[5]))};
9755
9756 new_hexes[0]->set_bounding_object_indices(
9757 {quad_indices[4],
9758 quad_indices[0],
9759 quad_indices[8],
9760 quad_indices[2],
9761 quad_indices[12],
9762 quad_indices[16]});
9763 new_hexes[1]->set_bounding_object_indices(
9764 {quad_indices[0],
9765 quad_indices[6],
9766 quad_indices[9],
9767 quad_indices[3],
9768 quad_indices[13],
9769 quad_indices[17]});
9770 new_hexes[2]->set_bounding_object_indices(
9771 {quad_indices[5],
9772 quad_indices[1],
9773 quad_indices[2],
9774 quad_indices[10],
9775 quad_indices[14],
9776 quad_indices[18]});
9777 new_hexes[3]->set_bounding_object_indices(
9778 {quad_indices[1],
9779 quad_indices[7],
9780 quad_indices[3],
9781 quad_indices[11],
9782 quad_indices[15],
9783 quad_indices[19]});
9784 break;
9785 }
9786
9788 {
9789 //----------------------------
9790 //
9791 // RefinementCase<dim>::cut_xz
9792 //
9793 // the refined cube will look like this:
9794 //
9795 // *----*----*
9796 // / / /|
9797 // / / / |
9798 // / / / *
9799 // *----*----* /|
9800 // | | | / |
9801 // | | |/ *
9802 // *----*----* /
9803 // | | | /
9804 // | | |/
9805 // *----*----*
9806 //
9807
9808 // first, create the new internal line
9809 new_lines[0]->set_bounding_object_indices(
9810 {middle_vertex_index<dim, spacedim>(hex->face(2)),
9811 middle_vertex_index<dim, spacedim>(hex->face(3))});
9812
9813 // again, first collect some data about the
9814 // indices of the lines, with the following
9815 // numbering:
9816
9817 // face 0: left plane
9818 // *
9819 // /|
9820 // / |
9821 // / *
9822 // * /|
9823 // | 0 |
9824 // |/ *
9825 // * /
9826 // | /
9827 // |/
9828 // *
9829 // face 1: right plane
9830 // *
9831 // /|
9832 // / |
9833 // / *
9834 // * /|
9835 // | 1 |
9836 // |/ *
9837 // * /
9838 // | /
9839 // |/
9840 // *
9841 // face 2: front plane
9842 // (note: x,y exchanged)
9843 // *---*---*
9844 // | 5 |
9845 // *-6-*-7-*
9846 // | 4 |
9847 // *---*---*
9848 // face 3: back plane
9849 // (note: x,y exchanged)
9850 // *---*---*
9851 // | 9 |
9852 // *10-*-11*
9853 // | 8 |
9854 // *---*---*
9855 // face 4: bottom plane
9856 // *---*---*
9857 // / / /
9858 // / 2 /
9859 // / / /
9860 // *---*---*
9861 // face 5: top plane
9862 // *---*---*
9863 // / / /
9864 // / 3 /
9865 // / / /
9866 // *---*---*
9867 // middle planes
9868 // *---*---* *-------*
9869 // / / / | |
9870 // / 12 / | |
9871 // / / / | |
9872 // *---*---* *-------*
9873
9874 // set up a list of line iterators first. from
9875 // this, construct lists of line_indices and
9876 // line orientations later on
9877 const typename Triangulation<
9878 dim,
9879 spacedim>::raw_line_iterator lines[13] = {
9880 hex->face(0)->child(0)->line(
9881 (hex->face(0)->refinement_case() ==
9883 1 :
9884 3), // 0
9885 hex->face(1)->child(0)->line(
9886 (hex->face(1)->refinement_case() ==
9888 1 :
9889 3), // 1
9890 hex->face(4)->child(0)->line(
9891 (hex->face(4)->refinement_case() ==
9893 1 :
9894 3), // 2
9895 hex->face(5)->child(0)->line(
9896 (hex->face(5)->refinement_case() ==
9898 1 :
9899 3), // 3
9900
9901 hex->face(2)
9902 ->isotropic_child(
9904 0, f_or[2], f_fl[2], f_ro[2]))
9905 ->line(
9907 3, f_or[2], f_fl[2], f_ro[2])), // 4
9908 hex->face(2)
9909 ->isotropic_child(
9911 3, f_or[2], f_fl[2], f_ro[2]))
9912 ->line(
9914 2, f_or[2], f_fl[2], f_ro[2])), // 5
9915 hex->face(2)
9916 ->isotropic_child(
9918 0, f_or[2], f_fl[2], f_ro[2]))
9919 ->line(
9921 1, f_or[2], f_fl[2], f_ro[2])), // 6
9922 hex->face(2)
9923 ->isotropic_child(
9925 3, f_or[2], f_fl[2], f_ro[2]))
9926 ->line(
9928 0, f_or[2], f_fl[2], f_ro[2])), // 7
9929
9930 hex->face(3)
9931 ->isotropic_child(
9933 0, f_or[3], f_fl[3], f_ro[3]))
9934 ->line(
9936 3, f_or[3], f_fl[3], f_ro[3])), // 8
9937 hex->face(3)
9938 ->isotropic_child(
9940 3, f_or[3], f_fl[3], f_ro[3]))
9941 ->line(
9943 2, f_or[3], f_fl[3], f_ro[3])), // 9
9944 hex->face(3)
9945 ->isotropic_child(
9947 0, f_or[3], f_fl[3], f_ro[3]))
9948 ->line(
9950 1, f_or[3], f_fl[3], f_ro[3])), // 10
9951 hex->face(3)
9952 ->isotropic_child(
9954 3, f_or[3], f_fl[3], f_ro[3]))
9955 ->line(
9957 0, f_or[3], f_fl[3], f_ro[3])), // 11
9958
9959 new_lines[0] // 12
9960 };
9961
9962 unsigned int line_indices[13];
9963 for (unsigned int i = 0; i < 13; ++i)
9964 line_indices[i] = lines[i]->index();
9965
9966 // the orientation of lines for the inner quads
9967 // is quite tricky. as these lines are newly
9968 // created ones and thus have no parents, they
9969 // cannot inherit this property. set up an array
9970 // and fill it with the respective values
9971 bool line_orientation[13];
9972
9973 // the middle vertices of the
9974 // lines of our front face
9975 const unsigned int middle_vertices[4] = {
9976 hex->line(8)->child(0)->vertex_index(1),
9977 hex->line(9)->child(0)->vertex_index(1),
9978 hex->line(2)->child(0)->vertex_index(1),
9979 hex->line(6)->child(0)->vertex_index(1),
9980 };
9981
9982 // note: for lines 0 to 3 the orientation of the
9983 // line is 'true', if vertex 0 is on the front
9984 for (unsigned int i = 0; i < 4; ++i)
9985 if (lines[i]->vertex_index(0) == middle_vertices[i])
9986 line_orientation[i] = true;
9987 else
9988 {
9989 // it must be the other way round then
9990 Assert(lines[i]->vertex_index(1) ==
9991 middle_vertices[i],
9993 line_orientation[i] = false;
9994 }
9995
9996 // note: for lines 4 to 11 (inner lines of the
9997 // outer quads) the following holds: the second
9998 // vertex of the even lines in standard
9999 // orientation is the vertex in the middle of
10000 // the quad, whereas for odd lines the first
10001 // vertex is the same middle vertex.
10002 for (unsigned int i = 4; i < 12; ++i)
10003 if (lines[i]->vertex_index((i + 1) % 2) ==
10004 middle_vertex_index<dim, spacedim>(
10005 hex->face(1 + i / 4)))
10006 line_orientation[i] = true;
10007 else
10008 {
10009 // it must be the other way
10010 // round then
10011 Assert(lines[i]->vertex_index(i % 2) ==
10012 (middle_vertex_index<dim, spacedim>(
10013 hex->face(1 + i / 4))),
10015 line_orientation[i] = false;
10016 }
10017 // for the last line the line orientation is
10018 // always true, since it was just constructed
10019 // that way
10020 line_orientation[12] = true;
10021
10022 // set up the 4 quads, numbered as follows (left
10023 // quad numbering, right line numbering
10024 // extracted from above), the drawings denote
10025 // middle planes
10026 //
10027 // * *
10028 // /| /|
10029 // / | 3 9
10030 // y/ * / *
10031 // * 3/| * /|
10032 // | / |x 5 12|8
10033 // |/ * |/ *
10034 // * 2/ * /
10035 // | / 4 2
10036 // |/ |/
10037 // * *
10038 //
10039 // y
10040 // *----*----* *-10-*-11-*
10041 // / / / / / /
10042 // / 0 / 1 / 0 12 1
10043 // / / / / / /
10044 // *----*----*x *--6-*--7-*
10045
10046 new_quads[0]->set_bounding_object_indices(
10047 {line_indices[0],
10048 line_indices[12],
10049 line_indices[6],
10050 line_indices[10]});
10051 new_quads[1]->set_bounding_object_indices(
10052 {line_indices[12],
10053 line_indices[1],
10054 line_indices[7],
10055 line_indices[11]});
10056 new_quads[2]->set_bounding_object_indices(
10057 {line_indices[4],
10058 line_indices[8],
10059 line_indices[2],
10060 line_indices[12]});
10061 new_quads[3]->set_bounding_object_indices(
10062 {line_indices[5],
10063 line_indices[9],
10064 line_indices[12],
10065 line_indices[3]});
10066
10067 new_quads[0]->set_line_orientation(
10068 0, line_orientation[0]);
10069 new_quads[0]->set_line_orientation(
10070 2, line_orientation[6]);
10071 new_quads[0]->set_line_orientation(
10072 3, line_orientation[10]);
10073
10074 new_quads[1]->set_line_orientation(
10075 1, line_orientation[1]);
10076 new_quads[1]->set_line_orientation(
10077 2, line_orientation[7]);
10078 new_quads[1]->set_line_orientation(
10079 3, line_orientation[11]);
10080
10081 new_quads[2]->set_line_orientation(
10082 0, line_orientation[4]);
10083 new_quads[2]->set_line_orientation(
10084 1, line_orientation[8]);
10085 new_quads[2]->set_line_orientation(
10086 2, line_orientation[2]);
10087
10088 new_quads[3]->set_line_orientation(
10089 0, line_orientation[5]);
10090 new_quads[3]->set_line_orientation(
10091 1, line_orientation[9]);
10092 new_quads[3]->set_line_orientation(
10093 3, line_orientation[3]);
10094
10095 // the quads are numbered as follows:
10096 //
10097 // planes in the interior of the old hex:
10098 //
10099 // *
10100 // /|
10101 // / | x
10102 // /3 * *-------* *----*----*
10103 // * /| | | / / /
10104 // | / | | | / 0 / 1 /
10105 // |/ * | | / / /
10106 // * 2/ *-------*y *----*----*x
10107 // | /
10108 // |/
10109 // *
10110 //
10111 // children of the faces
10112 // of the old hex
10113 // *---*---* *---*---*
10114 // /|13 | 15| / / /|
10115 // / | | | /18 / 19/ |
10116 // / *---*---* / / / *
10117 // * 5/| | | *---*---* 7/|
10118 // | / |12 | 14| | 9 | 11| / |
10119 // |/4 *---*---* | | |/6 *
10120 // * / / / *---*---* /
10121 // | /16 / 17/ | | | /
10122 // |/ / / | 8 | 10|/
10123 // *---*---* *---*---*
10124 //
10125 // note that we have to take care of the
10126 // orientation of faces.
10127 const int quad_indices[20] = {
10128 new_quads[0]->index(), // 0
10129 new_quads[1]->index(),
10130 new_quads[2]->index(),
10131 new_quads[3]->index(),
10132
10133 hex->face(0)->child_index(
10134 child_at_origin[hex->face(0)->refinement_case() -
10135 1][f_fl[0]][f_ro[0]]), // 4
10136 hex->face(0)->child_index(
10137 1 -
10138 child_at_origin[hex->face(0)->refinement_case() -
10139 1][f_fl[0]][f_ro[0]]),
10140
10141 hex->face(1)->child_index(
10142 child_at_origin[hex->face(1)->refinement_case() -
10143 1][f_fl[1]][f_ro[1]]), // 6
10144 hex->face(1)->child_index(
10145 1 -
10146 child_at_origin[hex->face(1)->refinement_case() -
10147 1][f_fl[1]][f_ro[1]]),
10148
10149 hex->face(2)->isotropic_child_index(
10151 0, f_or[2], f_fl[2], f_ro[2])), // 8
10152 hex->face(2)->isotropic_child_index(
10154 1, f_or[2], f_fl[2], f_ro[2])),
10155 hex->face(2)->isotropic_child_index(
10157 2, f_or[2], f_fl[2], f_ro[2])),
10158 hex->face(2)->isotropic_child_index(
10160 3, f_or[2], f_fl[2], f_ro[2])),
10161
10162 hex->face(3)->isotropic_child_index(
10164 0, f_or[3], f_fl[3], f_ro[3])), // 12
10165 hex->face(3)->isotropic_child_index(
10167 1, f_or[3], f_fl[3], f_ro[3])),
10168 hex->face(3)->isotropic_child_index(
10170 2, f_or[3], f_fl[3], f_ro[3])),
10171 hex->face(3)->isotropic_child_index(
10173 3, f_or[3], f_fl[3], f_ro[3])),
10174
10175 hex->face(4)->child_index(
10176 child_at_origin[hex->face(4)->refinement_case() -
10177 1][f_fl[4]][f_ro[4]]), // 16
10178 hex->face(4)->child_index(
10179 1 -
10180 child_at_origin[hex->face(4)->refinement_case() -
10181 1][f_fl[4]][f_ro[4]]),
10182
10183 hex->face(5)->child_index(
10184 child_at_origin[hex->face(5)->refinement_case() -
10185 1][f_fl[5]][f_ro[5]]), // 18
10186 hex->face(5)->child_index(
10187 1 -
10188 child_at_origin[hex->face(5)->refinement_case() -
10189 1][f_fl[5]][f_ro[5]])};
10190
10191 // due to the exchange of x and y for the front
10192 // and back face, we order the children
10193 // according to
10194 //
10195 // *---*---*
10196 // | 1 | 3 |
10197 // *---*---*
10198 // | 0 | 2 |
10199 // *---*---*
10200 new_hexes[0]->set_bounding_object_indices(
10201 {quad_indices[4],
10202 quad_indices[2],
10203 quad_indices[8],
10204 quad_indices[12],
10205 quad_indices[16],
10206 quad_indices[0]});
10207 new_hexes[1]->set_bounding_object_indices(
10208 {quad_indices[5],
10209 quad_indices[3],
10210 quad_indices[9],
10211 quad_indices[13],
10212 quad_indices[0],
10213 quad_indices[18]});
10214 new_hexes[2]->set_bounding_object_indices(
10215 {quad_indices[2],
10216 quad_indices[6],
10217 quad_indices[10],
10218 quad_indices[14],
10219 quad_indices[17],
10220 quad_indices[1]});
10221 new_hexes[3]->set_bounding_object_indices(
10222 {quad_indices[3],
10223 quad_indices[7],
10224 quad_indices[11],
10225 quad_indices[15],
10226 quad_indices[1],
10227 quad_indices[19]});
10228 break;
10229 }
10230
10232 {
10233 //----------------------------
10234 //
10235 // RefinementCase<dim>::cut_yz
10236 //
10237 // the refined cube will look like this:
10238 //
10239 // *---------*
10240 // / /|
10241 // *---------* |
10242 // / /| |
10243 // *---------* |/|
10244 // | | * |
10245 // | |/| *
10246 // *---------* |/
10247 // | | *
10248 // | |/
10249 // *---------*
10250 //
10251
10252 // first, create the new
10253 // internal line
10254 new_lines[0]->set_bounding_object_indices(
10255
10256 {middle_vertex_index<dim, spacedim>(hex->face(0)),
10257 middle_vertex_index<dim, spacedim>(hex->face(1))});
10258
10259 // again, first collect some data about the
10260 // indices of the lines, with the following
10261 // numbering: (note that face 0 and 1 each are
10262 // shown twice for better readability)
10263
10264 // face 0: left plane
10265 // * *
10266 // /| /|
10267 // * | * |
10268 // /| * /| *
10269 // * 5/| * |7|
10270 // | * | | * |
10271 // |/| * |6| *
10272 // * 4/ * |/
10273 // | * | *
10274 // |/ |/
10275 // * *
10276 // face 1: right plane
10277 // * *
10278 // /| /|
10279 // * | * |
10280 // /| * /| *
10281 // * 9/| * |11
10282 // | * | | * |
10283 // |/| * |10 *
10284 // * 8/ * |/
10285 // | * | *
10286 // |/ |/
10287 // * *
10288 // face 2: front plane
10289 // (note: x,y exchanged)
10290 // *-------*
10291 // | |
10292 // *---0---*
10293 // | |
10294 // *-------*
10295 // face 3: back plane
10296 // (note: x,y exchanged)
10297 // *-------*
10298 // | |
10299 // *---1---*
10300 // | |
10301 // *-------*
10302 // face 4: bottom plane
10303 // *-------*
10304 // / /
10305 // *---2---*
10306 // / /
10307 // *-------*
10308 // face 5: top plane
10309 // *-------*
10310 // / /
10311 // *---3---*
10312 // / /
10313 // *-------*
10314 // middle planes
10315 // *-------* *-------*
10316 // / / | |
10317 // *---12--* | |
10318 // / / | |
10319 // *-------* *-------*
10320
10321 // set up a list of line iterators first. from
10322 // this, construct lists of line_indices and
10323 // line orientations later on
10324 const typename Triangulation<
10325 dim,
10326 spacedim>::raw_line_iterator lines[13] = {
10327 hex->face(2)->child(0)->line(
10328 (hex->face(2)->refinement_case() ==
10330 1 :
10331 3), // 0
10332 hex->face(3)->child(0)->line(
10333 (hex->face(3)->refinement_case() ==
10335 1 :
10336 3), // 1
10337 hex->face(4)->child(0)->line(
10338 (hex->face(4)->refinement_case() ==
10340 1 :
10341 3), // 2
10342 hex->face(5)->child(0)->line(
10343 (hex->face(5)->refinement_case() ==
10345 1 :
10346 3), // 3
10347
10348 hex->face(0)
10349 ->isotropic_child(
10351 0, f_or[0], f_fl[0], f_ro[0]))
10352 ->line(
10354 1, f_or[0], f_fl[0], f_ro[0])), // 4
10355 hex->face(0)
10356 ->isotropic_child(
10358 3, f_or[0], f_fl[0], f_ro[0]))
10359 ->line(
10361 0, f_or[0], f_fl[0], f_ro[0])), // 5
10362 hex->face(0)
10363 ->isotropic_child(
10365 0, f_or[0], f_fl[0], f_ro[0]))
10366 ->line(
10368 3, f_or[0], f_fl[0], f_ro[0])), // 6
10369 hex->face(0)
10370 ->isotropic_child(
10372 3, f_or[0], f_fl[0], f_ro[0]))
10373 ->line(
10375 2, f_or[0], f_fl[0], f_ro[0])), // 7
10376
10377 hex->face(1)
10378 ->isotropic_child(
10380 0, f_or[1], f_fl[1], f_ro[1]))
10381 ->line(
10383 1, f_or[1], f_fl[1], f_ro[1])), // 8
10384 hex->face(1)
10385 ->isotropic_child(
10387 3, f_or[1], f_fl[1], f_ro[1]))
10388 ->line(
10390 0, f_or[1], f_fl[1], f_ro[1])), // 9
10391 hex->face(1)
10392 ->isotropic_child(
10394 0, f_or[1], f_fl[1], f_ro[1]))
10395 ->line(
10397 3, f_or[1], f_fl[1], f_ro[1])), // 10
10398 hex->face(1)
10399 ->isotropic_child(
10401 3, f_or[1], f_fl[1], f_ro[1]))
10402 ->line(
10404 2, f_or[1], f_fl[1], f_ro[1])), // 11
10405
10406 new_lines[0] // 12
10407 };
10408
10409 unsigned int line_indices[13];
10410
10411 for (unsigned int i = 0; i < 13; ++i)
10412 line_indices[i] = lines[i]->index();
10413
10414 // the orientation of lines for the inner quads
10415 // is quite tricky. as these lines are newly
10416 // created ones and thus have no parents, they
10417 // cannot inherit this property. set up an array
10418 // and fill it with the respective values
10419 bool line_orientation[13];
10420
10421 // the middle vertices of the lines of our front
10422 // face
10423 const unsigned int middle_vertices[4] = {
10424 hex->line(8)->child(0)->vertex_index(1),
10425 hex->line(10)->child(0)->vertex_index(1),
10426 hex->line(0)->child(0)->vertex_index(1),
10427 hex->line(4)->child(0)->vertex_index(1),
10428 };
10429
10430 // note: for lines 0 to 3 the orientation of the
10431 // line is 'true', if vertex 0 is on the front
10432 for (unsigned int i = 0; i < 4; ++i)
10433 if (lines[i]->vertex_index(0) == middle_vertices[i])
10434 line_orientation[i] = true;
10435 else
10436 {
10437 // it must be the other way round then
10438 Assert(lines[i]->vertex_index(1) ==
10439 middle_vertices[i],
10441 line_orientation[i] = false;
10442 }
10443
10444 // note: for lines 4 to 11 (inner lines of the
10445 // outer quads) the following holds: the second
10446 // vertex of the even lines in standard
10447 // orientation is the vertex in the middle of
10448 // the quad, whereas for odd lines the first
10449 // vertex is the same middle vertex.
10450 for (unsigned int i = 4; i < 12; ++i)
10451 if (lines[i]->vertex_index((i + 1) % 2) ==
10452 middle_vertex_index<dim, spacedim>(
10453 hex->face(i / 4 - 1)))
10454 line_orientation[i] = true;
10455 else
10456 {
10457 // it must be the other way
10458 // round then
10459 Assert(lines[i]->vertex_index(i % 2) ==
10460 (middle_vertex_index<dim, spacedim>(
10461 hex->face(i / 4 - 1))),
10463 line_orientation[i] = false;
10464 }
10465 // for the last line the line orientation is
10466 // always true, since it was just constructed
10467 // that way
10468 line_orientation[12] = true;
10469
10470 // set up the 4 quads, numbered as follows (left
10471 // quad numbering, right line numbering
10472 // extracted from above)
10473 //
10474 // x
10475 // *-------* *---3---*
10476 // | 3 | 5 9
10477 // *-------* *---12--*
10478 // | 2 | 4 8
10479 // *-------*y *---2---*
10480 //
10481 // y
10482 // *---------* *----1----*
10483 // / 1 / 7 11
10484 // *---------* *----12---*
10485 // / 0 / 6 10
10486 // *---------*x *----0----*
10487
10488 new_quads[0]->set_bounding_object_indices(
10489 {line_indices[6],
10490 line_indices[10],
10491 line_indices[0],
10492 line_indices[12]});
10493 new_quads[1]->set_bounding_object_indices(
10494 {line_indices[7],
10495 line_indices[11],
10496 line_indices[12],
10497 line_indices[1]});
10498 new_quads[2]->set_bounding_object_indices(
10499 {line_indices[2],
10500 line_indices[12],
10501 line_indices[4],
10502 line_indices[8]});
10503 new_quads[3]->set_bounding_object_indices(
10504 {line_indices[12],
10505 line_indices[3],
10506 line_indices[5],
10507 line_indices[9]});
10508
10509 new_quads[0]->set_line_orientation(
10510 0, line_orientation[6]);
10511 new_quads[0]->set_line_orientation(
10512 1, line_orientation[10]);
10513 new_quads[0]->set_line_orientation(
10514 2, line_orientation[0]);
10515
10516 new_quads[1]->set_line_orientation(
10517 0, line_orientation[7]);
10518 new_quads[1]->set_line_orientation(
10519 1, line_orientation[11]);
10520 new_quads[1]->set_line_orientation(
10521 3, line_orientation[1]);
10522
10523 new_quads[2]->set_line_orientation(
10524 0, line_orientation[2]);
10525 new_quads[2]->set_line_orientation(
10526 2, line_orientation[4]);
10527 new_quads[2]->set_line_orientation(
10528 3, line_orientation[8]);
10529
10530 new_quads[3]->set_line_orientation(
10531 1, line_orientation[3]);
10532 new_quads[3]->set_line_orientation(
10533 2, line_orientation[5]);
10534 new_quads[3]->set_line_orientation(
10535 3, line_orientation[9]);
10536
10537 // the quads are numbered as follows:
10538 //
10539 // planes in the interior of the old hex:
10540 //
10541 // *
10542 // /|
10543 // / | x
10544 // / | *-------* *---------*
10545 // * | | 3 | / 1 /
10546 // | | *-------* *---------*
10547 // | * | 2 | / 0 /
10548 // | / *-------*y *---------*x
10549 // | /
10550 // |/
10551 // *
10552 //
10553 // children of the faces
10554 // of the old hex
10555 // *-------* *-------*
10556 // /| | / 19 /|
10557 // * | 15 | *-------* |
10558 // /|7*-------* / 18 /|11
10559 // * |/| | *-------* |/|
10560 // |6* | 14 | | 10* |
10561 // |/|5*-------* | 13 |/|9*
10562 // * |/ 17 / *-------* |/
10563 // |4*-------* | |8*
10564 // |/ 16 / | 12 |/
10565 // *-------* *-------*
10566 //
10567 // note that we have to take care of the
10568 // orientation of faces.
10569 const int quad_indices[20] = {
10570 new_quads[0]->index(), // 0
10571 new_quads[1]->index(),
10572 new_quads[2]->index(),
10573 new_quads[3]->index(),
10574
10575 hex->face(0)->isotropic_child_index(
10577 0, f_or[0], f_fl[0], f_ro[0])), // 4
10578 hex->face(0)->isotropic_child_index(
10580 1, f_or[0], f_fl[0], f_ro[0])),
10581 hex->face(0)->isotropic_child_index(
10583 2, f_or[0], f_fl[0], f_ro[0])),
10584 hex->face(0)->isotropic_child_index(
10586 3, f_or[0], f_fl[0], f_ro[0])),
10587
10588 hex->face(1)->isotropic_child_index(
10590 0, f_or[1], f_fl[1], f_ro[1])), // 8
10591 hex->face(1)->isotropic_child_index(
10593 1, f_or[1], f_fl[1], f_ro[1])),
10594 hex->face(1)->isotropic_child_index(
10596 2, f_or[1], f_fl[1], f_ro[1])),
10597 hex->face(1)->isotropic_child_index(
10599 3, f_or[1], f_fl[1], f_ro[1])),
10600
10601 hex->face(2)->child_index(
10602 child_at_origin[hex->face(2)->refinement_case() -
10603 1][f_fl[2]][f_ro[2]]), // 12
10604 hex->face(2)->child_index(
10605 1 -
10606 child_at_origin[hex->face(2)->refinement_case() -
10607 1][f_fl[2]][f_ro[2]]),
10608
10609 hex->face(3)->child_index(
10610 child_at_origin[hex->face(3)->refinement_case() -
10611 1][f_fl[3]][f_ro[3]]), // 14
10612 hex->face(3)->child_index(
10613 1 -
10614 child_at_origin[hex->face(3)->refinement_case() -
10615 1][f_fl[3]][f_ro[3]]),
10616
10617 hex->face(4)->child_index(
10618 child_at_origin[hex->face(4)->refinement_case() -
10619 1][f_fl[4]][f_ro[4]]), // 16
10620 hex->face(4)->child_index(
10621 1 -
10622 child_at_origin[hex->face(4)->refinement_case() -
10623 1][f_fl[4]][f_ro[4]]),
10624
10625 hex->face(5)->child_index(
10626 child_at_origin[hex->face(5)->refinement_case() -
10627 1][f_fl[5]][f_ro[5]]), // 18
10628 hex->face(5)->child_index(
10629 1 -
10630 child_at_origin[hex->face(5)->refinement_case() -
10631 1][f_fl[5]][f_ro[5]])};
10632
10633 new_hexes[0]->set_bounding_object_indices(
10634 {quad_indices[4],
10635 quad_indices[8],
10636 quad_indices[12],
10637 quad_indices[2],
10638 quad_indices[16],
10639 quad_indices[0]});
10640 new_hexes[1]->set_bounding_object_indices(
10641 {quad_indices[5],
10642 quad_indices[9],
10643 quad_indices[2],
10644 quad_indices[14],
10645 quad_indices[17],
10646 quad_indices[1]});
10647 new_hexes[2]->set_bounding_object_indices(
10648 {quad_indices[6],
10649 quad_indices[10],
10650 quad_indices[13],
10651 quad_indices[3],
10652 quad_indices[0],
10653 quad_indices[18]});
10654 new_hexes[3]->set_bounding_object_indices(
10655 {quad_indices[7],
10656 quad_indices[11],
10657 quad_indices[3],
10658 quad_indices[15],
10659 quad_indices[1],
10660 quad_indices[19]});
10661 break;
10662 }
10663
10665 {
10666 //----------------------------
10667 //
10668 // RefinementCase<dim>::cut_xyz
10669 // isotropic refinement
10670 //
10671 // the refined cube will look
10672 // like this:
10673 //
10674 // *----*----*
10675 // / / /|
10676 // *----*----* |
10677 // / / /| *
10678 // *----*----* |/|
10679 // | | | * |
10680 // | | |/| *
10681 // *----*----* |/
10682 // | | | *
10683 // | | |/
10684 // *----*----*
10685 //
10686
10687 // find the next unused vertex and set it
10688 // appropriately
10689 while (
10690 triangulation.vertices_used[next_unused_vertex] ==
10691 true)
10692 ++next_unused_vertex;
10693 Assert(
10694 next_unused_vertex < triangulation.vertices.size(),
10695 ExcMessage(
10696 "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."));
10697 triangulation.vertices_used[next_unused_vertex] =
10698 true;
10699
10700 // the new vertex is definitely in the interior,
10701 // so we need not worry about the
10702 // boundary. However we need to worry about
10703 // Manifolds. Let the cell compute its own
10704 // center, by querying the underlying manifold
10705 // object.
10706 triangulation.vertices[next_unused_vertex] =
10707 hex->center(true, true);
10708
10709 // set the data of the six lines. first collect
10710 // the indices of the seven vertices (consider
10711 // the two planes to be crossed to form the
10712 // planes cutting the hex in two vertically and
10713 // horizontally)
10714 //
10715 // *--3--* *--5--*
10716 // / / / | | |
10717 // 0--6--1 0--6--1
10718 // / / / | | |
10719 // *--2--* *--4--*
10720 // the lines are numbered
10721 // as follows:
10722 // *--*--* *--*--*
10723 // / 1 / | 5 |
10724 // *2-*-3* *2-*-3*
10725 // / 0 / | 4 |
10726 // *--*--* *--*--*
10727 //
10728 const unsigned int vertex_indices[7] = {
10729 middle_vertex_index<dim, spacedim>(hex->face(0)),
10730 middle_vertex_index<dim, spacedim>(hex->face(1)),
10731 middle_vertex_index<dim, spacedim>(hex->face(2)),
10732 middle_vertex_index<dim, spacedim>(hex->face(3)),
10733 middle_vertex_index<dim, spacedim>(hex->face(4)),
10734 middle_vertex_index<dim, spacedim>(hex->face(5)),
10735 next_unused_vertex};
10736
10737 new_lines[0]->set_bounding_object_indices(
10739 new_lines[1]->set_bounding_object_indices(
10741 new_lines[2]->set_bounding_object_indices(
10743 new_lines[3]->set_bounding_object_indices(
10745 new_lines[4]->set_bounding_object_indices(
10747 new_lines[5]->set_bounding_object_indices(
10749
10750 // again, first collect some data about the
10751 // indices of the lines, with the following
10752 // numbering: (note that face 0 and 1 each are
10753 // shown twice for better readability)
10754
10755 // face 0: left plane
10756 // * *
10757 // /| /|
10758 // * | * |
10759 // /| * /| *
10760 // * 1/| * |3|
10761 // | * | | * |
10762 // |/| * |2| *
10763 // * 0/ * |/
10764 // | * | *
10765 // |/ |/
10766 // * *
10767 // face 1: right plane
10768 // * *
10769 // /| /|
10770 // * | * |
10771 // /| * /| *
10772 // * 5/| * |7|
10773 // | * | | * |
10774 // |/| * |6| *
10775 // * 4/ * |/
10776 // | * | *
10777 // |/ |/
10778 // * *
10779 // face 2: front plane
10780 // (note: x,y exchanged)
10781 // *---*---*
10782 // | 11 |
10783 // *-8-*-9-*
10784 // | 10 |
10785 // *---*---*
10786 // face 3: back plane
10787 // (note: x,y exchanged)
10788 // *---*---*
10789 // | 15 |
10790 // *12-*-13*
10791 // | 14 |
10792 // *---*---*
10793 // face 4: bottom plane
10794 // *---*---*
10795 // / 17 /
10796 // *18-*-19*
10797 // / 16 /
10798 // *---*---*
10799 // face 5: top plane
10800 // *---*---*
10801 // / 21 /
10802 // *22-*-23*
10803 // / 20 /
10804 // *---*---*
10805 // middle planes
10806 // *---*---* *---*---*
10807 // / 25 / | 29 |
10808 // *26-*-27* *26-*-27*
10809 // / 24 / | 28 |
10810 // *---*---* *---*---*
10811
10812 // set up a list of line iterators first. from
10813 // this, construct lists of line_indices and
10814 // line orientations later on
10815 const typename Triangulation<
10816 dim,
10817 spacedim>::raw_line_iterator lines[30] = {
10818 hex->face(0)
10819 ->isotropic_child(
10821 0, f_or[0], f_fl[0], f_ro[0]))
10822 ->line(
10824 1, f_or[0], f_fl[0], f_ro[0])), // 0
10825 hex->face(0)
10826 ->isotropic_child(
10828 3, f_or[0], f_fl[0], f_ro[0]))
10829 ->line(
10831 0, f_or[0], f_fl[0], f_ro[0])), // 1
10832 hex->face(0)
10833 ->isotropic_child(
10835 0, f_or[0], f_fl[0], f_ro[0]))
10836 ->line(
10838 3, f_or[0], f_fl[0], f_ro[0])), // 2
10839 hex->face(0)
10840 ->isotropic_child(
10842 3, f_or[0], f_fl[0], f_ro[0]))
10843 ->line(
10845 2, f_or[0], f_fl[0], f_ro[0])), // 3
10846
10847 hex->face(1)
10848 ->isotropic_child(
10850 0, f_or[1], f_fl[1], f_ro[1]))
10851 ->line(
10853 1, f_or[1], f_fl[1], f_ro[1])), // 4
10854 hex->face(1)
10855 ->isotropic_child(
10857 3, f_or[1], f_fl[1], f_ro[1]))
10858 ->line(
10860 0, f_or[1], f_fl[1], f_ro[1])), // 5
10861 hex->face(1)
10862 ->isotropic_child(
10864 0, f_or[1], f_fl[1], f_ro[1]))
10865 ->line(
10867 3, f_or[1], f_fl[1], f_ro[1])), // 6
10868 hex->face(1)
10869 ->isotropic_child(
10871 3, f_or[1], f_fl[1], f_ro[1]))
10872 ->line(
10874 2, f_or[1], f_fl[1], f_ro[1])), // 7
10875
10876 hex->face(2)
10877 ->isotropic_child(
10879 0, f_or[2], f_fl[2], f_ro[2]))
10880 ->line(
10882 1, f_or[2], f_fl[2], f_ro[2])), // 8
10883 hex->face(2)
10884 ->isotropic_child(
10886 3, f_or[2], f_fl[2], f_ro[2]))
10887 ->line(
10889 0, f_or[2], f_fl[2], f_ro[2])), // 9
10890 hex->face(2)
10891 ->isotropic_child(
10893 0, f_or[2], f_fl[2], f_ro[2]))
10894 ->line(
10896 3, f_or[2], f_fl[2], f_ro[2])), // 10
10897 hex->face(2)
10898 ->isotropic_child(
10900 3, f_or[2], f_fl[2], f_ro[2]))
10901 ->line(
10903 2, f_or[2], f_fl[2], f_ro[2])), // 11
10904
10905 hex->face(3)
10906 ->isotropic_child(
10908 0, f_or[3], f_fl[3], f_ro[3]))
10909 ->line(
10911 1, f_or[3], f_fl[3], f_ro[3])), // 12
10912 hex->face(3)
10913 ->isotropic_child(
10915 3, f_or[3], f_fl[3], f_ro[3]))
10916 ->line(
10918 0, f_or[3], f_fl[3], f_ro[3])), // 13
10919 hex->face(3)
10920 ->isotropic_child(
10922 0, f_or[3], f_fl[3], f_ro[3]))
10923 ->line(
10925 3, f_or[3], f_fl[3], f_ro[3])), // 14
10926 hex->face(3)
10927 ->isotropic_child(
10929 3, f_or[3], f_fl[3], f_ro[3]))
10930 ->line(
10932 2, f_or[3], f_fl[3], f_ro[3])), // 15
10933
10934 hex->face(4)
10935 ->isotropic_child(
10937 0, f_or[4], f_fl[4], f_ro[4]))
10938 ->line(
10940 1, f_or[4], f_fl[4], f_ro[4])), // 16
10941 hex->face(4)
10942 ->isotropic_child(
10944 3, f_or[4], f_fl[4], f_ro[4]))
10945 ->line(
10947 0, f_or[4], f_fl[4], f_ro[4])), // 17
10948 hex->face(4)
10949 ->isotropic_child(
10951 0, f_or[4], f_fl[4], f_ro[4]))
10952 ->line(
10954 3, f_or[4], f_fl[4], f_ro[4])), // 18
10955 hex->face(4)
10956 ->isotropic_child(
10958 3, f_or[4], f_fl[4], f_ro[4]))
10959 ->line(
10961 2, f_or[4], f_fl[4], f_ro[4])), // 19
10962
10963 hex->face(5)
10964 ->isotropic_child(
10966 0, f_or[5], f_fl[5], f_ro[5]))
10967 ->line(
10969 1, f_or[5], f_fl[5], f_ro[5])), // 20
10970 hex->face(5)
10971 ->isotropic_child(
10973 3, f_or[5], f_fl[5], f_ro[5]))
10974 ->line(
10976 0, f_or[5], f_fl[5], f_ro[5])), // 21
10977 hex->face(5)
10978 ->isotropic_child(
10980 0, f_or[5], f_fl[5], f_ro[5]))
10981 ->line(
10983 3, f_or[5], f_fl[5], f_ro[5])), // 22
10984 hex->face(5)
10985 ->isotropic_child(
10987 3, f_or[5], f_fl[5], f_ro[5]))
10988 ->line(
10990 2, f_or[5], f_fl[5], f_ro[5])), // 23
10991
10992 new_lines[0], // 24
10993 new_lines[1], // 25
10994 new_lines[2], // 26
10995 new_lines[3], // 27
10996 new_lines[4], // 28
10997 new_lines[5] // 29
10998 };
10999
11000 unsigned int line_indices[30];
11001 for (unsigned int i = 0; i < 30; ++i)
11002 line_indices[i] = lines[i]->index();
11003
11004 // the orientation of lines for the inner quads
11005 // is quite tricky. as these lines are newly
11006 // created ones and thus have no parents, they
11007 // cannot inherit this property. set up an array
11008 // and fill it with the respective values
11009 bool line_orientation[30];
11010
11011 // note: for the first 24 lines (inner lines of
11012 // the outer quads) the following holds: the
11013 // second vertex of the even lines in standard
11014 // orientation is the vertex in the middle of
11015 // the quad, whereas for odd lines the first
11016 // vertex is the same middle vertex.
11017 for (unsigned int i = 0; i < 24; ++i)
11018 if (lines[i]->vertex_index((i + 1) % 2) ==
11019 vertex_indices[i / 4])
11020 line_orientation[i] = true;
11021 else
11022 {
11023 // it must be the other way
11024 // round then
11025 Assert(lines[i]->vertex_index(i % 2) ==
11026 vertex_indices[i / 4],
11028 line_orientation[i] = false;
11029 }
11030 // for the last 6 lines the line orientation is
11031 // always true, since they were just constructed
11032 // that way
11033 for (unsigned int i = 24; i < 30; ++i)
11034 line_orientation[i] = true;
11035
11036 // set up the 12 quads, numbered as follows
11037 // (left quad numbering, right line numbering
11038 // extracted from above)
11039 //
11040 // * *
11041 // /| 21|
11042 // * | * 15
11043 // y/|3* 20| *
11044 // * |/| * |/|
11045 // |2* |x 11 * 14
11046 // |/|1* |/| *
11047 // * |/ * |17
11048 // |0* 10 *
11049 // |/ |16
11050 // * *
11051 //
11052 // x
11053 // *---*---* *22-*-23*
11054 // | 5 | 7 | 1 29 5
11055 // *---*---* *26-*-27*
11056 // | 4 | 6 | 0 28 4
11057 // *---*---*y *18-*-19*
11058 //
11059 // y
11060 // *----*----* *-12-*-13-*
11061 // / 10 / 11 / 3 25 7
11062 // *----*----* *-26-*-27-*
11063 // / 8 / 9 / 2 24 6
11064 // *----*----*x *--8-*--9-*
11065
11066 new_quads[0]->set_bounding_object_indices(
11067 {line_indices[10],
11068 line_indices[28],
11069 line_indices[16],
11070 line_indices[24]});
11071 new_quads[1]->set_bounding_object_indices(
11072 {line_indices[28],
11073 line_indices[14],
11074 line_indices[17],
11075 line_indices[25]});
11076 new_quads[2]->set_bounding_object_indices(
11077 {line_indices[11],
11078 line_indices[29],
11079 line_indices[24],
11080 line_indices[20]});
11081 new_quads[3]->set_bounding_object_indices(
11082 {line_indices[29],
11083 line_indices[15],
11084 line_indices[25],
11085 line_indices[21]});
11086 new_quads[4]->set_bounding_object_indices(
11087 {line_indices[18],
11088 line_indices[26],
11089 line_indices[0],
11090 line_indices[28]});
11091 new_quads[5]->set_bounding_object_indices(
11092 {line_indices[26],
11093 line_indices[22],
11094 line_indices[1],
11095 line_indices[29]});
11096 new_quads[6]->set_bounding_object_indices(
11097 {line_indices[19],
11098 line_indices[27],
11099 line_indices[28],
11100 line_indices[4]});
11101 new_quads[7]->set_bounding_object_indices(
11102 {line_indices[27],
11103 line_indices[23],
11104 line_indices[29],
11105 line_indices[5]});
11106 new_quads[8]->set_bounding_object_indices(
11107 {line_indices[2],
11108 line_indices[24],
11109 line_indices[8],
11110 line_indices[26]});
11111 new_quads[9]->set_bounding_object_indices(
11112 {line_indices[24],
11113 line_indices[6],
11114 line_indices[9],
11115 line_indices[27]});
11116 new_quads[10]->set_bounding_object_indices(
11117 {line_indices[3],
11118 line_indices[25],
11119 line_indices[26],
11120 line_indices[12]});
11121 new_quads[11]->set_bounding_object_indices(
11122 {line_indices[25],
11123 line_indices[7],
11124 line_indices[27],
11125 line_indices[13]});
11126
11127 // now reset the line_orientation flags of outer
11128 // lines as they cannot be set in a loop (at
11129 // least not easily)
11130 new_quads[0]->set_line_orientation(
11131 0, line_orientation[10]);
11132 new_quads[0]->set_line_orientation(
11133 2, line_orientation[16]);
11134
11135 new_quads[1]->set_line_orientation(
11136 1, line_orientation[14]);
11137 new_quads[1]->set_line_orientation(
11138 2, line_orientation[17]);
11139
11140 new_quads[2]->set_line_orientation(
11141 0, line_orientation[11]);
11142 new_quads[2]->set_line_orientation(
11143 3, line_orientation[20]);
11144
11145 new_quads[3]->set_line_orientation(
11146 1, line_orientation[15]);
11147 new_quads[3]->set_line_orientation(
11148 3, line_orientation[21]);
11149
11150 new_quads[4]->set_line_orientation(
11151 0, line_orientation[18]);
11152 new_quads[4]->set_line_orientation(
11153 2, line_orientation[0]);
11154
11155 new_quads[5]->set_line_orientation(
11156 1, line_orientation[22]);
11157 new_quads[5]->set_line_orientation(
11158 2, line_orientation[1]);
11159
11160 new_quads[6]->set_line_orientation(
11161 0, line_orientation[19]);
11162 new_quads[6]->set_line_orientation(
11163 3, line_orientation[4]);
11164
11165 new_quads[7]->set_line_orientation(
11166 1, line_orientation[23]);
11167 new_quads[7]->set_line_orientation(
11168 3, line_orientation[5]);
11169
11170 new_quads[8]->set_line_orientation(
11171 0, line_orientation[2]);
11172 new_quads[8]->set_line_orientation(
11173 2, line_orientation[8]);
11174
11175 new_quads[9]->set_line_orientation(
11176 1, line_orientation[6]);
11177 new_quads[9]->set_line_orientation(
11178 2, line_orientation[9]);
11179
11180 new_quads[10]->set_line_orientation(
11181 0, line_orientation[3]);
11182 new_quads[10]->set_line_orientation(
11183 3, line_orientation[12]);
11184
11185 new_quads[11]->set_line_orientation(
11186 1, line_orientation[7]);
11187 new_quads[11]->set_line_orientation(
11188 3, line_orientation[13]);
11189
11190 //-------------------------------
11191 // create the eight new hexes
11192 //
11193 // again first collect some data. here, we need
11194 // the indices of a whole lotta quads.
11195
11196 // the quads are numbered as follows:
11197 //
11198 // planes in the interior of the old hex:
11199 //
11200 // *
11201 // /|
11202 // * |
11203 // /|3* *---*---* *----*----*
11204 // * |/| | 5 | 7 | / 10 / 11 /
11205 // |2* | *---*---* *----*----*
11206 // |/|1* | 4 | 6 | / 8 / 9 /
11207 // * |/ *---*---*y *----*----*x
11208 // |0*
11209 // |/
11210 // *
11211 //
11212 // children of the faces
11213 // of the old hex
11214 // *-------* *-------*
11215 // /|25 27| /34 35/|
11216 // 15| | / /19
11217 // / | | /32 33/ |
11218 // * |24 26| *-------*18 |
11219 // 1413*-------* |21 23| 17*
11220 // | /30 31/ | | /
11221 // 12/ / | |16
11222 // |/28 29/ |20 22|/
11223 // *-------* *-------*
11224 //
11225 // note that we have to
11226 // take care of the
11227 // orientation of
11228 // faces.
11229 const int quad_indices[36] = {
11230 new_quads[0]->index(), // 0
11231 new_quads[1]->index(),
11232 new_quads[2]->index(),
11233 new_quads[3]->index(),
11234 new_quads[4]->index(),
11235 new_quads[5]->index(),
11236 new_quads[6]->index(),
11237 new_quads[7]->index(),
11238 new_quads[8]->index(),
11239 new_quads[9]->index(),
11240 new_quads[10]->index(),
11241 new_quads[11]->index(), // 11
11242
11243 hex->face(0)->isotropic_child_index(
11245 0, f_or[0], f_fl[0], f_ro[0])), // 12
11246 hex->face(0)->isotropic_child_index(
11248 1, f_or[0], f_fl[0], f_ro[0])),
11249 hex->face(0)->isotropic_child_index(
11251 2, f_or[0], f_fl[0], f_ro[0])),
11252 hex->face(0)->isotropic_child_index(
11254 3, f_or[0], f_fl[0], f_ro[0])),
11255
11256 hex->face(1)->isotropic_child_index(
11258 0, f_or[1], f_fl[1], f_ro[1])), // 16
11259 hex->face(1)->isotropic_child_index(
11261 1, f_or[1], f_fl[1], f_ro[1])),
11262 hex->face(1)->isotropic_child_index(
11264 2, f_or[1], f_fl[1], f_ro[1])),
11265 hex->face(1)->isotropic_child_index(
11267 3, f_or[1], f_fl[1], f_ro[1])),
11268
11269 hex->face(2)->isotropic_child_index(
11271 0, f_or[2], f_fl[2], f_ro[2])), // 20
11272 hex->face(2)->isotropic_child_index(
11274 1, f_or[2], f_fl[2], f_ro[2])),
11275 hex->face(2)->isotropic_child_index(
11277 2, f_or[2], f_fl[2], f_ro[2])),
11278 hex->face(2)->isotropic_child_index(
11280 3, f_or[2], f_fl[2], f_ro[2])),
11281
11282 hex->face(3)->isotropic_child_index(
11284 0, f_or[3], f_fl[3], f_ro[3])), // 24
11285 hex->face(3)->isotropic_child_index(
11287 1, f_or[3], f_fl[3], f_ro[3])),
11288 hex->face(3)->isotropic_child_index(
11290 2, f_or[3], f_fl[3], f_ro[3])),
11291 hex->face(3)->isotropic_child_index(
11293 3, f_or[3], f_fl[3], f_ro[3])),
11294
11295 hex->face(4)->isotropic_child_index(
11297 0, f_or[4], f_fl[4], f_ro[4])), // 28
11298 hex->face(4)->isotropic_child_index(
11300 1, f_or[4], f_fl[4], f_ro[4])),
11301 hex->face(4)->isotropic_child_index(
11303 2, f_or[4], f_fl[4], f_ro[4])),
11304 hex->face(4)->isotropic_child_index(
11306 3, f_or[4], f_fl[4], f_ro[4])),
11307
11308 hex->face(5)->isotropic_child_index(
11310 0, f_or[5], f_fl[5], f_ro[5])), // 32
11311 hex->face(5)->isotropic_child_index(
11313 1, f_or[5], f_fl[5], f_ro[5])),
11314 hex->face(5)->isotropic_child_index(
11316 2, f_or[5], f_fl[5], f_ro[5])),
11317 hex->face(5)->isotropic_child_index(
11319 3, f_or[5], f_fl[5], f_ro[5]))};
11320
11321 // bottom children
11322 new_hexes[0]->set_bounding_object_indices(
11323 {quad_indices[12],
11324 quad_indices[0],
11325 quad_indices[20],
11326 quad_indices[4],
11327 quad_indices[28],
11328 quad_indices[8]});
11329 new_hexes[1]->set_bounding_object_indices(
11330 {quad_indices[0],
11331 quad_indices[16],
11332 quad_indices[22],
11333 quad_indices[6],
11334 quad_indices[29],
11335 quad_indices[9]});
11336 new_hexes[2]->set_bounding_object_indices(
11337 {quad_indices[13],
11338 quad_indices[1],
11339 quad_indices[4],
11340 quad_indices[24],
11341 quad_indices[30],
11342 quad_indices[10]});
11343 new_hexes[3]->set_bounding_object_indices(
11344 {quad_indices[1],
11345 quad_indices[17],
11346 quad_indices[6],
11347 quad_indices[26],
11348 quad_indices[31],
11349 quad_indices[11]});
11350
11351 // top children
11352 new_hexes[4]->set_bounding_object_indices(
11353 {quad_indices[14],
11354 quad_indices[2],
11355 quad_indices[21],
11356 quad_indices[5],
11357 quad_indices[8],
11358 quad_indices[32]});
11359 new_hexes[5]->set_bounding_object_indices(
11360 {quad_indices[2],
11361 quad_indices[18],
11362 quad_indices[23],
11363 quad_indices[7],
11364 quad_indices[9],
11365 quad_indices[33]});
11366 new_hexes[6]->set_bounding_object_indices(
11367 {quad_indices[15],
11368 quad_indices[3],
11369 quad_indices[5],
11370 quad_indices[25],
11371 quad_indices[10],
11372 quad_indices[34]});
11373 new_hexes[7]->set_bounding_object_indices(
11374 {quad_indices[3],
11375 quad_indices[19],
11376 quad_indices[7],
11377 quad_indices[27],
11378 quad_indices[11],
11379 quad_indices[35]});
11380 break;
11381 }
11382 default:
11383 // all refinement cases have been treated, there
11384 // only remains
11385 // RefinementCase<dim>::no_refinement as
11386 // untreated enumeration value. However, in that
11387 // case we should have aborted much
11388 // earlier. thus we should never get here
11390 break;
11391 } // switch (ref_case)
11392
11393 // and set face orientation flags. note that new
11394 // faces in the interior of the mother cell always
11395 // have a correctly oriented face, but the ones on
11396 // the outer faces will inherit this flag
11397 //
11398 // the flag have been set to true for all faces
11399 // initially, now go the other way round and reset
11400 // faces that are at the boundary of the mother cube
11401 //
11402 // the same is true for the face_flip and
11403 // face_rotation flags. however, the latter two are
11404 // set to false by default as this is the standard
11405 // value
11406
11407 // loop over all faces and all (relevant) subfaces
11408 // of that in order to set the correct values for
11409 // face_orientation, face_flip and face_rotation,
11410 // which are inherited from the corresponding face
11411 // of the mother cube
11412 for (const unsigned int f : GeometryInfo<dim>::face_indices())
11413 for (unsigned int s = 0;
11416 ref_case, f)),
11417 1U);
11418 ++s)
11419 {
11420 const unsigned int current_child =
11422 ref_case,
11423 f,
11424 s,
11425 f_or[f],
11426 f_fl[f],
11427 f_ro[f],
11429 ref_case, f, f_or[f], f_fl[f], f_ro[f]));
11430 new_hexes[current_child]->set_combined_face_orientation(
11431 f, f_co[f]);
11432 }
11433
11434 // now see if we have created cells that are
11435 // distorted and if so add them to our list
11436 if (check_for_distorted_cells &&
11437 has_distorted_children<dim, spacedim>(hex))
11438 cells_with_distorted_children.distorted_cells.push_back(
11439 hex);
11440
11441 // note that the refinement flag was already cleared
11442 // at the beginning of this loop
11443
11444 // inform all listeners that cell refinement is done
11445 triangulation.signals.post_refinement_on_cell(hex);
11446 }
11447 }
11448
11449 // clear user data on quads. we used some of this data to
11450 // indicate anisotropic refinemnt cases on faces. all data
11451 // should be cleared by now, but the information whether we
11452 // used indices or pointers is still present. reset it now to
11453 // enable the user to use whichever they like later on.
11454 triangulation.faces->quads.clear_user_data();
11455
11456 // return the list with distorted children
11457 return cells_with_distorted_children;
11458 }
11459
11460
11473 template <int spacedim>
11474 static void
11477
11478
11479
11480 template <int dim, int spacedim>
11481 static void
11484 {
11485 // If the codimension is one, we cannot perform this check
11486 // yet.
11487 if (spacedim > dim)
11488 return;
11489
11490 for (const auto &cell : triangulation.cell_iterators())
11491 if (cell->at_boundary() && cell->refine_flag_set() &&
11492 cell->refine_flag_set() !=
11494 {
11495 // The cell is at the boundary and it is flagged for
11496 // anisotropic refinement. Therefore, we have a closer
11497 // look
11498 const RefinementCase<dim> ref_case = cell->refine_flag_set();
11499 for (const unsigned int face_no :
11501 if (cell->face(face_no)->at_boundary())
11502 {
11503 // this is the critical face at the boundary.
11505 face_no) !=
11507 {
11508 // up to now, we do not want to refine this
11509 // cell along the face under consideration
11510 // here.
11511 const typename Triangulation<dim,
11512 spacedim>::face_iterator
11513 face = cell->face(face_no);
11514 // the new point on the boundary would be this
11515 // one.
11516 const Point<spacedim> new_bound = face->center(true);
11517 // to check it, transform to the unit cell
11518 // with a linear mapping
11519 const Point<dim> new_unit =
11520 cell->reference_cell()
11521 .template get_default_linear_mapping<dim,
11522 spacedim>()
11523 .transform_real_to_unit_cell(cell, new_bound);
11524
11525 // Now, we have to calculate the distance from
11526 // the face in the unit cell.
11527
11528 // take the correct coordinate direction (0
11529 // for faces 0 and 1, 1 for faces 2 and 3, 2
11530 // for faces 4 and 5) and subtract the correct
11531 // boundary value of the face (0 for faces 0,
11532 // 2, and 4; 1 for faces 1, 3 and 5)
11533 const double dist =
11534 std::fabs(new_unit[face_no / 2] - face_no % 2);
11535
11536 // compare this with the empirical value
11537 // allowed. if it is too big, flag the face
11538 // for isotropic refinement
11539 const double allowed = 0.25;
11540
11541 if (dist > allowed)
11542 cell->flag_for_face_refinement(face_no);
11543 } // if flagged for anistropic refinement
11544 } // if (cell->face(face)->at_boundary())
11545 } // for all cells
11546 }
11547
11548
11561 template <int dim, int spacedim>
11562 static void
11564 {
11565 Assert(dim < 3,
11566 ExcMessage("Wrong function called -- there should "
11567 "be a specialization."));
11568 }
11569
11570
11571 template <int spacedim>
11572 static void
11575 {
11576 const unsigned int dim = 3;
11577 using raw_line_iterator =
11579
11580 // variable to store whether the mesh was changed in the
11581 // present loop and in the whole process
11582 bool mesh_changed = false;
11583
11584 do
11585 {
11586 mesh_changed = false;
11587
11588 // for this following, we need to know which cells are
11589 // going to be coarsened, if we had to make a
11590 // decision. the following function sets these flags:
11591 triangulation.fix_coarsen_flags();
11592
11593 // first clear flags on lines, since we need them to determine
11594 // which lines will be refined
11595 triangulation.clear_user_flags_line();
11596
11597 // flag those lines that are refined and will not be
11598 // coarsened and those that will be refined
11599 for (const auto &cell : triangulation.cell_iterators())
11600 if (cell->refine_flag_set())
11601 {
11602 const std::array<unsigned int, 12> line_indices =
11603 TriaAccessorImplementation::Implementation::
11604 get_line_indices_of_cell(*cell);
11605 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11607 cell->refine_flag_set(), l) ==
11609 {
11610 raw_line_iterator line(&triangulation,
11611 0,
11612 line_indices[l]);
11613 // flag a line, that will be refined
11614 line->set_user_flag();
11615 }
11616 }
11617 else if (cell->has_children() &&
11618 !cell->child(0)->coarsen_flag_set())
11619 {
11620 const std::array<unsigned int, 12> line_indices =
11621 TriaAccessorImplementation::Implementation::
11622 get_line_indices_of_cell(*cell);
11623 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11625 cell->refinement_case(), l) ==
11627 {
11628 raw_line_iterator line(&triangulation,
11629 0,
11630 line_indices[l]);
11631 // flag a line, that is refined and will stay so
11632 line->set_user_flag();
11633 }
11634 }
11635 else if (cell->has_children() &&
11636 cell->child(0)->coarsen_flag_set())
11637 cell->set_user_flag();
11638
11639
11640 // now check whether there are cells with lines that are
11641 // more than once refined or that will be more than once
11642 // refined. The first thing should never be the case, in
11643 // the second case we flag the cell for refinement
11645 cell = triangulation.last_active();
11646 cell != triangulation.end();
11647 --cell)
11648 {
11649 const std::array<unsigned int, 12> line_indices =
11650 TriaAccessorImplementation::Implementation::
11651 get_line_indices_of_cell(*cell);
11652 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11653 {
11654 raw_line_iterator line(&triangulation, 0, line_indices[l]);
11655 if (line->has_children())
11656 {
11657 // if this line is refined, its children should
11658 // not have further children
11659 //
11660 // however, if any of the children is flagged
11661 // for further refinement, we need to refine
11662 // this cell also (at least, if the cell is not
11663 // already flagged)
11664 bool offending_line_found = false;
11665
11666 for (unsigned int c = 0; c < 2; ++c)
11667 {
11668 Assert(line->child(c)->has_children() == false,
11670
11671 if (line->child(c)->user_flag_set() &&
11673 cell->refine_flag_set(), l) ==
11675 {
11676 // tag this cell for refinement
11677 cell->clear_coarsen_flag();
11678 // if anisotropic coarsening is allowed:
11679 // extend the refine_flag in the needed
11680 // direction, else set refine_flag
11681 // (isotropic)
11682 if (triangulation.smooth_grid &
11684 allow_anisotropic_smoothing)
11685 cell->flag_for_line_refinement(l);
11686 else
11687 cell->set_refine_flag();
11688
11689 for (unsigned int k = 0; k < cell->n_lines();
11690 ++k)
11692 cell->refine_flag_set(), l) ==
11694 // flag a line, that will be refined
11695 raw_line_iterator(&triangulation,
11696 0,
11697 line_indices[k])
11698 ->set_user_flag();
11699
11700 // note that we have changed the grid
11701 offending_line_found = true;
11702
11703 // it may save us several loop
11704 // iterations if we flag all lines of
11705 // this cell now (and not at the outset
11706 // of the next iteration) for refinement
11707 for (unsigned int k = 0; k < cell->n_lines();
11708 ++k)
11709 {
11710 const auto line =
11711 raw_line_iterator(&triangulation,
11712 0,
11713 line_indices[k]);
11714 if (!line->has_children() &&
11716 line_refinement_case(
11717 cell->refine_flag_set(), k) !=
11719 line->set_user_flag();
11720 }
11721
11722 break;
11723 }
11724 }
11725
11726 if (offending_line_found)
11727 {
11728 mesh_changed = true;
11729 break;
11730 }
11731 }
11732 }
11733 }
11734
11735
11736 // there is another thing here: if any of the lines will
11737 // be refined, then we may not coarsen the present cell
11738 // similarly, if any of the lines *is* already refined, we
11739 // may not coarsen the current cell. however, there's a
11740 // catch: if the line is refined, but the cell behind it
11741 // is going to be coarsened, then the situation
11742 // changes. if we forget this second condition, the
11743 // refine_and_coarsen_3d test will start to fail. note
11744 // that to know which cells are going to be coarsened, the
11745 // call for fix_coarsen_flags above is necessary
11747 triangulation.last();
11748 cell != triangulation.end();
11749 --cell)
11750 if (cell->user_flag_set())
11751 {
11752 const std::array<unsigned int, 12> line_indices =
11753 TriaAccessorImplementation::Implementation::
11754 get_line_indices_of_cell(*cell);
11755 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11756 {
11757 raw_line_iterator line(&triangulation,
11758 0,
11759 line_indices[l]);
11760 if (line->has_children() &&
11761 (line->child(0)->user_flag_set() ||
11762 line->child(1)->user_flag_set()))
11763 {
11764 for (unsigned int c = 0; c < cell->n_children(); ++c)
11765 cell->child(c)->clear_coarsen_flag();
11766 cell->clear_user_flag();
11767 for (unsigned int k = 0; k < cell->n_lines(); ++k)
11769 cell->refinement_case(), k) ==
11771 // flag a line, that is refined and will
11772 // stay so
11773 raw_line_iterator(&triangulation,
11774 0,
11775 line_indices[k])
11776 ->set_user_flag();
11777 mesh_changed = true;
11778 break;
11779 }
11780 }
11781 }
11782 }
11783 while (mesh_changed == true);
11784 }
11785
11786
11787
11794 template <int dim, int spacedim>
11795 static bool
11798 {
11799 // in 1d, coarsening is always allowed since we don't enforce
11800 // the 2:1 constraint there
11801 if (dim == 1)
11802 return true;
11803
11804 const RefinementCase<dim> ref_case = cell->refinement_case();
11805 for (const unsigned int n : GeometryInfo<dim>::face_indices())
11806 {
11807 // if the cell is not refined along that face, coarsening
11808 // will not change anything, so do nothing. the same
11809 // applies, if the face is at the boundary
11810 const RefinementCase<dim - 1> face_ref_case =
11811 GeometryInfo<dim>::face_refinement_case(cell->refinement_case(),
11812 n);
11813
11814 const unsigned int n_subfaces =
11815 GeometryInfo<dim - 1>::n_children(face_ref_case);
11816
11817 if (n_subfaces == 0 || cell->at_boundary(n))
11818 continue;
11819 for (unsigned int c = 0; c < n_subfaces; ++c)
11820 {
11822 child = cell->child(
11824
11826 child_neighbor = child->neighbor(n);
11827 if (!child->neighbor_is_coarser(n))
11828 {
11829 // in 2d, if the child's neighbor is coarser, then it has
11830 // no children. however, in 3d it might be
11831 // otherwise. consider for example, that our face might be
11832 // refined with cut_x, but the neighbor is refined with
11833 // cut_xy at that face. then the neighbor pointers of the
11834 // children of our cell will point to the common neighbor
11835 // cell, not to its children. what we really want to know
11836 // in the following is, whether the neighbor cell is
11837 // refined twice with reference to our cell. that only
11838 // has to be asked, if the child's neighbor is not a
11839 // coarser one. we check whether some of the children on
11840 // the neighbor are not flagged for coarsening, in that
11841 // case we may not coarsen. it is enough to check the
11842 // first child because we have already fixed the coarsen
11843 // flags on finer levels
11844 if (child_neighbor->has_children() &&
11845 !(child_neighbor->child(0)->is_active() &&
11846 child_neighbor->child(0)->coarsen_flag_set()))
11847 return false;
11848
11849 // the same applies, if the neighbors children are not
11850 // refined but will be after refinement
11851 if (child_neighbor->refine_flag_set())
11852 return false;
11853 }
11854 }
11855 }
11856 return true;
11857 }
11858 };
11859
11860
11865 {
11866 template <int spacedim>
11867 static void
11870
11871 template <int dim, int spacedim>
11873 {
11874 std::vector<std::pair<unsigned int, unsigned int>> adjacent_cells(
11875 2 * triangulation.n_raw_faces(),
11876 {numbers::invalid_unsigned_int, numbers::invalid_unsigned_int});
11877
11878 const auto set_entry = [&](const auto &face_index, const auto &cell) {
11879 const std::pair<unsigned int, unsigned int> cell_pair = {
11880 cell->level(), cell->index()};
11881 unsigned int index;
11882
11883 if (adjacent_cells[2 * face_index].first ==
11885 adjacent_cells[2 * face_index].second ==
11887 {
11888 index = 2 * face_index + 0;
11889 }
11890 else
11891 {
11892 Assert(((adjacent_cells[2 * face_index + 1].first ==
11894 (adjacent_cells[2 * face_index + 1].second ==
11897 index = 2 * face_index + 1;
11898 }
11899
11900 adjacent_cells[index] = cell_pair;
11901 };
11902
11903 const auto get_entry =
11904 [&](const auto &face_index,
11905 const auto &cell) -> TriaIterator<CellAccessor<dim, spacedim>> {
11906 auto test = adjacent_cells[2 * face_index];
11907
11908 if (test == std::pair<unsigned int, unsigned int>(cell->level(),
11909 cell->index()))
11910 test = adjacent_cells[2 * face_index + 1];
11911
11912 if ((test.first != numbers::invalid_unsigned_int) &&
11913 (test.second != numbers::invalid_unsigned_int))
11915 test.first,
11916 test.second);
11917 else
11919 };
11920
11921 for (const auto &cell : triangulation.cell_iterators())
11922 for (const auto &face : cell->face_iterators())
11923 {
11924 set_entry(face->index(), cell);
11925
11926 if (cell->is_active() && face->has_children())
11927 for (unsigned int c = 0; c < face->n_children(); ++c)
11928 set_entry(face->child(c)->index(), cell);
11929 }
11930
11931 for (const auto &cell : triangulation.cell_iterators())
11932 for (auto f : cell->face_indices())
11933 cell->set_neighbor(f, get_entry(cell->face(f)->index(), cell));
11934 }
11935
11936 template <int dim, int spacedim>
11937 static void
11941 std::vector<unsigned int> &line_cell_count,
11942 std::vector<unsigned int> &quad_cell_count)
11943 {
11945 (void)triangulation;
11946 (void)cell;
11947 (void)line_cell_count;
11948 (void)quad_cell_count;
11949 }
11950
11951 template <int dim, int spacedim>
11954 const bool check_for_distorted_cells)
11955 {
11956 return Implementation::execute_refinement_isotropic(
11957 triangulation, check_for_distorted_cells);
11958 }
11959
11960 template <int dim, int spacedim>
11961 static void
11964 {
11965 // nothing to do since anisotropy is not supported
11966 (void)triangulation;
11967 }
11968
11969 template <int dim, int spacedim>
11970 static void
11973 {
11974 Implementation::prepare_refinement_dim_dependent(triangulation);
11975 }
11976
11977 template <int dim, int spacedim>
11978 static bool
11981 {
11983
11984 return false;
11985 }
11986 };
11987
11988
11989 template <int dim, int spacedim>
11992 {
11993 static const FlatManifold<dim, spacedim> flat_manifold;
11994 return flat_manifold;
11995 }
11996 } // namespace TriangulationImplementation
11997} // namespace internal
11998
11999#ifndef DOXYGEN
12000
12001template <int dim, int spacedim>
12004
12005
12006
12007template <int dim, int spacedim>
12010 const MeshSmoothing smooth_grid,
12011 const bool check_for_distorted_cells)
12012 : cell_attached_data({0, 0, {}, {}})
12013 , smooth_grid(smooth_grid)
12014 , anisotropic_refinement(false)
12015 , check_for_distorted_cells(check_for_distorted_cells)
12016{
12017 if (dim == 1)
12018 {
12019 vertex_to_boundary_id_map_1d =
12020 std::make_unique<std::map<unsigned int, types::boundary_id>>();
12021 vertex_to_manifold_id_map_1d =
12022 std::make_unique<std::map<unsigned int, types::manifold_id>>();
12023 }
12024
12025 // connect the any_change signal to the other top level signals
12026 signals.create.connect(signals.any_change);
12027 signals.post_refinement.connect(signals.any_change);
12028 signals.clear.connect(signals.any_change);
12029 signals.mesh_movement.connect(signals.any_change);
12030}
12031
12032
12033
12034template <int dim, int spacedim>
12037 Triangulation<dim, spacedim> &&tria) noexcept
12038 : Subscriptor(std::move(tria))
12039 , smooth_grid(tria.smooth_grid)
12040 , reference_cells(std::move(tria.reference_cells))
12041 , periodic_face_pairs_level_0(std::move(tria.periodic_face_pairs_level_0))
12042 , periodic_face_map(std::move(tria.periodic_face_map))
12043 , levels(std::move(tria.levels))
12044 , faces(std::move(tria.faces))
12045 , vertices(std::move(tria.vertices))
12046 , vertices_used(std::move(tria.vertices_used))
12047 , manifolds(std::move(tria.manifolds))
12048 , anisotropic_refinement(tria.anisotropic_refinement)
12049 , check_for_distorted_cells(tria.check_for_distorted_cells)
12050 , number_cache(std::move(tria.number_cache))
12051 , vertex_to_boundary_id_map_1d(std::move(tria.vertex_to_boundary_id_map_1d))
12052 , vertex_to_manifold_id_map_1d(std::move(tria.vertex_to_manifold_id_map_1d))
12053{
12055
12056 if (tria.policy)
12057 this->policy = tria.policy->clone();
12058}
12059
12060
12061template <int dim, int spacedim>
12064 Triangulation<dim, spacedim> &&tria) noexcept
12065{
12066 Subscriptor::operator=(std::move(tria));
12067
12068 smooth_grid = tria.smooth_grid;
12069 reference_cells = std::move(tria.reference_cells);
12070 periodic_face_pairs_level_0 = std::move(tria.periodic_face_pairs_level_0);
12071 periodic_face_map = std::move(tria.periodic_face_map);
12072 levels = std::move(tria.levels);
12073 faces = std::move(tria.faces);
12074 vertices = std::move(tria.vertices);
12075 vertices_used = std::move(tria.vertices_used);
12076 manifolds = std::move(tria.manifolds);
12077 anisotropic_refinement = tria.anisotropic_refinement;
12078 number_cache = tria.number_cache;
12079 vertex_to_boundary_id_map_1d = std::move(tria.vertex_to_boundary_id_map_1d);
12080 vertex_to_manifold_id_map_1d = std::move(tria.vertex_to_manifold_id_map_1d);
12081
12083
12084 if (tria.policy)
12085 this->policy = tria.policy->clone();
12086
12087 return *this;
12088}
12089
12090
12091
12092template <int dim, int spacedim>
12095{
12096 // notify listeners that the triangulation is going down...
12097 try
12098 {
12099 signals.clear();
12100 }
12101 catch (...)
12102 {}
12103
12104 levels.clear();
12105
12106 // the vertex_to_boundary_id_map_1d field should be unused except in
12107 // 1d. double check this here, as destruction is a good place to
12108 // ensure that what we've done over the course of the lifetime of
12109 // this object makes sense
12110 AssertNothrow((dim == 1) || (vertex_to_boundary_id_map_1d == nullptr),
12112
12113 // the vertex_to_manifold_id_map_1d field should be also unused
12114 // except in 1d. check this as well
12115 AssertNothrow((dim == 1) || (vertex_to_manifold_id_map_1d == nullptr),
12117}
12118
12119
12120
12121template <int dim, int spacedim>
12124{
12125 // notify listeners that the triangulation is going down...
12126 signals.clear();
12127
12128 // ...and then actually clear all content of it
12129 clear_despite_subscriptions();
12130 periodic_face_pairs_level_0.clear();
12131 periodic_face_map.clear();
12132 reference_cells.clear();
12133
12134 cell_attached_data = {0, 0, {}, {}};
12135 data_serializer.clear();
12136}
12137
12138template <int dim, int spacedim>
12141{
12142 return MPI_COMM_SELF;
12143}
12144
12145
12146
12147template <int dim, int spacedim>
12149std::weak_ptr<const Utilities::MPI::Partitioner> Triangulation<dim, spacedim>::
12151{
12152 return number_cache.active_cell_index_partitioner;
12153}
12154
12155
12156
12157template <int dim, int spacedim>
12159std::weak_ptr<const Utilities::MPI::Partitioner> Triangulation<dim, spacedim>::
12160 global_level_cell_index_partitioner(const unsigned int level) const
12161{
12162 AssertIndexRange(level, this->n_levels());
12163
12164 return number_cache.level_cell_index_partitioners[level];
12165}
12166
12167
12168
12169template <int dim, int spacedim>
12172 const MeshSmoothing mesh_smoothing)
12173{
12174 smooth_grid = mesh_smoothing;
12175}
12176
12177
12178
12179template <int dim, int spacedim>
12183{
12184 return smooth_grid;
12185}
12186
12187
12188
12189template <int dim, int spacedim>
12192 const types::manifold_id m_number,
12193 const Manifold<dim, spacedim> &manifold_object)
12194{
12196
12197 manifolds[m_number] = manifold_object.clone();
12198}
12199
12200
12201
12202template <int dim, int spacedim>
12205 const types::manifold_id m_number)
12206{
12208
12209 // delete the entry located at number.
12210 manifolds[m_number] =
12212 spacedim>()
12213 .clone();
12214}
12215
12216
12217template <int dim, int spacedim>
12220{
12221 for (auto &m : manifolds)
12222 m.second = internal::TriangulationImplementation::
12223 get_default_flat_manifold<dim, spacedim>()
12224 .clone();
12225}
12226
12227
12228template <int dim, int spacedim>
12231 const types::manifold_id m_number)
12232{
12233 Assert(
12234 n_cells() > 0,
12235 ExcMessage(
12236 "Error: set_all_manifold_ids() can not be called on an empty Triangulation."));
12237
12238 for (const auto &cell : this->active_cell_iterators())
12239 cell->set_all_manifold_ids(m_number);
12240}
12241
12242
12243template <int dim, int spacedim>
12246 const types::manifold_id m_number)
12247{
12248 Assert(
12249 n_cells() > 0,
12250 ExcMessage(
12251 "Error: set_all_manifold_ids_on_boundary() can not be called on an empty Triangulation."));
12252
12253 for (const auto &cell : this->active_cell_iterators())
12254 for (auto f : GeometryInfo<dim>::face_indices())
12255 if (cell->face(f)->at_boundary())
12256 cell->face(f)->set_all_manifold_ids(m_number);
12257}
12258
12259
12260template <int dim, int spacedim>
12263 const types::boundary_id b_id,
12264 const types::manifold_id m_number)
12265{
12266 Assert(
12267 n_cells() > 0,
12268 ExcMessage(
12269 "Error: set_all_manifold_ids_on_boundary() can not be called on an empty Triangulation."));
12270
12271 bool boundary_found = false;
12272
12273 for (const auto &cell : this->active_cell_iterators())
12274 {
12275 // loop on faces
12276 for (auto f : GeometryInfo<dim>::face_indices())
12277 if (cell->face(f)->at_boundary() &&
12278 cell->face(f)->boundary_id() == b_id)
12279 {
12280 boundary_found = true;
12281 cell->face(f)->set_manifold_id(m_number);
12282 }
12283
12284 // loop on edges if dim >= 3
12285 if (dim >= 3)
12286 for (unsigned int e = 0; e < GeometryInfo<dim>::lines_per_cell; ++e)
12287 if (cell->line(e)->at_boundary() &&
12288 cell->line(e)->boundary_id() == b_id)
12289 {
12290 boundary_found = true;
12291 cell->line(e)->set_manifold_id(m_number);
12292 }
12293 }
12294
12295 (void)boundary_found;
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 // in 1d, we store a map of all used boundary indicators. use it for
12340 // our purposes
12341 if (dim == 1)
12342 {
12343 std::vector<types::boundary_id> boundary_ids;
12344 for (std::map<unsigned int, types::boundary_id>::const_iterator p =
12345 vertex_to_boundary_id_map_1d->begin();
12346 p != vertex_to_boundary_id_map_1d->end();
12347 ++p)
12348 boundary_ids.push_back(p->second);
12349
12350 return boundary_ids;
12351 }
12352 else
12353 {
12354 std::set<types::boundary_id> b_ids;
12355 for (auto cell : active_cell_iterators())
12356 if (cell->is_locally_owned())
12357 for (const unsigned int face : cell->face_indices())
12358 if (cell->at_boundary(face))
12359 b_ids.insert(cell->face(face)->boundary_id());
12360 std::vector<types::boundary_id> boundary_ids(b_ids.begin(), b_ids.end());
12361 return boundary_ids;
12362 }
12363}
12364
12365
12366
12367template <int dim, int spacedim>
12369std::vector<types::manifold_id> Triangulation<dim, spacedim>::get_manifold_ids()
12370 const
12371{
12372 std::set<types::manifold_id> m_ids;
12373 for (const auto &cell : active_cell_iterators())
12374 if (cell->is_locally_owned())
12375 {
12376 m_ids.insert(cell->manifold_id());
12377 for (const auto &face : cell->face_iterators())
12378 m_ids.insert(face->manifold_id());
12379 if (dim == 3)
12380 {
12381 const auto line_indices = internal::TriaAccessorImplementation::
12382 Implementation::get_line_indices_of_cell(*cell);
12383 for (unsigned int l = 0; l < cell->n_lines(); ++l)
12384 {
12385 raw_line_iterator line(this, 0, line_indices[l]);
12386 m_ids.insert(line->manifold_id());
12387 }
12388 }
12389 }
12390 return {m_ids.begin(), m_ids.end()};
12391}
12392
12393#endif
12394/*-----------------------------------------------------------------*/
12395
12396#ifndef DOXYGEN
12397
12398template <int dim, int spacedim>
12401 const Triangulation<dim, spacedim> &other_tria)
12402{
12403 Assert((vertices.empty()) && (levels.empty()) && (faces == nullptr),
12404 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
12405 Assert((other_tria.levels.size() != 0) && (other_tria.vertices.size() != 0) &&
12406 (dim == 1 || other_tria.faces != nullptr),
12407 ExcMessage(
12408 "When calling Triangulation::copy_triangulation(), "
12409 "the target triangulation must be empty but the source "
12410 "triangulation (the argument to this function) must contain "
12411 "something. Here, it seems like the source does not "
12412 "contain anything at all."));
12413
12414
12415 // copy normal elements
12416 vertices = other_tria.vertices;
12417 vertices_used = other_tria.vertices_used;
12418 anisotropic_refinement = other_tria.anisotropic_refinement;
12419 smooth_grid = other_tria.smooth_grid;
12420 reference_cells = other_tria.reference_cells;
12421
12422 if (dim > 1)
12423 faces = std::make_unique<internal::TriangulationImplementation::TriaFaces>(
12424 *other_tria.faces);
12425
12426 for (const auto &p : other_tria.manifolds)
12427 set_manifold(p.first, *p.second);
12428
12429
12430 levels.reserve(other_tria.levels.size());
12431 for (unsigned int level = 0; level < other_tria.levels.size(); ++level)
12432 levels.push_back(
12433 std::make_unique<internal::TriangulationImplementation::TriaLevel>(
12434 *other_tria.levels[level]));
12435
12436 number_cache = other_tria.number_cache;
12437
12438 if (dim == 1)
12439 {
12440 vertex_to_boundary_id_map_1d =
12441 std::make_unique<std::map<unsigned int, types::boundary_id>>(
12442 *other_tria.vertex_to_boundary_id_map_1d);
12443
12444 vertex_to_manifold_id_map_1d =
12445 std::make_unique<std::map<unsigned int, types::manifold_id>>(
12446 *other_tria.vertex_to_manifold_id_map_1d);
12447 }
12448
12449 if (other_tria.policy)
12450 this->policy = other_tria.policy->clone();
12451
12452 // periodic faces
12453 this->periodic_face_pairs_level_0.reserve(
12454 other_tria.periodic_face_pairs_level_0.size());
12455
12456 for (const auto &other_entry : other_tria.periodic_face_pairs_level_0)
12457 {
12458 auto entry = other_entry;
12459 entry.cell[0] =
12460 cell_iterator(this, entry.cell[0]->level(), entry.cell[0]->index());
12461 entry.cell[1] =
12462 cell_iterator(this, entry.cell[1]->level(), entry.cell[1]->index());
12463 periodic_face_pairs_level_0.emplace_back(entry);
12464 }
12465
12466 for (auto [first_cell_, second_cell_and_orientation] :
12467 other_tria.periodic_face_map)
12468 {
12469 auto first_cell = first_cell_; // make copy since key is const
12470 first_cell.first = cell_iterator(this,
12471 first_cell.first->level(),
12472 first_cell.first->index());
12473 second_cell_and_orientation.first.first =
12474 cell_iterator(this,
12475 second_cell_and_orientation.first.first->level(),
12476 second_cell_and_orientation.first.first->index());
12477
12478 this->periodic_face_map[first_cell] = second_cell_and_orientation;
12479 }
12480
12481 // inform those who are listening on other_tria of the copy operation
12482 other_tria.signals.copy(*this);
12483 // also inform all listeners of the current triangulation that the
12484 // triangulation has been created
12485 signals.create();
12486
12487 // note that we need not copy the
12488 // subscriptor!
12489}
12490
12491
12492
12493template <int dim, int spacedim>
12496{
12497 this->update_reference_cells();
12498
12499 if (this->all_reference_cells_are_hyper_cube())
12500 {
12501 this->policy =
12503 dim,
12504 spacedim,
12506 }
12507 else
12508 {
12509 this->policy =
12511 dim,
12512 spacedim,
12514 }
12515}
12516
12517
12518
12519template <int dim, int spacedim>
12522 const std::vector<Point<spacedim>> &v,
12523 const std::vector<CellData<dim>> &cells,
12524 const SubCellData &subcelldata)
12525{
12526 Assert((vertices.empty()) && (levels.empty()) && (faces == nullptr),
12527 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
12528 // check that no forbidden arrays
12529 // are used
12530 Assert(subcelldata.check_consistency(dim), ExcInternalError());
12531
12532 // try to create a triangulation; if this fails, we still want to
12533 // throw an exception but if we just do so we'll get into trouble
12534 // because sometimes other objects are already attached to it:
12535 try
12536 {
12538 create_triangulation(v, cells, subcelldata, *this);
12539 }
12540 catch (...)
12541 {
12542 clear_despite_subscriptions();
12543 throw;
12544 }
12545
12546 reset_policy();
12547
12548 // update our counts of the various elements of a triangulation, and set
12549 // active_cell_indices of all cells
12550 reset_cell_vertex_indices_cache();
12552 *this, levels.size(), number_cache);
12553 reset_active_cell_indices();
12554 reset_global_cell_indices();
12555
12556 // now verify that there are indeed no distorted cells. as per the
12557 // documentation of this class, we first collect all distorted cells
12558 // and then throw an exception if there are any
12559 if (check_for_distorted_cells)
12560 {
12561 DistortedCellList distorted_cells = collect_distorted_coarse_cells(*this);
12562 // throw the array (and fill the various location fields) if
12563 // there are distorted cells. otherwise, just fall off the end
12564 // of the function
12565 AssertThrow(distorted_cells.distorted_cells.empty(), distorted_cells);
12566 }
12567
12568
12569 /*
12570 When the triangulation is a manifold (dim < spacedim) and made of
12571 quadrilaterals, the normal field provided from the map class depends on
12572 the order of the vertices. It may happen that this normal field is
12573 discontinuous. The following code takes care that this is not the case by
12574 setting the cell direction flag on those cell that produce the wrong
12575 orientation.
12576
12577 To determine if 2 neighbors have the same or opposite orientation we use
12578 a truth table. Its entries are indexed by the local indices of the
12579 common face. For example if two elements share a face, and this face is
12580 face 0 for element 0 and face 1 for element 1, then table(0,1) will tell
12581 whether the orientation are the same (true) or opposite (false).
12582
12583 Even though there may be a combinatorial/graph theory argument to get this
12584 table in any dimension, I tested by hand all the different possible cases
12585 in 1D and 2D to generate the table.
12586
12587 Assuming that a surface respects the standard orientation for 2d meshes,
12588 the truth tables are symmetric and their true values are the following
12589
12590 - 1D curves: (0,1)
12591 - 2D surface: (0,1),(0,2),(1,3),(2,3)
12592
12593 We store this data using an n_faces x n_faces full matrix, which is
12594 actually much bigger than the minimal data required, but it makes the code
12595 more readable.
12596
12597 */
12598 if ((dim == spacedim - 1) && all_reference_cells_are_hyper_cube())
12599 {
12602 switch (dim)
12603 {
12604 case 1:
12605 {
12606 const bool values[][2] = {{false, true}, {true, false}};
12607 for (const unsigned int i : GeometryInfo<dim>::face_indices())
12608 for (const unsigned int j : GeometryInfo<dim>::face_indices())
12609 correct(i, j) = values[i][j];
12610 break;
12611 }
12612 case 2:
12613 {
12614 const bool values[][4] = {{false, true, true, false},
12615 {true, false, false, true},
12616 {true, false, false, true},
12617 {false, true, true, false}};
12618 for (const unsigned int i : GeometryInfo<dim>::face_indices())
12619 for (const unsigned int j : GeometryInfo<dim>::face_indices())
12620 correct(i, j) = (values[i][j]);
12621 break;
12622 }
12623 default:
12625 }
12626
12627
12628 std::list<active_cell_iterator> this_round, next_round;
12629 active_cell_iterator neighbor;
12630
12631 // Start with the first cell and (arbitrarily) decide that its
12632 // direction flag should be 'true':
12633 this_round.push_back(begin_active());
12634 begin_active()->set_direction_flag(true);
12635 begin_active()->set_user_flag();
12636
12637 while (this_round.size() > 0)
12638 {
12639 for (const auto &cell : this_round)
12640 {
12641 for (const unsigned int i : cell->face_indices())
12642 {
12643 if (cell->face(i)->at_boundary() == false)
12644 {
12645 // Consider the i'th neighbor of a cell for
12646 // which we have already set the direction:
12647 neighbor = cell->neighbor(i);
12648
12649 const unsigned int nb_of_nb =
12650 cell->neighbor_of_neighbor(i);
12651
12652 // If we already saw this neighboring cell,
12653 // check that everything is fine:
12654 if (neighbor->user_flag_set())
12655 {
12656 Assert(
12657 !(correct(i, nb_of_nb) ^
12658 (neighbor->direction_flag() ==
12659 cell->direction_flag())),
12660 ExcMessage(
12661 "The triangulation you are trying to create is not orientable."));
12662 }
12663 else
12664 {
12665 // We had not seen this cell yet. Set its
12666 // orientation flag (if necessary), mark it
12667 // as treated via the user flag, and push it
12668 // onto the list of cells to start work from
12669 // the next time around:
12670 if (correct(i, nb_of_nb) ^
12671 (neighbor->direction_flag() ==
12672 cell->direction_flag()))
12673 neighbor->set_direction_flag(
12674 !neighbor->direction_flag());
12675 neighbor->set_user_flag();
12676 next_round.push_back(neighbor);
12677 }
12678 }
12679 }
12680 }
12681
12682 // Before we quit let's check that if the triangulation is
12683 // disconnected that we still get all cells by starting
12684 // again from the first cell we haven't treated yet -- that
12685 // is, the first cell of the next disconnected component we
12686 // had not yet touched.
12687 if (next_round.empty())
12688 for (const auto &cell : this->active_cell_iterators())
12689 if (cell->user_flag_set() == false)
12690 {
12691 next_round.push_back(cell);
12692 cell->set_direction_flag(true);
12693 cell->set_user_flag();
12694 break;
12695 }
12696
12697 // Go on to the next round:
12698 next_round.swap(this_round);
12699 next_round.clear();
12700 }
12701 clear_user_flags();
12702 }
12703
12704 // inform all listeners that the triangulation has been created
12705 signals.create();
12706}
12707
12708
12709
12710template <int dim, int spacedim>
12714{
12715 // 1) create coarse grid
12717 construction_data.coarse_cells,
12718 SubCellData());
12719
12720 // create a copy of cell_infos such that we can sort them
12721 auto cell_infos = construction_data.cell_infos;
12722
12723 // sort cell_infos on each level separately
12724 for (auto &cell_info : cell_infos)
12725 std::sort(
12726 cell_info.begin(),
12727 cell_info.end(),
12730 const CellId a_id(a.id);
12731 const CellId b_id(b.id);
12732
12733 const auto a_coarse_cell_index =
12734 this->coarse_cell_id_to_coarse_cell_index(a_id.get_coarse_cell_id());
12735 const auto b_coarse_cell_index =
12736 this->coarse_cell_id_to_coarse_cell_index(b_id.get_coarse_cell_id());
12737
12738 // according to their coarse-cell index and if that is
12739 // same according to their cell id (the result is that
12740 // cells on each level are sorted according to their
12741 // index on that level - what we need in the following
12742 // operations)
12743 if (a_coarse_cell_index != b_coarse_cell_index)
12744 return a_coarse_cell_index < b_coarse_cell_index;
12745 else
12746 return a_id < b_id;
12747 });
12748
12749 // 2) create all levels via a sequence of refinements. note that
12750 // we must make sure that we actually have cells on this level,
12751 // which is not clear in a parallel context for some processes
12752 for (unsigned int level = 0;
12753 level < cell_infos.size() && !cell_infos[level].empty();
12754 ++level)
12755 {
12756 // a) set manifold ids here (because new vertices have to be
12757 // positioned correctly during each refinement step)
12758 {
12759 auto cell = this->begin(level);
12760 auto cell_info = cell_infos[level].begin();
12761 for (; cell_info != cell_infos[level].end(); ++cell_info)
12762 {
12763 while (cell_info->id != cell->id().template to_binary<dim>())
12764 ++cell;
12765 if (dim == 2)
12766 for (const auto face : cell->face_indices())
12767 cell->face(face)->set_manifold_id(
12768 cell_info->manifold_line_ids[face]);
12769 else if (dim == 3)
12770 {
12771 for (const auto face : cell->face_indices())
12772 cell->face(face)->set_manifold_id(
12773 cell_info->manifold_quad_ids[face]);
12774
12775 const auto line_indices = internal::TriaAccessorImplementation::
12776 Implementation::get_line_indices_of_cell(*cell);
12777 for (unsigned int l = 0; l < cell->n_lines(); ++l)
12778 {
12779 raw_line_iterator line(this, 0, line_indices[l]);
12780 line->set_manifold_id(cell_info->manifold_line_ids[l]);
12781 }
12782 }
12783
12784 cell->set_manifold_id(cell_info->manifold_id);
12785 }
12786 }
12787
12788 // b) perform refinement on all levels but on the finest
12789 if (level + 1 != cell_infos.size())
12790 {
12791 // find cells that should have children and mark them for
12792 // refinement
12793 auto coarse_cell = this->begin(level);
12794 auto fine_cell_info = cell_infos[level + 1].begin();
12795
12796 // loop over all cells on the next level
12797 for (; fine_cell_info != cell_infos[level + 1].end();
12798 ++fine_cell_info)
12799 {
12800 // find the parent of that cell
12801 while (
12802 !coarse_cell->id().is_parent_of(CellId(fine_cell_info->id)))
12803 ++coarse_cell;
12804
12805 // set parent for refinement
12806 coarse_cell->set_refine_flag();
12807 }
12808
12809 // execute refinement
12810 ::Triangulation<dim,
12811 spacedim>::execute_coarsening_and_refinement();
12812 }
12813 }
12814
12815 // 3) set boundary ids
12816 for (unsigned int level = 0;
12817 level < cell_infos.size() && !cell_infos[level].empty();
12818 ++level)
12819 {
12820 auto cell = this->begin(level);
12821 auto cell_info = cell_infos[level].begin();
12822 for (; cell_info != cell_infos[level].end(); ++cell_info)
12823 {
12824 // find cell that has the correct cell
12825 while (cell_info->id != cell->id().template to_binary<dim>())
12826 ++cell;
12827
12828 // boundary ids
12829 for (auto pair : cell_info->boundary_ids)
12830 if (cell->face(pair.first)->at_boundary())
12831 cell->face(pair.first)->set_boundary_id(pair.second);
12832 }
12833 }
12834
12835 // inform all listeners that the triangulation has been created
12836 signals.create();
12837}
12838
12839
12840template <int dim, int spacedim>
12843{
12844 AssertThrow(dim + 1 == spacedim,
12845 ExcMessage(
12846 "This function can only be called if dim == spacedim-1."));
12847 for (const auto &cell : this->active_cell_iterators())
12848 cell->set_direction_flag(!cell->direction_flag());
12849}
12850
12851
12852
12853template <int dim, int spacedim>
12856{
12857 Assert(n_cells() > 0,
12858 ExcMessage("Error: An empty Triangulation can not be refined."));
12859
12860 for (const auto &cell : this->active_cell_iterators())
12861 {
12862 cell->clear_coarsen_flag();
12863 cell->set_refine_flag();
12864 cell->set_refine_choice();
12865 }
12866}
12867
12868
12869
12870template <int dim, int spacedim>
12872void Triangulation<dim, spacedim>::refine_global(const unsigned int times)
12873{
12874 for (unsigned int i = 0; i < times; ++i)
12875 {
12876 set_all_refine_flags();
12877 execute_coarsening_and_refinement();
12878 }
12879}
12880
12881
12882
12883template <int dim, int spacedim>
12885void Triangulation<dim, spacedim>::coarsen_global(const unsigned int times)
12886{
12887 for (unsigned int i = 0; i < times; ++i)
12888 {
12889 for (const auto &cell : this->active_cell_iterators())
12890 {
12891 cell->clear_refine_flag();
12892 cell->set_coarsen_flag();
12893 }
12894 execute_coarsening_and_refinement();
12895 }
12896}
12897
12898
12899#endif
12900/*-------------------- refine/coarsen flags -------------------------*/
12901
12902#ifndef DOXYGEN
12903
12904template <int dim, int spacedim>
12906void Triangulation<dim, spacedim>::save_refine_flags(std::vector<bool> &v) const
12907{
12908 v.resize(dim * n_active_cells(), false);
12909 std::vector<bool>::iterator i = v.begin();
12910
12911 for (const auto &cell : this->active_cell_iterators())
12912 for (unsigned int j = 0; j < dim; ++j, ++i)
12913 if (cell->refine_flag_set() & (1 << j))
12914 *i = true;
12915
12916 Assert(i == v.end(), ExcInternalError());
12917}
12918
12919
12920
12921template <int dim, int spacedim>
12923void Triangulation<dim, spacedim>::save_refine_flags(std::ostream &out) const
12924{
12925 std::vector<bool> v;
12926 save_refine_flags(v);
12927 write_bool_vector(mn_tria_refine_flags_begin,
12928 v,
12930 out);
12931}
12932
12933
12934
12935template <int dim, int spacedim>
12938{
12939 std::vector<bool> v;
12940 read_bool_vector(mn_tria_refine_flags_begin, v, mn_tria_refine_flags_end, in);
12941 load_refine_flags(v);
12942}
12943
12944
12945
12946template <int dim, int spacedim>
12948void Triangulation<dim, spacedim>::load_refine_flags(const std::vector<bool> &v)
12949{
12950 AssertThrow(v.size() == dim * n_active_cells(), ExcGridReadError());
12951
12952 std::vector<bool>::const_iterator i = v.begin();
12953 for (const auto &cell : this->active_cell_iterators())
12954 {
12955 unsigned int ref_case = 0;
12956
12957 for (unsigned int j = 0; j < dim; ++j, ++i)
12958 if (*i == true)
12959 ref_case += 1 << j;
12961 ExcGridReadError());
12962 if (ref_case > 0)
12963 cell->set_refine_flag(RefinementCase<dim>(ref_case));
12964 else
12965 cell->clear_refine_flag();
12966 }
12967
12968 Assert(i == v.end(), ExcInternalError());
12969}
12970
12971
12972
12973template <int dim, int spacedim>
12976 std::vector<bool> &v) const
12977{
12978 v.resize(n_active_cells(), false);
12979 std::vector<bool>::iterator i = v.begin();
12980 for (const auto &cell : this->active_cell_iterators())
12981 {
12982 *i = cell->coarsen_flag_set();
12983 ++i;
12984 }
12985
12986 Assert(i == v.end(), ExcInternalError());
12987}
12988
12989
12990
12991template <int dim, int spacedim>
12993void Triangulation<dim, spacedim>::save_coarsen_flags(std::ostream &out) const
12994{
12995 std::vector<bool> v;
12996 save_coarsen_flags(v);
12997 write_bool_vector(mn_tria_coarsen_flags_begin,
12998 v,
13000 out);
13001}
13002
13003
13004
13005template <int dim, int spacedim>
13008{
13009 std::vector<bool> v;
13010 read_bool_vector(mn_tria_coarsen_flags_begin,
13011 v,
13013 in);
13014 load_coarsen_flags(v);
13015}
13016
13017
13018
13019template <int dim, int spacedim>
13022 const std::vector<bool> &v)
13023{
13024 Assert(v.size() == n_active_cells(), ExcGridReadError());
13025
13026 std::vector<bool>::const_iterator i = v.begin();
13027 for (const auto &cell : this->active_cell_iterators())
13028 {
13029 if (*i == true)
13030 cell->set_coarsen_flag();
13031 else
13032 cell->clear_coarsen_flag();
13033 ++i;
13034 }
13035
13036 Assert(i == v.end(), ExcInternalError());
13037}
13038
13039
13040template <int dim, int spacedim>
13043{
13044 return anisotropic_refinement;
13045}
13046
13047
13048#endif
13049
13050namespace internal
13051{
13052 namespace
13053 {
13054 std::vector<std::vector<bool>>
13055 extract_raw_coarsen_flags(
13056 const std::vector<std::unique_ptr<
13058 {
13059 std::vector<std::vector<bool>> coarsen_flags(levels.size());
13060 for (unsigned int level = 0; level < levels.size(); ++level)
13061 coarsen_flags[level] = levels[level]->coarsen_flags;
13062 return coarsen_flags;
13063 }
13064
13065 std::vector<std::vector<std::uint8_t>>
13066 extract_raw_refine_flags(
13067 const std::vector<std::unique_ptr<
13069 {
13070 std::vector<std::vector<std::uint8_t>> refine_flags(levels.size());
13071 for (unsigned int level = 0; level < levels.size(); ++level)
13072 refine_flags[level] = levels[level]->refine_flags;
13073 return refine_flags;
13074 }
13075 } // namespace
13076} // namespace internal
13077
13078
13079/*-------------------- user data/flags -------------------------*/
13080
13081
13082namespace
13083{
13084 // clear user data of cells
13085 void
13086 clear_user_data(std::vector<std::unique_ptr<
13088 {
13089 for (auto &level : levels)
13090 level->cells.clear_user_data();
13091 }
13092
13093
13094 // clear user data of faces
13095 void
13097 {
13098 if (faces->dim == 2)
13099 {
13100 faces->lines.clear_user_data();
13101 }
13102
13103
13104 if (faces->dim == 3)
13105 {
13106 faces->lines.clear_user_data();
13107 faces->quads.clear_user_data();
13108 }
13109 }
13110} // namespace
13111
13112#ifndef DOXYGEN
13113
13114template <int dim, int spacedim>
13117{
13118 // let functions in anonymous namespace do their work
13119 ::clear_user_data(levels);
13120 if (dim > 1)
13121 ::clear_user_data(faces.get());
13122}
13123
13124
13125
13126namespace
13127{
13128 void
13129 clear_user_flags_line(
13130 unsigned int dim,
13131 std::vector<
13132 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
13133 &levels,
13135 {
13136 if (dim == 1)
13137 {
13138 for (const auto &level : levels)
13139 level->cells.clear_user_flags();
13140 }
13141 else if (dim == 2 || dim == 3)
13142 {
13143 faces->lines.clear_user_flags();
13144 }
13145 else
13146 {
13148 }
13149 }
13150} // namespace
13151
13152
13153template <int dim, int spacedim>
13156{
13157 ::clear_user_flags_line(dim, levels, faces.get());
13158}
13159
13160
13161
13162namespace
13163{
13164 void
13165 clear_user_flags_quad(
13166 unsigned int dim,
13167 std::vector<
13168 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
13169 &levels,
13171 {
13172 if (dim == 1)
13173 {
13174 // nothing to do in 1d
13175 }
13176 else if (dim == 2)
13177 {
13178 for (const auto &level : levels)
13179 level->cells.clear_user_flags();
13180 }
13181 else if (dim == 3)
13182 {
13183 faces->quads.clear_user_flags();
13184 }
13185 else
13186 {
13188 }
13189 }
13190} // namespace
13191
13192
13193template <int dim, int spacedim>
13196{
13197 ::clear_user_flags_quad(dim, levels, faces.get());
13198}
13199
13200
13201
13202namespace
13203{
13204 void
13205 clear_user_flags_hex(
13206 unsigned int dim,
13207 std::vector<
13208 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
13209 &levels,
13211 {
13212 if (dim == 1)
13213 {
13214 // nothing to do in 1d
13215 }
13216 else if (dim == 2)
13217 {
13218 // nothing to do in 2d
13219 }
13220 else if (dim == 3)
13221 {
13222 for (const auto &level : levels)
13223 level->cells.clear_user_flags();
13224 }
13225 else
13226 {
13228 }
13229 }
13230} // namespace
13231
13232
13233template <int dim, int spacedim>
13236{
13237 ::clear_user_flags_hex(dim, levels, faces.get());
13238}
13239
13240
13241
13242template <int dim, int spacedim>
13245{
13246 clear_user_flags_line();
13247 clear_user_flags_quad();
13248 clear_user_flags_hex();
13249}
13250
13251
13252
13253template <int dim, int spacedim>
13255void Triangulation<dim, spacedim>::save_user_flags(std::ostream &out) const
13256{
13257 save_user_flags_line(out);
13258
13259 if (dim >= 2)
13260 save_user_flags_quad(out);
13261
13262 if (dim >= 3)
13263 save_user_flags_hex(out);
13264
13265 if (dim >= 4)
13267}
13268
13269
13270
13271template <int dim, int spacedim>
13273void Triangulation<dim, spacedim>::save_user_flags(std::vector<bool> &v) const
13274{
13275 // clear vector and append
13276 // all the stuff later on
13277 v.clear();
13278
13279 std::vector<bool> tmp;
13280
13281 save_user_flags_line(tmp);
13282 v.insert(v.end(), tmp.begin(), tmp.end());
13283
13284 if (dim >= 2)
13285 {
13286 save_user_flags_quad(tmp);
13287 v.insert(v.end(), tmp.begin(), tmp.end());
13288 }
13289
13290 if (dim >= 3)
13291 {
13292 save_user_flags_hex(tmp);
13293 v.insert(v.end(), tmp.begin(), tmp.end());
13294 }
13295
13296 if (dim >= 4)
13298}
13299
13300
13301
13302template <int dim, int spacedim>
13305{
13306 load_user_flags_line(in);
13307
13308 if (dim >= 2)
13309 load_user_flags_quad(in);
13310
13311 if (dim >= 3)
13312 load_user_flags_hex(in);
13313
13314 if (dim >= 4)
13316}
13317
13318
13319
13320template <int dim, int spacedim>
13322void Triangulation<dim, spacedim>::load_user_flags(const std::vector<bool> &v)
13323{
13324 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
13325 std::vector<bool> tmp;
13326
13327 // first extract the flags
13328 // belonging to lines
13329 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
13330 // and set the lines
13331 load_user_flags_line(tmp);
13332
13333 if (dim >= 2)
13334 {
13335 tmp.clear();
13336 tmp.insert(tmp.end(),
13337 v.begin() + n_lines(),
13338 v.begin() + n_lines() + n_quads());
13339 load_user_flags_quad(tmp);
13340 }
13341
13342 if (dim >= 3)
13343 {
13344 tmp.clear();
13345 tmp.insert(tmp.end(),
13346 v.begin() + n_lines() + n_quads(),
13347 v.begin() + n_lines() + n_quads() + n_hexs());
13348 load_user_flags_hex(tmp);
13349 }
13350
13351 if (dim >= 4)
13353}
13354
13355
13356
13357template <int dim, int spacedim>
13360 std::vector<bool> &v) const
13361{
13362 v.resize(n_lines(), false);
13363 std::vector<bool>::iterator i = v.begin();
13364 line_iterator line = begin_line(), endl = end_line();
13365 for (; line != endl; ++line, ++i)
13366 *i = line->user_flag_set();
13367
13368 Assert(i == v.end(), ExcInternalError());
13369}
13370
13371
13372
13373template <int dim, int spacedim>
13375void Triangulation<dim, spacedim>::save_user_flags_line(std::ostream &out) const
13376{
13377 std::vector<bool> v;
13378 save_user_flags_line(v);
13379 write_bool_vector(mn_tria_line_user_flags_begin,
13380 v,
13382 out);
13383}
13384
13385
13386
13387template <int dim, int spacedim>
13390{
13391 std::vector<bool> v;
13392 read_bool_vector(mn_tria_line_user_flags_begin,
13393 v,
13395 in);
13396 load_user_flags_line(v);
13397}
13398
13399
13400
13401template <int dim, int spacedim>
13404 const std::vector<bool> &v)
13405{
13406 Assert(v.size() == n_lines(), ExcGridReadError());
13407
13408 line_iterator line = begin_line(), endl = end_line();
13409 std::vector<bool>::const_iterator i = v.begin();
13410 for (; line != endl; ++line, ++i)
13411 if (*i == true)
13412 line->set_user_flag();
13413 else
13414 line->clear_user_flag();
13415
13416 Assert(i == v.end(), ExcInternalError());
13417}
13418
13419#endif
13420
13421namespace
13422{
13423 template <typename Iterator>
13424 bool
13425 get_user_flag(const Iterator &i)
13426 {
13427 return i->user_flag_set();
13428 }
13429
13430
13431
13432 template <int structdim, int dim, int spacedim>
13433 bool
13435 {
13437 return false;
13438 }
13439
13440
13441
13442 template <typename Iterator>
13443 void
13444 set_user_flag(const Iterator &i)
13445 {
13446 i->set_user_flag();
13447 }
13448
13449
13450
13451 template <int structdim, int dim, int spacedim>
13452 void
13454 {
13456 }
13457
13458
13459
13460 template <typename Iterator>
13461 void
13462 clear_user_flag(const Iterator &i)
13463 {
13464 i->clear_user_flag();
13465 }
13466
13467
13468
13469 template <int structdim, int dim, int spacedim>
13470 void
13471 clear_user_flag(
13473 {
13475 }
13476} // namespace
13477
13478#ifndef DOXYGEN
13479
13480template <int dim, int spacedim>
13483 std::vector<bool> &v) const
13484{
13485 v.resize(n_quads(), false);
13486
13487 if (dim >= 2)
13488 {
13489 std::vector<bool>::iterator i = v.begin();
13490 quad_iterator quad = begin_quad(), endq = end_quad();
13491 for (; quad != endq; ++quad, ++i)
13492 *i = get_user_flag(quad);
13493
13494 Assert(i == v.end(), ExcInternalError());
13495 }
13496}
13497
13498
13499
13500template <int dim, int spacedim>
13502void Triangulation<dim, spacedim>::save_user_flags_quad(std::ostream &out) const
13503{
13504 std::vector<bool> v;
13505 save_user_flags_quad(v);
13506 write_bool_vector(mn_tria_quad_user_flags_begin,
13507 v,
13509 out);
13510}
13511
13512
13513
13514template <int dim, int spacedim>
13517{
13518 std::vector<bool> v;
13519 read_bool_vector(mn_tria_quad_user_flags_begin,
13520 v,
13522 in);
13523 load_user_flags_quad(v);
13524}
13525
13526
13527
13528template <int dim, int spacedim>
13531 const std::vector<bool> &v)
13532{
13533 Assert(v.size() == n_quads(), ExcGridReadError());
13534
13535 if (dim >= 2)
13536 {
13537 quad_iterator quad = begin_quad(), endq = end_quad();
13538 std::vector<bool>::const_iterator i = v.begin();
13539 for (; quad != endq; ++quad, ++i)
13540 if (*i == true)
13541 set_user_flag(quad);
13542 else
13543 clear_user_flag(quad);
13544
13545 Assert(i == v.end(), ExcInternalError());
13546 }
13547}
13548
13549
13550
13551template <int dim, int spacedim>
13554 std::vector<bool> &v) const
13555{
13556 v.resize(n_hexs(), false);
13557
13558 if (dim >= 3)
13559 {
13560 std::vector<bool>::iterator i = v.begin();
13561 hex_iterator hex = begin_hex(), endh = end_hex();
13562 for (; hex != endh; ++hex, ++i)
13563 *i = get_user_flag(hex);
13564
13565 Assert(i == v.end(), ExcInternalError());
13566 }
13567}
13568
13569
13570
13571template <int dim, int spacedim>
13573void Triangulation<dim, spacedim>::save_user_flags_hex(std::ostream &out) const
13574{
13575 std::vector<bool> v;
13576 save_user_flags_hex(v);
13577 write_bool_vector(mn_tria_hex_user_flags_begin,
13578 v,
13580 out);
13581}
13582
13583
13584
13585template <int dim, int spacedim>
13588{
13589 std::vector<bool> v;
13590 read_bool_vector(mn_tria_hex_user_flags_begin,
13591 v,
13593 in);
13594 load_user_flags_hex(v);
13595}
13596
13597
13598
13599template <int dim, int spacedim>
13602 const std::vector<bool> &v)
13603{
13604 Assert(v.size() == n_hexs(), ExcGridReadError());
13605
13606 if (dim >= 3)
13607 {
13608 hex_iterator hex = begin_hex(), endh = end_hex();
13609 std::vector<bool>::const_iterator i = v.begin();
13610 for (; hex != endh; ++hex, ++i)
13611 if (*i == true)
13612 set_user_flag(hex);
13613 else
13614 clear_user_flag(hex);
13615
13616 Assert(i == v.end(), ExcInternalError());
13617 }
13618}
13619
13620
13621
13622template <int dim, int spacedim>
13625 std::vector<unsigned int> &v) const
13626{
13627 // clear vector and append all the
13628 // stuff later on
13629 v.clear();
13630
13631 std::vector<unsigned int> tmp;
13632
13633 save_user_indices_line(tmp);
13634 v.insert(v.end(), tmp.begin(), tmp.end());
13635
13636 if (dim >= 2)
13637 {
13638 save_user_indices_quad(tmp);
13639 v.insert(v.end(), tmp.begin(), tmp.end());
13640 }
13641
13642 if (dim >= 3)
13643 {
13644 save_user_indices_hex(tmp);
13645 v.insert(v.end(), tmp.begin(), tmp.end());
13646 }
13647
13648 if (dim >= 4)
13650}
13651
13652
13653
13654template <int dim, int spacedim>
13657 const std::vector<unsigned int> &v)
13658{
13659 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
13660 std::vector<unsigned int> tmp;
13661
13662 // first extract the indices
13663 // belonging to lines
13664 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
13665 // and set the lines
13666 load_user_indices_line(tmp);
13667
13668 if (dim >= 2)
13669 {
13670 tmp.clear();
13671 tmp.insert(tmp.end(),
13672 v.begin() + n_lines(),
13673 v.begin() + n_lines() + n_quads());
13674 load_user_indices_quad(tmp);
13675 }
13676
13677 if (dim >= 3)
13678 {
13679 tmp.clear();
13680 tmp.insert(tmp.end(),
13681 v.begin() + n_lines() + n_quads(),
13682 v.begin() + n_lines() + n_quads() + n_hexs());
13683 load_user_indices_hex(tmp);
13684 }
13685
13686 if (dim >= 4)
13688}
13689
13690template <int dim, int spacedim>
13692void Triangulation<dim, spacedim>::save(const std::string &filename) const
13693{
13694 // Create boost archive then call alternative version of the save function
13695 std::ofstream ofs(filename);
13696 boost::archive::text_oarchive oa(ofs, boost::archive::no_header);
13697 save(oa, 0);
13698}
13699
13700template <int dim, int spacedim>
13702void Triangulation<dim, spacedim>::load(const std::string &filename)
13703{
13704 // Create boost archive then call alternative version of the load function
13705 std::ifstream ifs(filename);
13706 boost::archive::text_iarchive ia(ifs, boost::archive::no_header);
13707 load(ia, 0);
13708}
13709
13710#endif
13711namespace
13712{
13713 template <typename Iterator>
13714 unsigned int
13715 get_user_index(const Iterator &i)
13716 {
13717 return i->user_index();
13718 }
13719
13720
13721
13722 template <int structdim, int dim, int spacedim>
13723 unsigned int
13724 get_user_index(
13726 {
13729 }
13730
13731
13732
13733 template <typename Iterator>
13734 void
13735 set_user_index(const Iterator &i, const unsigned int x)
13736 {
13737 i->set_user_index(x);
13738 }
13739
13740
13741
13742 template <int structdim, int dim, int spacedim>
13743 void
13744 set_user_index(
13746 const unsigned int)
13747 {
13749 }
13750} // namespace
13751
13752#ifndef DOXYGEN
13753
13754template <int dim, int spacedim>
13757 std::vector<unsigned int> &v) const
13758{
13759 v.resize(n_lines(), 0);
13760 std::vector<unsigned int>::iterator i = v.begin();
13761 line_iterator line = begin_line(), endl = end_line();
13762 for (; line != endl; ++line, ++i)
13763 *i = line->user_index();
13764}
13765
13766
13767
13768template <int dim, int spacedim>
13771 const std::vector<unsigned int> &v)
13772{
13773 Assert(v.size() == n_lines(), ExcGridReadError());
13774
13775 line_iterator line = begin_line(), endl = end_line();
13776 std::vector<unsigned int>::const_iterator i = v.begin();
13777 for (; line != endl; ++line, ++i)
13778 line->set_user_index(*i);
13779}
13780
13781
13782template <int dim, int spacedim>
13785 std::vector<unsigned int> &v) const
13786{
13787 v.resize(n_quads(), 0);
13788
13789 if (dim >= 2)
13790 {
13791 std::vector<unsigned int>::iterator i = v.begin();
13792 quad_iterator quad = begin_quad(), endq = end_quad();
13793 for (; quad != endq; ++quad, ++i)
13794 *i = get_user_index(quad);
13795 }
13796}
13797
13798
13799
13800template <int dim, int spacedim>
13803 const std::vector<unsigned int> &v)
13804{
13805 Assert(v.size() == n_quads(), ExcGridReadError());
13806
13807 if (dim >= 2)
13808 {
13809 quad_iterator quad = begin_quad(), endq = end_quad();
13810 std::vector<unsigned int>::const_iterator i = v.begin();
13811 for (; quad != endq; ++quad, ++i)
13812 set_user_index(quad, *i);
13813 }
13814}
13815
13816
13817template <int dim, int spacedim>
13820 std::vector<unsigned int> &v) const
13821{
13822 v.resize(n_hexs(), 0);
13823
13824 if (dim >= 3)
13825 {
13826 std::vector<unsigned int>::iterator i = v.begin();
13827 hex_iterator hex = begin_hex(), endh = end_hex();
13828 for (; hex != endh; ++hex, ++i)
13829 *i = get_user_index(hex);
13830 }
13831}
13832
13833
13834
13835template <int dim, int spacedim>
13838 const std::vector<unsigned int> &v)
13839{
13840 Assert(v.size() == n_hexs(), ExcGridReadError());
13841
13842 if (dim >= 3)
13843 {
13844 hex_iterator hex = begin_hex(), endh = end_hex();
13845 std::vector<unsigned int>::const_iterator i = v.begin();
13846 for (; hex != endh; ++hex, ++i)
13847 set_user_index(hex, *i);
13848 }
13849}
13850
13851#endif
13852
13853
13854//---------------- user pointers ----------------------------------------//
13855
13856
13857namespace
13858{
13859 template <typename Iterator>
13860 void *
13861 get_user_pointer(const Iterator &i)
13862 {
13863 return i->user_pointer();
13864 }
13865
13866
13867
13868 template <int structdim, int dim, int spacedim>
13869 void *
13870 get_user_pointer(
13872 {
13874 return nullptr;
13875 }
13876
13877
13878
13879 template <typename Iterator>
13880 void
13881 set_user_pointer(const Iterator &i, void *x)
13882 {
13883 i->set_user_pointer(x);
13884 }
13885
13886
13887
13888 template <int structdim, int dim, int spacedim>
13889 void
13890 set_user_pointer(
13892 void *)
13893 {
13895 }
13896} // namespace
13897
13898#ifndef DOXYGEN
13899
13900template <int dim, int spacedim>
13903 std::vector<void *> &v) const
13904{
13905 // clear vector and append all the
13906 // stuff later on
13907 v.clear();
13908
13909 std::vector<void *> tmp;
13910
13911 save_user_pointers_line(tmp);
13912 v.insert(v.end(), tmp.begin(), tmp.end());
13913
13914 if (dim >= 2)
13915 {
13916 save_user_pointers_quad(tmp);
13917 v.insert(v.end(), tmp.begin(), tmp.end());
13918 }
13919
13920 if (dim >= 3)
13921 {
13922 save_user_pointers_hex(tmp);
13923 v.insert(v.end(), tmp.begin(), tmp.end());
13924 }
13925
13926 if (dim >= 4)
13928}
13929
13930
13931
13932template <int dim, int spacedim>
13935 const std::vector<void *> &v)
13936{
13937 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
13938 std::vector<void *> tmp;
13939
13940 // first extract the pointers
13941 // belonging to lines
13942 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
13943 // and set the lines
13944 load_user_pointers_line(tmp);
13945
13946 if (dim >= 2)
13947 {
13948 tmp.clear();
13949 tmp.insert(tmp.end(),
13950 v.begin() + n_lines(),
13951 v.begin() + n_lines() + n_quads());
13952 load_user_pointers_quad(tmp);
13953 }
13954
13955 if (dim >= 3)
13956 {
13957 tmp.clear();
13958 tmp.insert(tmp.end(),
13959 v.begin() + n_lines() + n_quads(),
13960 v.begin() + n_lines() + n_quads() + n_hexs());
13961 load_user_pointers_hex(tmp);
13962 }
13963
13964 if (dim >= 4)
13966}
13967
13968
13969
13970template <int dim, int spacedim>
13973 std::vector<void *> &v) const
13974{
13975 v.resize(n_lines(), nullptr);
13976 std::vector<void *>::iterator i = v.begin();
13977 line_iterator line = begin_line(), endl = end_line();
13978 for (; line != endl; ++line, ++i)
13979 *i = line->user_pointer();
13980}
13981
13982
13983
13984template <int dim, int spacedim>
13987 const std::vector<void *> &v)
13988{
13989 Assert(v.size() == n_lines(), ExcGridReadError());
13990
13991 line_iterator line = begin_line(), endl = end_line();
13992 std::vector<void *>::const_iterator i = v.begin();
13993 for (; line != endl; ++line, ++i)
13994 line->set_user_pointer(*i);
13995}
13996
13997
13998
13999template <int dim, int spacedim>
14002 std::vector<void *> &v) const
14003{
14004 v.resize(n_quads(), nullptr);
14005
14006 if (dim >= 2)
14007 {
14008 std::vector<void *>::iterator i = v.begin();
14009 quad_iterator quad = begin_quad(), endq = end_quad();
14010 for (; quad != endq; ++quad, ++i)
14011 *i = get_user_pointer(quad);
14012 }
14013}
14014
14015
14016
14017template <int dim, int spacedim>
14020 const std::vector<void *> &v)
14021{
14022 Assert(v.size() == n_quads(), ExcGridReadError());
14023
14024 if (dim >= 2)
14025 {
14026 quad_iterator quad = begin_quad(), endq = end_quad();
14027 std::vector<void *>::const_iterator i = v.begin();
14028 for (; quad != endq; ++quad, ++i)
14029 set_user_pointer(quad, *i);
14030 }
14031}
14032
14033
14034template <int dim, int spacedim>
14037 std::vector<void *> &v) const
14038{
14039 v.resize(n_hexs(), nullptr);
14040
14041 if (dim >= 3)
14042 {
14043 std::vector<void *>::iterator i = v.begin();
14044 hex_iterator hex = begin_hex(), endh = end_hex();
14045 for (; hex != endh; ++hex, ++i)
14046 *i = get_user_pointer(hex);
14047 }
14048}
14049
14050
14051
14052template <int dim, int spacedim>
14055 const std::vector<void *> &v)
14056{
14057 Assert(v.size() == n_hexs(), ExcGridReadError());
14058
14059 if (dim >= 3)
14060 {
14061 hex_iterator hex = begin_hex(), endh = end_hex();
14062 std::vector<void *>::const_iterator i = v.begin();
14063 for (; hex != endh; ++hex, ++i)
14064 set_user_pointer(hex, *i);
14065 }
14066}
14067
14068#endif
14069
14070/*------------------------ Cell iterator functions ------------------------*/
14071
14072#ifndef DOXYGEN
14073
14074template <int dim, int spacedim>
14077 Triangulation<dim, spacedim>::begin_raw(const unsigned int level) const
14078{
14079 switch (dim)
14080 {
14081 case 1:
14082 return begin_raw_line(level);
14083 case 2:
14084 return begin_raw_quad(level);
14085 case 3:
14086 return begin_raw_hex(level);
14087 default:
14089 return raw_cell_iterator();
14090 }
14091}
14092
14093
14094
14095template <int dim, int spacedim>
14098 Triangulation<dim, spacedim>::begin(const unsigned int level) const
14099{
14100 switch (dim)
14101 {
14102 case 1:
14103 return begin_line(level);
14104 case 2:
14105 return begin_quad(level);
14106 case 3:
14107 return begin_hex(level);
14108 default:
14109 Assert(false, ExcImpossibleInDim(dim));
14110 return cell_iterator();
14111 }
14112}
14113
14114
14115
14116template <int dim, int spacedim>
14119 Triangulation<dim, spacedim>::begin_active(const unsigned int level) const
14120{
14121 switch (dim)
14122 {
14123 case 1:
14124 return begin_active_line(level);
14125 case 2:
14126 return begin_active_quad(level);
14127 case 3:
14128 return begin_active_hex(level);
14129 default:
14131 return active_cell_iterator();
14132 }
14133}
14134
14135
14136
14137template <int dim, int spacedim>
14141{
14142 const unsigned int level = levels.size() - 1;
14143 if (levels[level]->cells.n_objects() == 0)
14144 return end(level);
14145
14146 // find the last raw iterator on
14147 // this level
14148 raw_cell_iterator ri(const_cast<Triangulation<dim, spacedim> *>(this),
14149 level,
14150 levels[level]->cells.n_objects() - 1);
14151
14152 // then move to the last used one
14153 if (ri->used() == true)
14154 return ri;
14155 while ((--ri).state() == IteratorState::valid)
14156 if (ri->used() == true)
14157 return ri;
14158 return ri;
14159}
14160
14161
14162
14163template <int dim, int spacedim>
14167{
14168 // get the last used cell
14169 cell_iterator cell = last();
14170
14171 if (cell != end())
14172 {
14173 // then move to the last active one
14174 if (cell->is_active() == true)
14175 return cell;
14176 while ((--cell).state() == IteratorState::valid)
14177 if (cell->is_active() == true)
14178 return cell;
14179 }
14180 return cell;
14181}
14182
14183
14184
14185template <int dim, int spacedim>
14189 const CellId &cell_id) const
14190{
14191 Assert(
14192 this->contains_cell(cell_id),
14193 ExcMessage(
14194 "CellId is invalid for this triangulation.\n"
14195 "Either the provided CellId does not correspond to a cell in this "
14196 "triangulation object, or, in case you are using a parallel "
14197 "triangulation, may correspond to an artificial cell that is less "
14198 "refined on this processor. In the case of "
14199 "parallel::fullydistributed::Triangulation, the corresponding coarse "
14200 "cell might not be accessible by the current process."));
14201
14202 cell_iterator cell(
14203 this, 0, coarse_cell_id_to_coarse_cell_index(cell_id.get_coarse_cell_id()));
14204
14205 for (const auto &child_index : cell_id.get_child_indices())
14206 cell = cell->child(static_cast<unsigned int>(child_index));
14207
14208 return cell;
14209}
14210
14211
14212
14213template <int dim, int spacedim>
14215bool Triangulation<dim, spacedim>::contains_cell(const CellId &cell_id) const
14216{
14217 const auto coarse_cell_index =
14218 coarse_cell_id_to_coarse_cell_index(cell_id.get_coarse_cell_id());
14219
14220 if (coarse_cell_index == numbers::invalid_unsigned_int)
14221 return false;
14222
14223 cell_iterator cell(this, 0, coarse_cell_index);
14224
14225 for (const auto &child_index : cell_id.get_child_indices())
14226 {
14227 if (cell->has_children() == false)
14228 return false;
14229 cell = cell->child(static_cast<unsigned int>(child_index));
14230 }
14231
14232 return true;
14233}
14234
14235
14236
14237template <int dim, int spacedim>
14241{
14242 return cell_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14243 -1,
14244 -1);
14245}
14246
14247
14248
14249template <int dim, int spacedim>
14252 Triangulation<dim, spacedim>::end_raw(const unsigned int level) const
14253{
14254 // This function may be called on parallel triangulations on levels
14255 // that exist globally, but not on the local portion of the
14256 // triangulation. In that case, just return the end iterator.
14257 //
14258 // We need to use levels.size() instead of n_levels() because the
14259 // latter function uses the cache, but we need to be able to call
14260 // this function at a time when the cache is not currently up to
14261 // date.
14262 if (level >= levels.size())
14263 {
14264 Assert(level < n_global_levels(),
14265 ExcInvalidLevel(level, n_global_levels()));
14266 return end();
14267 }
14268
14269 // Query whether the given level is valid for the local portion of the
14270 // triangulation.
14271 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14272 if (level < levels.size() - 1)
14273 return begin_raw(level + 1);
14274 else
14275 return end();
14276}
14277
14278
14279template <int dim, int spacedim>
14282 Triangulation<dim, spacedim>::end(const unsigned int level) const
14283{
14284 // This function may be called on parallel triangulations on levels
14285 // that exist globally, but not on the local portion of the
14286 // triangulation. In that case, just return the end iterator.
14287 //
14288 // We need to use levels.size() instead of n_levels() because the
14289 // latter function uses the cache, but we need to be able to call
14290 // this function at a time when the cache is not currently up to
14291 // date.
14292 if (level >= levels.size())
14293 {
14294 Assert(level < n_global_levels(),
14295 ExcInvalidLevel(level, n_global_levels()));
14296 return end();
14297 }
14298
14299 // Query whether the given level is valid for the local portion of the
14300 // triangulation.
14301 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14302 if (level < levels.size() - 1)
14303 return begin(level + 1);
14304 else
14305 return end();
14306}
14307
14308
14309template <int dim, int spacedim>
14312 Triangulation<dim, spacedim>::end_active(const unsigned int level) const
14313{
14314 // This function may be called on parallel triangulations on levels
14315 // that exist globally, but not on the local portion of the
14316 // triangulation. In that case, just return the end iterator.
14317 //
14318 // We need to use levels.size() instead of n_levels() because the
14319 // latter function uses the cache, but we need to be able to call
14320 // this function at a time when the cache is not currently up to
14321 // date.
14322 if (level >= levels.size())
14323 {
14324 Assert(level < n_global_levels(),
14325 ExcInvalidLevel(level, n_global_levels()));
14326 return end();
14327 }
14328
14329 // Query whether the given level is valid for the local portion of the
14330 // triangulation.
14331 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14332 return (level >= levels.size() - 1 ? active_cell_iterator(end()) :
14333 begin_active(level + 1));
14334}
14335
14336
14337
14338template <int dim, int spacedim>
14342 const
14343{
14345 begin(), end());
14346}
14347
14348
14349template <int dim, int spacedim>
14352 active_cell_iterator> Triangulation<dim, spacedim>::
14354{
14355 return IteratorRange<
14357 end());
14358}
14359
14360
14361
14362template <int dim, int spacedim>
14365 cell_iterator> Triangulation<dim, spacedim>::
14366 cell_iterators_on_level(const unsigned int level) const
14367{
14369 begin(level), end(level));
14370}
14371
14372
14373
14374template <int dim, int spacedim>
14377 active_cell_iterator> Triangulation<dim, spacedim>::
14378 active_cell_iterators_on_level(const unsigned int level) const
14379{
14380 return IteratorRange<
14382 begin_active(level), end_active(level));
14383}
14384#endif
14385
14386/*------------------------ Face iterator functions ------------------------*/
14387
14388#ifndef DOXYGEN
14389
14390template <int dim, int spacedim>
14394{
14395 switch (dim)
14396 {
14397 case 1:
14398 Assert(false, ExcImpossibleInDim(1));
14399 return raw_face_iterator();
14400 case 2:
14401 return begin_line();
14402 case 3:
14403 return begin_quad();
14404 default:
14406 return face_iterator();
14407 }
14408}
14409
14410
14411
14412template <int dim, int spacedim>
14416{
14417 switch (dim)
14418 {
14419 case 1:
14420 Assert(false, ExcImpossibleInDim(1));
14421 return raw_face_iterator();
14422 case 2:
14423 return begin_active_line();
14424 case 3:
14425 return begin_active_quad();
14426 default:
14428 return active_face_iterator();
14429 }
14430}
14431
14432
14433
14434template <int dim, int spacedim>
14438{
14439 switch (dim)
14440 {
14441 case 1:
14442 Assert(false, ExcImpossibleInDim(1));
14443 return raw_face_iterator();
14444 case 2:
14445 return end_line();
14446 case 3:
14447 return end_quad();
14448 default:
14450 return raw_face_iterator();
14451 }
14452}
14453
14454
14455
14456template <int dim, int spacedim>
14459 active_face_iterator> Triangulation<dim, spacedim>::
14461{
14462 return IteratorRange<
14464 begin_active_face(), end_face());
14465}
14466
14467/*------------------------ Vertex iterator functions ------------------------*/
14468
14469
14470template <int dim, int spacedim>
14474{
14475 vertex_iterator i =
14476 raw_vertex_iterator(const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
14477 if (i.state() != IteratorState::valid)
14478 return i;
14479 // This loop will end because every triangulation has used vertices.
14480 while (i->used() == false)
14481 if ((++i).state() != IteratorState::valid)
14482 return i;
14483 return i;
14484}
14485
14486
14487
14488template <int dim, int spacedim>
14492{
14493 // every vertex is active
14494 return begin_vertex();
14495}
14496
14497
14498
14499template <int dim, int spacedim>
14503{
14504 return raw_vertex_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14505 -1,
14507}
14508
14509#endif
14510
14511
14512/*------------------------ Line iterator functions ------------------------*/
14513
14514#ifndef DOXYGEN
14515
14516template <int dim, int spacedim>
14519 Triangulation<dim, spacedim>::begin_raw_line(const unsigned int level) const
14520{
14521 // This function may be called on parallel triangulations on levels
14522 // that exist globally, but not on the local portion of the
14523 // triangulation. In that case, just return the end iterator.
14524 //
14525 // We need to use levels.size() instead of n_levels() because the
14526 // latter function uses the cache, but we need to be able to call
14527 // this function at a time when the cache is not currently up to
14528 // date.
14529 if (level >= levels.size())
14530 {
14531 Assert(level < n_global_levels(),
14532 ExcInvalidLevel(level, n_global_levels()));
14533 return end_line();
14534 }
14535
14536 switch (dim)
14537 {
14538 case 1:
14539 // Query whether the given level is valid for the local portion of the
14540 // triangulation.
14541 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14542
14543 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
14544 return end_line();
14545
14546 return raw_line_iterator(
14547 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
14548
14549 default:
14550 Assert(level == 0, ExcFacesHaveNoLevel());
14551 return raw_line_iterator(
14552 const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
14553 }
14554}
14555
14556
14557template <int dim, int spacedim>
14560 Triangulation<dim, spacedim>::begin_line(const unsigned int level) const
14561{
14562 // level is checked in begin_raw
14563 raw_line_iterator ri = begin_raw_line(level);
14564 if (ri.state() != IteratorState::valid)
14565 return ri;
14566 while (ri->used() == false)
14567 if ((++ri).state() != IteratorState::valid)
14568 return ri;
14569 return ri;
14570}
14571
14572
14573
14574template <int dim, int spacedim>
14578 const unsigned int level) const
14579{
14580 // level is checked in begin_raw
14581 line_iterator i = begin_line(level);
14582 if (i.state() != IteratorState::valid)
14583 return i;
14584 while (i->has_children())
14585 if ((++i).state() != IteratorState::valid)
14586 return i;
14587 return i;
14588}
14589
14590
14591
14592template <int dim, int spacedim>
14596{
14597 return raw_line_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14598 -1,
14599 -1);
14600}
14601
14602#endif
14603
14604/*------------------------ Quad iterator functions ------------------------*/
14605
14606#ifndef DOXYGEN
14607
14608template <int dim, int spacedim>
14611 Triangulation<dim, spacedim>::begin_raw_quad(const unsigned int level) const
14612{
14613 // This function may be called on parallel triangulations on levels
14614 // that exist globally, but not on the local portion of the
14615 // triangulation. In that case, just return the end iterator.
14616 //
14617 // We need to use levels.size() instead of n_levels() because the
14618 // latter function uses the cache, but we need to be able to call
14619 // this function at a time when the cache is not currently up to
14620 // date.
14621 if (level >= levels.size())
14622 {
14623 Assert(level < n_global_levels(),
14624 ExcInvalidLevel(level, n_global_levels()));
14625 return end_quad();
14626 }
14627
14628 switch (dim)
14629 {
14630 case 1:
14631 Assert(false, ExcImpossibleInDim(1));
14632 return raw_hex_iterator();
14633 case 2:
14634 {
14635 // Query whether the given level is valid for the local portion of the
14636 // triangulation.
14637 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14638
14639 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
14640 return end_quad();
14641
14642 return raw_quad_iterator(
14643 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
14644 }
14645
14646 case 3:
14647 {
14648 Assert(level == 0, ExcFacesHaveNoLevel());
14649
14650 return raw_quad_iterator(
14651 const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
14652 }
14653
14654
14655 default:
14657 return raw_hex_iterator();
14658 }
14659}
14660
14661
14662
14663template <int dim, int spacedim>
14666 Triangulation<dim, spacedim>::begin_quad(const unsigned int level) const
14667{
14668 // level is checked in begin_raw
14669 raw_quad_iterator ri = begin_raw_quad(level);
14670 if (ri.state() != IteratorState::valid)
14671 return ri;
14672 while (ri->used() == false)
14673 if ((++ri).state() != IteratorState::valid)
14674 return ri;
14675 return ri;
14676}
14677
14678
14679
14680template <int dim, int spacedim>
14684 const unsigned int level) const
14685{
14686 // level is checked in begin_raw
14687 quad_iterator i = begin_quad(level);
14688 if (i.state() != IteratorState::valid)
14689 return i;
14690 while (i->has_children())
14691 if ((++i).state() != IteratorState::valid)
14692 return i;
14693 return i;
14694}
14695
14696
14697
14698template <int dim, int spacedim>
14702{
14703 return raw_quad_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14704 -1,
14705 -1);
14706}
14707
14708#endif
14709
14710/*------------------------ Hex iterator functions ------------------------*/
14711
14712#ifndef DOXYGEN
14713
14714template <int dim, int spacedim>
14717 Triangulation<dim, spacedim>::begin_raw_hex(const unsigned int level) const
14718{
14719 // This function may be called on parallel triangulations on levels
14720 // that exist globally, but not on the local portion of the
14721 // triangulation. In that case, just return the end iterator.
14722 //
14723 // We need to use levels.size() instead of n_levels() because the
14724 // latter function uses the cache, but we need to be able to call
14725 // this function at a time when the cache is not currently up to
14726 // date.
14727 if (level >= levels.size())
14728 {
14729 Assert(level < n_global_levels(),
14730 ExcInvalidLevel(level, n_global_levels()));
14731 return end_hex();
14732 }
14733
14734 switch (dim)
14735 {
14736 case 1:
14737 case 2:
14738 Assert(false, ExcImpossibleInDim(1));
14739 return raw_hex_iterator();
14740 case 3:
14741 {
14742 // Query whether the given level is valid for the local portion of the
14743 // triangulation.
14744 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14745
14746 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
14747 return end_hex();
14748
14749 return raw_hex_iterator(
14750 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
14751 }
14752
14753 default:
14755 return raw_hex_iterator();
14756 }
14757}
14758
14759
14760
14761template <int dim, int spacedim>
14764 Triangulation<dim, spacedim>::begin_hex(const unsigned int level) const
14765{
14766 // level is checked in begin_raw
14767 raw_hex_iterator ri = begin_raw_hex(level);
14768 if (ri.state() != IteratorState::valid)
14769 return ri;
14770 while (ri->used() == false)
14771 if ((++ri).state() != IteratorState::valid)
14772 return ri;
14773 return ri;
14774}
14775
14776
14777
14778template <int dim, int spacedim>
14782{
14783 // level is checked in begin_raw
14784 hex_iterator i = begin_hex(level);
14785 if (i.state() != IteratorState::valid)
14786 return i;
14787 while (i->has_children())
14788 if ((++i).state() != IteratorState::valid)
14789 return i;
14790 return i;
14791}
14792
14793
14794
14795template <int dim, int spacedim>
14799{
14800 return raw_hex_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14801 -1,
14802 -1);
14803}
14804
14805#endif
14806
14807// -------------------------------- number of cells etc ---------------
14808
14809
14810namespace internal
14811{
14812 namespace TriangulationImplementation
14813 {
14814 inline unsigned int
14816 {
14817 return c.n_lines;
14818 }
14819
14820
14821 inline unsigned int
14824 {
14825 return c.n_active_lines;
14826 }
14827
14828
14829 inline unsigned int
14831 {
14832 return c.n_quads;
14833 }
14834
14835
14836 inline unsigned int
14839 {
14840 return c.n_active_quads;
14841 }
14842
14843
14844 inline unsigned int
14846 {
14847 return c.n_hexes;
14848 }
14849
14850
14851 inline unsigned int
14854 {
14855 return c.n_active_hexes;
14856 }
14857 } // namespace TriangulationImplementation
14858} // namespace internal
14859
14860#ifndef DOXYGEN
14861
14862template <int dim, int spacedim>
14864unsigned int Triangulation<dim, spacedim>::n_cells() const
14865{
14867}
14868
14869
14870template <int dim, int spacedim>
14873{
14875}
14876
14877template <int dim, int spacedim>
14881{
14882 return n_active_cells();
14883}
14884
14885template <int dim, int spacedim>
14889{
14890 return n_cells(0);
14891}
14892
14893template <int dim, int spacedim>
14895unsigned int Triangulation<dim, spacedim>::n_faces() const
14896{
14897 switch (dim)
14898 {
14899 case 1:
14900 return n_used_vertices();
14901 case 2:
14902 return n_lines();
14903 case 3:
14904 return n_quads();
14905 default:
14907 }
14908 return 0;
14909}
14910
14911
14912template <int dim, int spacedim>
14915{
14916 switch (dim)
14917 {
14918 case 1:
14919 return n_vertices();
14920 case 2:
14921 return n_raw_lines();
14922 case 3:
14923 return n_raw_quads();
14924 default:
14926 }
14927 return 0;
14928}
14929
14930
14931template <int dim, int spacedim>
14934{
14935 switch (dim)
14936 {
14937 case 1:
14938 return n_used_vertices();
14939 case 2:
14940 return n_active_lines();
14941 case 3:
14942 return n_active_quads();
14943 default:
14945 }
14946 return 0;
14947}
14948
14949
14950template <int dim, int spacedim>
14953 const unsigned int level) const
14954{
14955 switch (dim)
14956 {
14957 case 1:
14958 return n_raw_lines(level);
14959 case 2:
14960 return n_raw_quads(level);
14961 case 3:
14962 return n_raw_hexs(level);
14963 default:
14965 }
14966 return 0;
14967}
14968
14969
14970
14971template <int dim, int spacedim>
14974 const unsigned int level) const
14975{
14976 switch (dim)
14977 {
14978 case 1:
14979 return n_lines(level);
14980 case 2:
14981 return n_quads(level);
14982 case 3:
14983 return n_hexs(level);
14984 default:
14986 }
14987 return 0;
14988}
14989
14990
14991
14992template <int dim, int spacedim>
14995 const unsigned int level) const
14996{
14997 switch (dim)
14998 {
14999 case 1:
15000 return n_active_lines(level);
15001 case 2:
15002 return n_active_quads(level);
15003 case 3:
15004 return n_active_hexs(level);
15005 default:
15007 }
15008 return 0;
15009}
15010
15011
15012template <int dim, int spacedim>
15015{
15016 if (anisotropic_refinement == false)
15017 {
15018 for (unsigned int lvl = 0; lvl < n_global_levels() - 1; ++lvl)
15019 if (n_active_cells(lvl) != 0)
15020 return true;
15021 }
15022 else
15023 {
15024 for (const auto &cell : active_cell_iterators())
15025 for (const auto &i : cell->face_indices())
15026 if (cell->face(i)->has_children())
15027 return true;
15028 }
15029 return false;
15030}
15031
15032
15033template <int dim, int spacedim>
15035unsigned int Triangulation<dim, spacedim>::n_lines() const
15036{
15037 return number_cache.n_lines;
15038}
15039
15040
15041
15042template <int dim, int spacedim>
15045 const unsigned int level) const
15046{
15047 if (dim == 1)
15048 {
15049 AssertIndexRange(level, n_levels());
15050 return levels[level]->cells.n_objects();
15051 }
15052
15053 Assert(false, ExcFacesHaveNoLevel());
15054 return 0;
15055}
15056
15057
15058template <int dim, int spacedim>
15061{
15062 if (dim == 1)
15063 {
15065 return 0;
15066 }
15067
15068 return faces->lines.n_objects();
15069}
15070
15071
15072template <int dim, int spacedim>
15075 const unsigned int level) const
15076{
15077 AssertIndexRange(level, number_cache.n_lines_level.size());
15078 Assert(dim == 1, ExcFacesHaveNoLevel());
15079 return number_cache.n_lines_level[level];
15080}
15081
15082
15083template <int dim, int spacedim>
15086{
15087 return number_cache.n_active_lines;
15088}
15089
15090
15091template <int dim, int spacedim>
15094 const unsigned int level) const
15095{
15096 AssertIndexRange(level, number_cache.n_lines_level.size());
15097 Assert(dim == 1, ExcFacesHaveNoLevel());
15098
15099 return number_cache.n_active_lines_level[level];
15100}
15101#endif
15102
15103template <>
15104unsigned int
15106{
15107 return 0;
15108}
15109
15110
15111template <>
15112unsigned int
15113Triangulation<1, 1>::n_quads(const unsigned int) const
15114{
15115 return 0;
15116}
15117
15118
15119template <>
15120unsigned int
15121Triangulation<1, 1>::n_raw_quads(const unsigned int) const
15122{
15123 return 0;
15124}
15125
15126
15127template <>
15128unsigned int
15129Triangulation<1, 1>::n_raw_hexs(const unsigned int) const
15130{
15131 return 0;
15132}
15133
15134
15135template <>
15136unsigned int
15138{
15139 return 0;
15140}
15141
15142
15143template <>
15144unsigned int
15146{
15147 return 0;
15148}
15149
15150
15151
15152template <>
15153unsigned int
15155{
15156 return 0;
15157}
15158
15159
15160template <>
15161unsigned int
15162Triangulation<1, 2>::n_quads(const unsigned int) const
15163{
15164 return 0;
15165}
15166
15167
15168template <>
15169unsigned int
15170Triangulation<1, 2>::n_raw_quads(const unsigned int) const
15171{
15172 return 0;
15173}
15174
15175
15176template <>
15177unsigned int
15178Triangulation<1, 2>::n_raw_hexs(const unsigned int) const
15179{
15180 return 0;
15181}
15182
15183
15184template <>
15185unsigned int
15187{
15188 return 0;
15189}
15190
15191
15192template <>
15193unsigned int
15195{
15196 return 0;
15197}
15198
15199
15200template <>
15201unsigned int
15203{
15204 return 0;
15205}
15206
15207
15208template <>
15209unsigned int
15210Triangulation<1, 3>::n_quads(const unsigned int) const
15211{
15212 return 0;
15213}
15214
15215
15216template <>
15217unsigned int
15218Triangulation<1, 3>::n_raw_quads(const unsigned int) const
15219{
15220 return 0;
15221}
15222
15223
15224template <>
15225unsigned int
15226Triangulation<1, 3>::n_raw_hexs(const unsigned int) const
15227{
15228 return 0;
15229}
15230
15231
15232template <>
15233unsigned int
15235{
15236 return 0;
15237}
15238
15239
15240template <>
15241unsigned int
15243{
15244 return 0;
15245}
15246
15247#ifndef DOXYGEN
15248
15249template <int dim, int spacedim>
15251unsigned int Triangulation<dim, spacedim>::n_quads() const
15252{
15253 return number_cache.n_quads;
15254}
15255
15256
15257template <int dim, int spacedim>
15260 const unsigned int level) const
15261{
15262 Assert(dim == 2, ExcFacesHaveNoLevel());
15263 AssertIndexRange(level, number_cache.n_quads_level.size());
15264 return number_cache.n_quads_level[level];
15265}
15266
15267#endif
15268
15269template <>
15270unsigned int
15272{
15273 AssertIndexRange(level, n_levels());
15274 return levels[level]->cells.n_objects();
15275}
15276
15277
15278
15279template <>
15280unsigned int
15282{
15283 AssertIndexRange(level, n_levels());
15284 return levels[level]->cells.n_objects();
15285}
15286
15287
15288template <>
15289unsigned int
15290Triangulation<3, 3>::n_raw_quads(const unsigned int) const
15291{
15292 Assert(false, ExcFacesHaveNoLevel());
15293 return 0;
15294}
15295
15296#ifndef DOXYGEN
15297
15298template <int dim, int spacedim>
15301{
15303 return 0;
15304}
15305
15306#endif
15307
15308template <>
15309unsigned int
15311{
15312 return faces->quads.n_objects();
15313}
15314
15315#ifndef DOXYGEN
15316
15317template <int dim, int spacedim>
15320{
15321 return number_cache.n_active_quads;
15322}
15323
15324
15325template <int dim, int spacedim>
15328 const unsigned int level) const
15329{
15330 AssertIndexRange(level, number_cache.n_quads_level.size());
15331 Assert(dim == 2, ExcFacesHaveNoLevel());
15332
15333 return number_cache.n_active_quads_level[level];
15334}
15335
15336
15337template <int dim, int spacedim>
15339unsigned int Triangulation<dim, spacedim>::n_hexs() const
15340{
15341 return 0;
15342}
15343
15344
15345
15346template <int dim, int spacedim>
15348unsigned int Triangulation<dim, spacedim>::n_hexs(const unsigned int) const
15349{
15350 return 0;
15351}
15352
15353
15354
15355template <int dim, int spacedim>
15357unsigned int Triangulation<dim, spacedim>::n_raw_hexs(const unsigned int) const
15358{
15359 return 0;
15360}
15361
15362
15363template <int dim, int spacedim>
15366{
15367 return 0;
15368}
15369
15370
15371
15372template <int dim, int spacedim>
15375 const unsigned int) const
15376{
15377 return 0;
15378}
15379
15380#endif
15381
15382template <>
15383unsigned int
15385{
15386 return number_cache.n_hexes;
15387}
15388
15389
15390
15391template <>
15392unsigned int
15393Triangulation<3, 3>::n_hexs(const unsigned int level) const
15394{
15395 AssertIndexRange(level, number_cache.n_hexes_level.size());
15396
15397 return number_cache.n_hexes_level[level];
15398}
15399
15400
15401
15402template <>
15403unsigned int
15405{
15406 AssertIndexRange(level, n_levels());
15407 return levels[level]->cells.n_objects();
15408}
15409
15410
15411template <>
15412unsigned int
15414{
15415 return number_cache.n_active_hexes;
15416}
15417
15418
15419
15420template <>
15421unsigned int
15423{
15424 AssertIndexRange(level, number_cache.n_hexes_level.size());
15425
15426 return number_cache.n_active_hexes_level[level];
15427}
15428
15429#ifndef DOXYGEN
15430
15431template <int dim, int spacedim>
15434{
15435 return std::count(vertices_used.begin(), vertices_used.end(), true);
15436}
15437
15438
15439
15440template <int dim, int spacedim>
15442const std::vector<bool> &Triangulation<dim, spacedim>::get_used_vertices() const
15443{
15444 return vertices_used;
15445}
15446
15447#endif
15448
15449template <>
15450unsigned int
15452{
15453 return 2;
15454}
15455
15456
15457
15458template <>
15459unsigned int
15461{
15462 return 2;
15463}
15464
15465
15466template <>
15467unsigned int
15469{
15470 return 2;
15471}
15472
15473#ifndef DOXYGEN
15474
15475template <int dim, int spacedim>
15478{
15479 cell_iterator cell = begin(0),
15480 endc = (n_levels() > 1 ? begin(1) : cell_iterator(end()));
15481 // store the largest index of the
15482 // vertices used on level 0
15483 unsigned int max_vertex_index = 0;
15484 for (; cell != endc; ++cell)
15485 for (const unsigned int vertex : GeometryInfo<dim>::vertex_indices())
15486 if (cell->vertex_index(vertex) > max_vertex_index)
15487 max_vertex_index = cell->vertex_index(vertex);
15488
15489 // store the number of times a cell
15490 // touches a vertex. An unsigned
15491 // int should suffice, even for
15492 // larger dimensions
15493 std::vector<unsigned short int> usage_count(max_vertex_index + 1, 0);
15494 // touch a vertex's usage count
15495 // every time we find an adjacent
15496 // element
15497 for (cell = begin(); cell != endc; ++cell)
15498 for (const unsigned int vertex : GeometryInfo<dim>::vertex_indices())
15499 ++usage_count[cell->vertex_index(vertex)];
15500
15502 static_cast<unsigned int>(
15503 *std::max_element(usage_count.begin(), usage_count.end())));
15504}
15505
15506
15507
15508template <int dim, int spacedim>
15512{
15514}
15515
15516
15517
15518template <int dim, int spacedim>
15521{
15522 return *this;
15523}
15524
15525
15526
15527template <int dim, int spacedim>
15531{
15532 return *this;
15533}
15534
15535
15536
15537template <int dim, int spacedim>
15541 &periodicity_vector)
15542{
15543 periodic_face_pairs_level_0.insert(periodic_face_pairs_level_0.end(),
15544 periodicity_vector.begin(),
15545 periodicity_vector.end());
15546
15547 // Now initialize periodic_face_map
15548 update_periodic_face_map();
15549}
15550
15551
15552
15553template <int dim, int spacedim>
15555const typename std::map<
15556 std::pair<typename Triangulation<dim, spacedim>::cell_iterator, unsigned int>,
15557 std::pair<std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
15558 unsigned int>,
15559 unsigned char>>
15561{
15562 return periodic_face_map;
15563}
15564
15565
15566
15567template <int dim, int spacedim>
15570{
15571 // Call our version of prepare_coarsening_and_refinement() even if a derived
15572 // class like parallel::distributed::Triangulation overrides it. Their
15573 // function will be called in their execute_coarsening_and_refinement()
15574 // function. Even in a distributed computation our job here is to reconstruct
15575 // the local part of the mesh and as such checking our flags is enough.
15577
15578 // verify a case with which we have had
15579 // some difficulty in the past (see the
15580 // deal.II/coarsening_* tests)
15581 if (smooth_grid & limit_level_difference_at_vertices)
15582 Assert(satisfies_level1_at_vertex_rule(*this) == true, ExcInternalError());
15583
15584 // Inform all listeners about beginning of refinement.
15585 signals.pre_refinement();
15586
15587 execute_coarsening();
15588
15589 const DistortedCellList cells_with_distorted_children = execute_refinement();
15590
15591 reset_cell_vertex_indices_cache();
15592
15593 // verify a case with which we have had
15594 // some difficulty in the past (see the
15595 // deal.II/coarsening_* tests)
15596 if (smooth_grid & limit_level_difference_at_vertices)
15597 Assert(satisfies_level1_at_vertex_rule(*this) == true, ExcInternalError());
15598
15599 // finally build up neighbor connectivity information, and set
15600 // active cell indices
15601 this->policy->update_neighbors(*this);
15602 reset_active_cell_indices();
15603
15604 reset_global_cell_indices(); // TODO: better place?
15605
15606 // Inform all listeners about end of refinement.
15607 signals.post_refinement();
15608
15609 AssertThrow(cells_with_distorted_children.distorted_cells.empty(),
15610 cells_with_distorted_children);
15611
15612 update_periodic_face_map();
15613
15614# ifdef DEBUG
15615
15616 // In debug mode, we want to check for some consistency of the
15617 // result of this function. Because there are multiple exit
15618 // paths, put this check into a ScopeExit object that is
15619 // executed on each of the exit paths.
15620 //
15621 // Specifically, check on exit of this function that if a quad
15622 // cell has been refined, all of its children have neighbors
15623 // in all directions in which the parent cell has neighbors as
15624 // well. The children's neighbors are either the parent
15625 // neighbor or the parent neighbor's children, or simply one of
15626 // the other children of the current cell. This check is
15627 // useful because if one creates a triangulation with an
15628 // inconsistently ordered set of cells (e.g., because one has
15629 // forgotten to call GridTools::consistently_order_cells()),
15630 // then this relatively simple invariant is violated -- so the
15631 // check here can be used to catch that case, at least
15632 // sometimes.
15633 //
15634 // In 1d, this situation cannot happen. In 3d, we have explicit
15635 // orientation flags to ensure that it is not necessary to re-orient
15636 // cells at the beginning. But in both cases, the invariant should
15637 // still hold as long as the cell is a hypercube.
15638 for (const auto &cell : cell_iterators())
15639 {
15640 if (cell->has_children() && cell->reference_cell().is_hyper_cube())
15641 for (const unsigned int f : cell->face_indices())
15642 if (cell->at_boundary(f) == false)
15643 {
15644 for (const auto &child : cell->child_iterators())
15645 {
15646 Assert(
15647 child->at_boundary(f) == false,
15648 ExcMessage(
15649 "We ended up with a triangulation whose child cells "
15650 "are not connected to their neighbors as expected. "
15651 "When you created the triangulation, did you forget "
15652 "to call GridTools::consistently_order_cells() "
15653 "before calling Triangulation::create_triangulation()?"));
15654 }
15655 }
15656 }
15657# endif
15658}
15659
15660
15661
15662template <int dim, int spacedim>
15665{
15666 unsigned int active_cell_index = 0;
15667 for (raw_cell_iterator cell = begin_raw(); cell != end(); ++cell)
15668 if ((cell->used() == false) || cell->has_children())
15669 cell->set_active_cell_index(numbers::invalid_unsigned_int);
15670 else
15671 {
15672 cell->set_active_cell_index(active_cell_index);
15673 ++active_cell_index;
15674 }
15675
15676 Assert(active_cell_index == n_active_cells(), ExcInternalError());
15677}
15678
15679
15680
15681template <int dim, int spacedim>
15684{
15685 {
15687 for (const auto &cell : active_cell_iterators())
15688 cell->set_global_active_cell_index(cell_index++);
15689 }
15690
15691 for (unsigned int l = 0; l < levels.size(); ++l)
15692 {
15694 for (const auto &cell : cell_iterators_on_level(l))
15695 cell->set_global_level_cell_index(cell_index++);
15696 }
15697}
15698
15699
15700
15701template <int dim, int spacedim>
15704{
15705 for (unsigned int l = 0; l < levels.size(); ++l)
15706 {
15707 constexpr unsigned int max_vertices_per_cell = 1 << dim;
15708 std::vector<unsigned int> &cache = levels[l]->cell_vertex_indices_cache;
15709 cache.clear();
15710 cache.resize(levels[l]->refine_flags.size() * max_vertices_per_cell,
15712 for (const auto &cell : cell_iterators_on_level(l))
15713 {
15714 const unsigned int my_index = cell->index() * max_vertices_per_cell;
15715
15716 // to reduce the cost of this function when passing down into quads,
15717 // then lines, then vertices, we use a more low-level access method
15718 // for hexahedral cells, where we can streamline most of the logic
15719 const ReferenceCell ref_cell = cell->reference_cell();
15720 if (ref_cell == ReferenceCells::Hexahedron)
15721 for (unsigned int face = 4; face < 6; ++face)
15722 {
15723 const auto face_iter = cell->face(face);
15724 const std::array<bool, 2> line_orientations{
15725 {face_iter->line_orientation(0),
15726 face_iter->line_orientation(1)}};
15727 std::array<unsigned int, 4> raw_vertex_indices{
15728 {face_iter->line(0)->vertex_index(1 - line_orientations[0]),
15729 face_iter->line(1)->vertex_index(1 - line_orientations[1]),
15730 face_iter->line(0)->vertex_index(line_orientations[0]),
15731 face_iter->line(1)->vertex_index(line_orientations[1])}};
15732
15733 const unsigned char combined_orientation =
15734 levels[l]->face_orientations.get_combined_orientation(
15735 cell->index() * GeometryInfo<3>::faces_per_cell + face);
15736 std::array<unsigned int, 4> vertex_order{
15737 {ref_cell.standard_to_real_face_vertex(0,
15738 face,
15739 combined_orientation),
15741 face,
15742 combined_orientation),
15744 face,
15745 combined_orientation),
15747 3, face, combined_orientation)}};
15748
15749 const unsigned int index = my_index + 4 * (face - 4);
15750 for (unsigned int i = 0; i < 4; ++i)
15751 cache[index + i] = raw_vertex_indices[vertex_order[i]];
15752 }
15753 else if (ref_cell == ReferenceCells::Quadrilateral)
15754 {
15755 const std::array<bool, 2> line_orientations{
15756 {cell->line_orientation(0), cell->line_orientation(1)}};
15757 std::array<unsigned int, 4> raw_vertex_indices{
15758 {cell->line(0)->vertex_index(1 - line_orientations[0]),
15759 cell->line(1)->vertex_index(1 - line_orientations[1]),
15760 cell->line(0)->vertex_index(line_orientations[0]),
15761 cell->line(1)->vertex_index(line_orientations[1])}};
15762 for (unsigned int i = 0; i < 4; ++i)
15763 cache[my_index + i] = raw_vertex_indices[i];
15764 }
15765 else
15766 for (const unsigned int i : cell->vertex_indices())
15767 cache[my_index + i] = internal::TriaAccessorImplementation::
15768 Implementation::vertex_index(*cell, i);
15769 }
15770 }
15771}
15772
15773
15774
15775template <int dim, int spacedim>
15778{
15779 // first empty the currently stored objects
15780 periodic_face_map.clear();
15781
15782 typename std::vector<
15784 for (it = periodic_face_pairs_level_0.begin();
15785 it != periodic_face_pairs_level_0.end();
15786 ++it)
15787 {
15788 update_periodic_face_map_recursively<dim, spacedim>(it->cell[0],
15789 it->cell[1],
15790 it->face_idx[0],
15791 it->face_idx[1],
15792 it->orientation,
15793 periodic_face_map);
15794
15795 const auto face_reference_cell =
15796 it->cell[0]->reference_cell().face_reference_cell(it->face_idx[0]);
15797 // for the other way, we need to invert the orientation
15798 update_periodic_face_map_recursively<dim, spacedim>(
15799 it->cell[1],
15800 it->cell[0],
15801 it->face_idx[1],
15802 it->face_idx[0],
15803 face_reference_cell.get_inverse_combined_orientation(it->orientation),
15804 periodic_face_map);
15805 }
15806
15807 // check consistency
15808 typename std::map<std::pair<cell_iterator, unsigned int>,
15809 std::pair<std::pair<cell_iterator, unsigned int>,
15810 unsigned char>>::const_iterator it_test;
15811 for (it_test = periodic_face_map.begin(); it_test != periodic_face_map.end();
15812 ++it_test)
15813 {
15815 it_test->first.first;
15817 it_test->second.first.first;
15818 if (cell_1->level() == cell_2->level())
15819 {
15820 // if both cells have the same neighbor, then the same pair
15821 // order swapped has to be in the map
15822 Assert(periodic_face_map[it_test->second.first].first ==
15823 it_test->first,
15825 }
15826 }
15827}
15828
15829
15830
15831template <int dim, int spacedim>
15834{
15835 std::set<ReferenceCell> reference_cells_set;
15836 for (auto cell : active_cell_iterators())
15837 if (cell->is_locally_owned())
15838 reference_cells_set.insert(cell->reference_cell());
15839
15840 this->reference_cells =
15841 std::vector<ReferenceCell>(reference_cells_set.begin(),
15842 reference_cells_set.end());
15843}
15844
15845
15846
15847template <int dim, int spacedim>
15849const std::vector<ReferenceCell>
15851{
15852 return this->reference_cells;
15853}
15854
15855
15856
15857template <int dim, int spacedim>
15860{
15861 Assert(this->reference_cells.size() > 0,
15862 ExcMessage("You can't ask about the kinds of reference "
15863 "cells used by this triangulation if the "
15864 "triangulation doesn't yet have any cells in it."));
15865 return (this->reference_cells.size() == 1 &&
15866 this->reference_cells[0].is_hyper_cube());
15867}
15868
15869
15870
15871template <int dim, int spacedim>
15874{
15875 Assert(this->reference_cells.size() > 0,
15876 ExcMessage("You can't ask about the kinds of reference "
15877 "cells used by this triangulation if the "
15878 "triangulation doesn't yet have any cells in it."));
15879 return (this->reference_cells.size() == 1 &&
15880 this->reference_cells[0].is_simplex());
15881}
15882
15883
15884
15885template <int dim, int spacedim>
15888{
15889 Assert(this->reference_cells.size() > 0,
15890 ExcMessage("You can't ask about the kinds of reference "
15891 "cells used by this triangulation if the "
15892 "triangulation doesn't yet have any cells in it."));
15893 return reference_cells.size() > 1 ||
15894 ((reference_cells[0].is_hyper_cube() == false) &&
15895 (reference_cells[0].is_simplex() == false));
15896}
15897
15898
15899
15900template <int dim, int spacedim>
15903 const std::function<std::vector<char>(const cell_iterator &,
15904 const ::CellStatus)>
15905 &pack_callback,
15906 const bool returns_variable_size_data)
15907{
15908 unsigned int handle = numbers::invalid_unsigned_int;
15909
15910 // Add new callback function to the corresponding register.
15911 // Encode handles according to returns_variable_size_data.
15912 if (returns_variable_size_data)
15913 {
15914 handle = 2 * this->cell_attached_data.pack_callbacks_variable.size();
15915 this->cell_attached_data.pack_callbacks_variable.push_back(pack_callback);
15916 }
15917 else
15918 {
15919 handle = 2 * this->cell_attached_data.pack_callbacks_fixed.size() + 1;
15920 this->cell_attached_data.pack_callbacks_fixed.push_back(pack_callback);
15921 }
15922
15923 // Increase overall counter.
15924 ++this->cell_attached_data.n_attached_data_sets;
15925
15926 return handle;
15927}
15928
15929
15930
15931template <int dim, int spacedim>
15934 const unsigned int handle,
15935 const std::function<
15936 void(const cell_iterator &,
15937 const ::CellStatus,
15938 const boost::iterator_range<std::vector<char>::const_iterator> &)>
15939 &unpack_callback)
15940{
15941 // perform unpacking
15942 this->data_serializer.unpack_data(this->local_cell_relations,
15943 handle,
15944 unpack_callback);
15945
15946 // decrease counters
15947 --this->cell_attached_data.n_attached_data_sets;
15948 if (this->cell_attached_data.n_attached_deserialize > 0)
15949 --this->cell_attached_data.n_attached_deserialize;
15950
15951 // important: only remove data if we are not in the deserialization
15952 // process. There, each SolutionTransfer registers and unpacks before
15953 // the next one does this, so n_attached_data_sets is only 1 here. This
15954 // would destroy the saved data before the second SolutionTransfer can
15955 // get it. This created a bug that is documented in
15956 // tests/mpi/p4est_save_03 with more than one SolutionTransfer.
15957
15958 if (this->cell_attached_data.n_attached_data_sets == 0 &&
15959 this->cell_attached_data.n_attached_deserialize == 0)
15960 {
15961 // everybody got their data, time for cleanup!
15962 this->cell_attached_data.pack_callbacks_fixed.clear();
15963 this->cell_attached_data.pack_callbacks_variable.clear();
15964 this->data_serializer.clear();
15965
15966 // reset all cell_status entries after coarsening/refinement
15967 for (auto &cell_rel : this->local_cell_relations)
15968 cell_rel.second = ::CellStatus::cell_will_persist;
15969 }
15970}
15971
15972
15973
15974template <int dim, int spacedim>
15977 const unsigned int global_first_cell,
15978 const unsigned int global_num_cells,
15979 const std::string &filename) const
15980{
15981 // cast away constness
15982 auto tria = const_cast<Triangulation<dim, spacedim> *>(this);
15983
15984 if (this->cell_attached_data.n_attached_data_sets > 0)
15985 {
15986 // pack attached data first
15988 tria->local_cell_relations,
15989 tria->cell_attached_data.pack_callbacks_fixed,
15990 tria->cell_attached_data.pack_callbacks_variable,
15991 this->get_communicator());
15992
15993 // then store buffers in file
15994 tria->data_serializer.save(global_first_cell,
15995 global_num_cells,
15996 filename,
15997 this->get_communicator());
15998
15999 // and release the memory afterwards
16000 tria->data_serializer.clear();
16001 }
16002
16003 // clear all of the callback data, as explained in the documentation of
16004 // register_data_attach()
16005 {
16006 tria->cell_attached_data.n_attached_data_sets = 0;
16007 tria->cell_attached_data.pack_callbacks_fixed.clear();
16008 tria->cell_attached_data.pack_callbacks_variable.clear();
16009 }
16010}
16011
16012
16013template <int dim, int spacedim>
16016 const unsigned int global_first_cell,
16017 const unsigned int global_num_cells,
16018 const unsigned int local_num_cells,
16019 const std::string &filename,
16020 const unsigned int n_attached_deserialize_fixed,
16021 const unsigned int n_attached_deserialize_variable)
16022{
16023 // load saved data, if any was stored
16024 if (this->cell_attached_data.n_attached_deserialize > 0)
16025 {
16026 this->data_serializer.load(global_first_cell,
16027 global_num_cells,
16028 local_num_cells,
16029 filename,
16030 n_attached_deserialize_fixed,
16031 n_attached_deserialize_variable,
16032 this->get_communicator());
16033
16034 this->data_serializer.unpack_cell_status(this->local_cell_relations);
16035
16036 // the CellStatus of all stored cells should always be
16037 // CellStatus::cell_will_persist.
16038 for (const auto &cell_rel : this->local_cell_relations)
16039 {
16040 (void)cell_rel;
16041 Assert((cell_rel.second == // cell_status
16044 }
16045 }
16046}
16047
16048
16049template <int dim, int spacedim>
16052{
16053 levels.clear();
16054 faces.reset();
16055
16056 vertices.clear();
16057 vertices_used.clear();
16058
16059 manifolds.clear();
16060
16061 // In 1d, also reset vertex-to-(boundary|manifold) maps to empty maps
16062 if (dim == 1)
16063 {
16064 Assert(vertex_to_boundary_id_map_1d != nullptr, ExcInternalError());
16065 vertex_to_boundary_id_map_1d->clear();
16066
16067 Assert(vertex_to_manifold_id_map_1d != nullptr, ExcInternalError());
16068 vertex_to_manifold_id_map_1d->clear();
16069 }
16070 else
16071 {
16072 // For dim>1, these maps should simply not exist.
16073 Assert(vertex_to_boundary_id_map_1d == nullptr, ExcInternalError());
16074 Assert(vertex_to_manifold_id_map_1d == nullptr, ExcInternalError());
16075 }
16076
16077
16079}
16080
16081
16082
16083template <int dim, int spacedim>
16087{
16088 const DistortedCellList cells_with_distorted_children =
16089 this->policy->execute_refinement(*this, check_for_distorted_cells);
16090
16091
16092
16093 // re-compute number of lines
16095 *this, levels.size(), number_cache);
16096
16097# ifdef DEBUG
16098 for (const auto &level : levels)
16099 monitor_memory(level->cells, dim);
16100
16101 // check whether really all refinement flags are reset (also of
16102 // previously non-active cells which we may not have touched. If the
16103 // refinement flag of a non-active cell is set, something went wrong
16104 // since the cell-accessors should have caught this)
16105 for (const auto &cell : this->cell_iterators())
16106 Assert(!cell->refine_flag_set(), ExcInternalError());
16107# endif
16108
16109 return cells_with_distorted_children;
16110}
16111
16112
16113
16114template <int dim, int spacedim>
16117{
16118 // first find out if there are any cells at all to be coarsened in the
16119 // loop below
16120 const cell_iterator endc = end();
16121 bool do_coarsen = false;
16122 if (levels.size() >= 2)
16123 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
16124 if (!cell->is_active() && cell->child(0)->coarsen_flag_set())
16125 {
16126 do_coarsen = true;
16127 break;
16128 }
16129
16130 if (!do_coarsen)
16131 return;
16132
16133 // create a vector counting for each line and quads how many cells contain
16134 // the respective object. this is used later to decide which lines can be
16135 // deleted after coarsening a cell.
16136 std::vector<unsigned int> line_cell_count(dim > 1 ? this->n_raw_lines() : 0);
16137 std::vector<unsigned int> quad_cell_count(dim > 2 ? this->n_raw_quads() : 0);
16138 if (dim > 1)
16139 for (const auto &cell : this->cell_iterators())
16140 {
16141 if (dim > 2)
16142 {
16143 const auto line_indices = internal::TriaAccessorImplementation::
16144 Implementation::get_line_indices_of_cell(*cell);
16145 // avoid a compiler warning by fixing the max number of
16146 // loop iterations to 12
16147 const unsigned int n_lines = std::min(cell->n_lines(), 12u);
16148 for (unsigned int l = 0; l < n_lines; ++l)
16149 ++line_cell_count[line_indices[l]];
16150 for (const unsigned int q : cell->face_indices())
16151 ++quad_cell_count[cell->face_index(q)];
16152 }
16153 else
16154 for (unsigned int l = 0; l < cell->n_lines(); ++l)
16155 ++line_cell_count[cell->line(l)->index()];
16156 }
16157
16158 // Since the loop goes over used cells we only need not worry about
16159 // deleting some cells since the ++operator will then just hop over them
16160 // if we should hit one. Do the loop in the reverse way since we may
16161 // only delete some cells if their neighbors have already been deleted
16162 // (if the latter are on a higher level for example). In effect, only
16163 // those cells are deleted of which originally all children were flagged
16164 // and for which all children are on the same refinement level. Note
16165 // that because of the effects of
16166 // @p{fix_coarsen_flags}, of a cell either all or no children must be
16167 // flagged for coarsening, so it is ok to only check the first child
16168 //
16169 // since we delete the *children* of cells, we can ignore cells on the
16170 // highest level, i.e., level must be less than or equal to
16171 // n_levels()-2.
16172 if (levels.size() >= 2)
16173 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
16174 if (!cell->is_active() && cell->child(0)->coarsen_flag_set())
16175 {
16176 for (unsigned int child = 0; child < cell->n_children(); ++child)
16177 {
16178 Assert(cell->child(child)->coarsen_flag_set(),
16180 cell->child(child)->clear_coarsen_flag();
16181 }
16182 // inform all listeners that cell coarsening is going to happen
16183 signals.pre_coarsening_on_cell(cell);
16184 // use a separate function, since this is dimension specific
16185 this->policy->delete_children(*this,
16186 cell,
16187 line_cell_count,
16188 quad_cell_count);
16189 }
16190
16191 // re-compute number of lines and quads
16193 *this, levels.size(), number_cache);
16194}
16195
16196
16197
16198template <int dim, int spacedim>
16201{
16202 // copy a piece of code from prepare_coarsening_and_refinement that
16203 // ensures that the level difference at vertices is limited if so
16204 // desired. we need this code here since at least in 1d we don't
16205 // call the dimension-independent version of
16206 // prepare_coarsening_and_refinement function. in 2d and 3d, having
16207 // this hunk here makes our lives a bit easier as well as it takes
16208 // care of these cases earlier than it would otherwise happen.
16209 //
16210 // the main difference to the code in p_c_and_r is that here we
16211 // absolutely have to make sure that we get things right, i.e. that
16212 // in particular we set flags right if
16213 // limit_level_difference_at_vertices is set. to do so we iterate
16214 // until the flags don't change any more
16215 auto previous_coarsen_flags = internal::extract_raw_coarsen_flags(levels);
16216
16217 bool continue_iterating = true;
16218
16219 do
16220 {
16221 if (smooth_grid & limit_level_difference_at_vertices)
16222 {
16223 Assert(!anisotropic_refinement,
16224 ExcMessage("In case of anisotropic refinement the "
16225 "limit_level_difference_at_vertices flag for "
16226 "mesh smoothing must not be set!"));
16227
16228 // store highest level one of the cells adjacent to a vertex
16229 // belongs to
16230 std::vector<int> vertex_level(vertices.size(), 0);
16231 for (const auto &cell : this->active_cell_iterators())
16232 {
16233 if (cell->refine_flag_set())
16234 for (const unsigned int vertex :
16236 vertex_level[cell->vertex_index(vertex)] =
16237 std::max(vertex_level[cell->vertex_index(vertex)],
16238 cell->level() + 1);
16239 else if (!cell->coarsen_flag_set())
16240 for (const unsigned int vertex :
16242 vertex_level[cell->vertex_index(vertex)] =
16243 std::max(vertex_level[cell->vertex_index(vertex)],
16244 cell->level());
16245 else
16246 {
16247 // if coarsen flag is set then tentatively assume
16248 // that the cell will be coarsened. this isn't
16249 // always true (the coarsen flag could be removed
16250 // again) and so we may make an error here. we try
16251 // to correct this by iterating over the entire
16252 // process until we are converged
16253 Assert(cell->coarsen_flag_set(), ExcInternalError());
16254 for (const unsigned int vertex :
16256 vertex_level[cell->vertex_index(vertex)] =
16257 std::max(vertex_level[cell->vertex_index(vertex)],
16258 cell->level() - 1);
16259 }
16260 }
16261
16262
16263 // loop over all cells in reverse order. do so because we
16264 // can then update the vertex levels on the adjacent
16265 // vertices and maybe already flag additional cells in this
16266 // loop
16267 //
16268 // note that not only may we have to add additional
16269 // refinement flags, but we will also have to remove
16270 // coarsening flags on cells adjacent to vertices that will
16271 // see refinement
16272 active_cell_iterator endc = end();
16273 for (active_cell_iterator cell = last_active(); cell != endc; --cell)
16274 if (cell->refine_flag_set() == false)
16275 {
16276 for (const unsigned int vertex :
16278 if (vertex_level[cell->vertex_index(vertex)] >=
16279 cell->level() + 1)
16280 {
16281 // remove coarsen flag...
16282 cell->clear_coarsen_flag();
16283
16284 // ...and if necessary also refine the current
16285 // cell, at the same time updating the level
16286 // information about vertices
16287 if (vertex_level[cell->vertex_index(vertex)] >
16288 cell->level() + 1)
16289 {
16290 cell->set_refine_flag();
16291
16292 for (const unsigned int v :
16294 vertex_level[cell->vertex_index(v)] =
16295 std::max(vertex_level[cell->vertex_index(v)],
16296 cell->level() + 1);
16297 }
16298
16299 // continue and see whether we may, for example,
16300 // go into the inner 'if' above based on a
16301 // different vertex
16302 }
16303 }
16304 }
16305
16306 // loop over all cells and remove the coarsen flags for those cells that
16307 // have sister cells not marked for coarsening, or where some neighbors
16308 // are more refined.
16309
16310 // Coarsen flags of cells with no mother cell, i.e. on the
16311 // coarsest level, are deleted explicitly.
16312 for (const auto &acell : this->active_cell_iterators_on_level(0))
16313 acell->clear_coarsen_flag();
16314
16315 const cell_iterator endc = end();
16316 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
16317 {
16318 // nothing to do if we are already on the finest level
16319 if (cell->is_active())
16320 continue;
16321
16322 const unsigned int n_children = cell->n_children();
16323 unsigned int flagged_children = 0;
16324 for (unsigned int child = 0; child < n_children; ++child)
16325 {
16326 const auto child_cell = cell->child(child);
16327 if (child_cell->is_active() && child_cell->coarsen_flag_set())
16328 {
16329 ++flagged_children;
16330 // clear flag since we don't need it anymore
16331 child_cell->clear_coarsen_flag();
16332 }
16333 }
16334
16335 // flag the children for coarsening again if all children were
16336 // flagged and if the policy allows it
16337 if (flagged_children == n_children &&
16338 this->policy->coarsening_allowed(cell))
16339 for (unsigned int c = 0; c < n_children; ++c)
16340 {
16341 Assert(cell->child(c)->refine_flag_set() == false,
16343
16344 cell->child(c)->set_coarsen_flag();
16345 }
16346 }
16347
16348 // now see if anything has changed in the last iteration of this
16349 // function
16350 auto current_coarsen_flags = internal::extract_raw_coarsen_flags(levels);
16351
16352 continue_iterating = (current_coarsen_flags != previous_coarsen_flags);
16353 previous_coarsen_flags.swap(current_coarsen_flags);
16354 }
16355 while (continue_iterating == true);
16356}
16357
16358#endif
16359
16360// TODO: merge the following 3 functions since they are the same
16361template <>
16362bool
16364{
16365 // save the flags to determine whether something was changed in the
16366 // course of this function
16367 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
16368
16369 // do nothing in 1d, except setting the coarsening flags correctly
16370 fix_coarsen_flags();
16371
16372 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
16373
16374 return (flags_before != flags_after);
16375}
16376
16377
16378
16379template <>
16380bool
16382{
16383 // save the flags to determine whether something was changed in the
16384 // course of this function
16385 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
16386
16387 // do nothing in 1d, except setting the coarsening flags correctly
16388 fix_coarsen_flags();
16389
16390 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
16391
16392 return (flags_before != flags_after);
16393}
16394
16395
16396
16397template <>
16398bool
16400{
16401 // save the flags to determine whether something was changed in the
16402 // course of this function
16403 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
16404
16405 // do nothing in 1d, except setting the coarsening flags correctly
16406 fix_coarsen_flags();
16407
16408 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
16409
16410 return (flags_before != flags_after);
16411}
16412
16413
16414
16415namespace
16416{
16417 // check if the given @param cell marked for coarsening would
16418 // produce an unrefined island. To break up long chains of these
16419 // cells we recursively check our neighbors in case we change this
16420 // cell. This reduces the number of outer iterations dramatically.
16421 template <int dim, int spacedim>
16422 void
16423 possibly_do_not_produce_unrefined_islands(
16425 {
16426 Assert(cell->has_children(), ExcInternalError());
16427
16428 unsigned int n_neighbors = 0;
16429 // count all neighbors that will be refined along the face of our
16430 // cell after the next step
16431 unsigned int count = 0;
16432 for (const unsigned int n : GeometryInfo<dim>::face_indices())
16433 {
16434 const typename Triangulation<dim, spacedim>::cell_iterator neighbor =
16435 cell->neighbor(n);
16436 if (neighbor.state() == IteratorState::valid)
16437 {
16438 ++n_neighbors;
16439 if (face_will_be_refined_by_neighbor(cell, n))
16440 ++count;
16441 }
16442 }
16443 // clear coarsen flags if either all existing neighbors will be
16444 // refined or all but one will be and the cell is in the interior
16445 // of the domain
16446 if (count == n_neighbors ||
16447 (count >= n_neighbors - 1 &&
16448 n_neighbors == GeometryInfo<dim>::faces_per_cell))
16449 {
16450 for (unsigned int c = 0; c < cell->n_children(); ++c)
16451 cell->child(c)->clear_coarsen_flag();
16452
16453 for (const unsigned int face : GeometryInfo<dim>::face_indices())
16454 if (!cell->at_boundary(face) &&
16455 (!cell->neighbor(face)->is_active()) &&
16456 (cell_will_be_coarsened(cell->neighbor(face))))
16457 possibly_do_not_produce_unrefined_islands<dim, spacedim>(
16458 cell->neighbor(face));
16459 }
16460 }
16461
16462
16463 // see if the current cell needs to be refined to avoid unrefined
16464 // islands.
16465 //
16466 // there are sometimes chains of cells that induce refinement of
16467 // each other. to avoid running the loop in
16468 // prepare_coarsening_and_refinement over and over again for each
16469 // one of them, at least for the isotropic refinement case we seek
16470 // to flag neighboring elements as well as necessary. this takes
16471 // care of (slightly pathological) cases like
16472 // deal.II/mesh_smoothing_03
16473 template <int dim, int spacedim>
16474 void
16475 possibly_refine_unrefined_island(
16477 const bool allow_anisotropic_smoothing)
16478 {
16479 Assert(cell->is_active(), ExcInternalError());
16480
16481#ifdef DEBUG
16482 // If this is not a parallel::distributed::Triangulation, then we really
16483 // should only get here if the cell is marked for refinement:
16485 *>(&cell->get_triangulation()) == nullptr)
16486 Assert(cell->refine_flag_set() == false, ExcInternalError());
16487 else
16488 // But if this is a p::d::Triangulation, then we don't have that
16489 // much control and we can get here because mesh smoothing is
16490 // requested but can not be honored because p4est controls
16491 // what gets refined. In that case, we can at least provide
16492 // a better error message.
16493 Assert(cell->refine_flag_set() == false,
16494 ExcMessage(
16495 "The triangulation is trying to avoid unrefined islands "
16496 "during mesh refinement/coarsening, as you had requested "
16497 " by passing the appropriate 'smoothing flags' to the "
16498 "constructor of the triangulation. However, for objects "
16499 "of type parallel::distributed::Triangulation, control "
16500 "over which cells get refined rests with p4est, not the "
16501 "deal.II triangulation, and consequently it is not "
16502 "always possible to avoid unrefined islands in the mesh. "
16503 "Please remove the constructor argument to the triangulation "
16504 "object that requests mesh smoothing."));
16505#endif
16506
16507 // now we provide two algorithms. the first one is the standard
16508 // one, coming from the time, where only isotropic refinement was
16509 // possible. it simply counts the neighbors that are or will be
16510 // refined and compares to the number of other ones. the second
16511 // one does this check independently for each direction: if all
16512 // neighbors in one direction (normally two, at the boundary only
16513 // one) are refined, the current cell is flagged to be refined in
16514 // an according direction.
16515
16516 if (allow_anisotropic_smoothing == false)
16517 {
16518 // use first algorithm
16519 unsigned int refined_neighbors = 0, unrefined_neighbors = 0;
16520 for (const unsigned int face : GeometryInfo<dim>::face_indices())
16521 if (!cell->at_boundary(face))
16522 {
16523 if (face_will_be_refined_by_neighbor(cell, face))
16524 ++refined_neighbors;
16525 else
16526 ++unrefined_neighbors;
16527 }
16528
16529 if (unrefined_neighbors < refined_neighbors)
16530 {
16531 cell->clear_coarsen_flag();
16532 cell->set_refine_flag();
16533
16534 // ok, so now we have flagged this cell. if we know that
16535 // there were any unrefined neighbors at all, see if any
16536 // of those will have to be refined as well
16537 if (unrefined_neighbors > 0)
16538 for (const unsigned int face : GeometryInfo<dim>::face_indices())
16539 if (!cell->at_boundary(face) &&
16540 (face_will_be_refined_by_neighbor(cell, face) == false) &&
16541 (cell->neighbor(face)->has_children() == false) &&
16542 (cell->neighbor(face)->refine_flag_set() == false))
16543 possibly_refine_unrefined_island<dim, spacedim>(
16544 cell->neighbor(face), allow_anisotropic_smoothing);
16545 }
16546 }
16547 else
16548 {
16549 // variable to store the cell refine case needed to fulfill
16550 // all smoothing requirements
16551 RefinementCase<dim> smoothing_cell_refinement_case =
16553
16554 // use second algorithm, do the check individually for each
16555 // direction
16556 for (unsigned int face_pair = 0;
16557 face_pair < GeometryInfo<dim>::faces_per_cell / 2;
16558 ++face_pair)
16559 {
16560 // variable to store the cell refine case needed to refine
16561 // at the current face pair in the same way as the
16562 // neighbors do...
16563 RefinementCase<dim> directional_cell_refinement_case =
16565
16566 for (unsigned int face_index = 0; face_index < 2; ++face_index)
16567 {
16568 unsigned int face = 2 * face_pair + face_index;
16569 // variable to store the refine case (to come) of the
16570 // face under consideration
16571 RefinementCase<dim - 1> expected_face_ref_case =
16572 RefinementCase<dim - 1>::no_refinement;
16573
16574 if (cell->neighbor(face).state() == IteratorState::valid)
16575 face_will_be_refined_by_neighbor<dim, spacedim>(
16576 cell, face, expected_face_ref_case);
16577 // now extract which refine case would be necessary to
16578 // achieve the same face refinement. set the
16579 // intersection with other requirements for the same
16580 // direction.
16581
16582 // note: using the intersection is not an obvious
16583 // decision, we could also argue that it is more
16584 // natural to use the union. however, intersection is
16585 // the less aggressive tactic and favours a smaller
16586 // number of refined cells over an intensive
16587 // smoothing. this way we try not to lose too much of
16588 // the effort we put in anisotropic refinement
16589 // indicators due to overly aggressive smoothing...
16590 directional_cell_refinement_case =
16591 (directional_cell_refinement_case &
16594 expected_face_ref_case,
16595 face,
16596 cell->face_orientation(face),
16597 cell->face_flip(face),
16598 cell->face_rotation(face)));
16599 } // for both face indices
16600 // if both requirements sum up to something useful, add
16601 // this to the refine case for smoothing. note: if
16602 // directional_cell_refinement_case is isotropic still,
16603 // then something went wrong...
16604 Assert(directional_cell_refinement_case <
16607 smoothing_cell_refinement_case =
16608 smoothing_cell_refinement_case | directional_cell_refinement_case;
16609 } // for all face_pairs
16610 // no we collected contributions from all directions. combine
16611 // the new flags with the existing refine case, but only if
16612 // smoothing is required
16613 if (smoothing_cell_refinement_case)
16614 {
16615 cell->clear_coarsen_flag();
16616 cell->set_refine_flag(cell->refine_flag_set() |
16617 smoothing_cell_refinement_case);
16618 }
16619 }
16620 }
16621} // namespace
16622
16623#ifndef DOXYGEN
16624template <int dim, int spacedim>
16627{
16628 // save the flags to determine whether something was changed in the
16629 // course of this function
16630 const auto coarsen_flags_before = internal::extract_raw_coarsen_flags(levels);
16631 const auto refine_flags_before = internal::extract_raw_refine_flags(levels);
16632
16633 // save the flags at the outset of each loop. we do so in order to
16634 // find out whether something was changed in the present loop, in
16635 // which case we would have to re-run the loop. the other
16636 // possibility to find this out would be to set a flag
16637 // @p{something_changed} to true each time we change something.
16638 // however, sometimes one change in one of the parts of the loop is
16639 // undone by another one, so we might end up in an endless loop. we
16640 // could be tempted to break this loop at an arbitrary number of
16641 // runs, but that would not be a clean solution, since we would
16642 // either have to 1/ break the loop too early, in which case the
16643 // promise that a second call to this function immediately after the
16644 // first one does not change anything, would be broken, or 2/ we do
16645 // as many loops as there are levels. we know that information is
16646 // transported over one level in each run of the loop, so this is
16647 // enough. Unfortunately, each loop is rather expensive, so we chose
16648 // the way presented here
16649 auto coarsen_flags_before_loop = coarsen_flags_before;
16650 auto refine_flags_before_loop = refine_flags_before;
16651
16652 // now for what is done in each loop: we have to fulfill several
16653 // tasks at the same time, namely several mesh smoothing algorithms
16654 // and mesh regularization, by which we mean that the next mesh
16655 // fulfills several requirements such as no double refinement at
16656 // each face or line, etc.
16657 //
16658 // since doing these things at once seems almost impossible (in the
16659 // first year of this library, they were done in two functions, one
16660 // for refinement and one for coarsening, and most things within
16661 // these were done at once, so the code was rather impossible to
16662 // join into this, only, function), we do them one after each
16663 // other. the order in which we do them is such that the important
16664 // tasks, namely regularization, are done last and the least
16665 // important things are done the first. the following order is
16666 // chosen:
16667 //
16668 // 0/ Only if coarsest_level_1 or patch_level_1 is set: clear all
16669 // coarsen flags on level 1 to avoid level 0 cells being created
16670 // by coarsening. As coarsen flags will never be added, this can
16671 // be done once and for all before the actual loop starts.
16672 //
16673 // 1/ do not coarsen a cell if 'most of the neighbors' will be
16674 // refined after the step. This is to prevent occurrence of
16675 // unrefined islands.
16676 //
16677 // 2/ eliminate refined islands in the interior and at the
16678 // boundary. since they don't do much harm besides increasing the
16679 // number of degrees of freedom, doing this has a rather low
16680 // priority.
16681 //
16682 // 3/ limit the level difference of neighboring cells at each
16683 // vertex.
16684 //
16685 // 4/ eliminate unrefined islands. this has higher priority since
16686 // this diminishes the approximation properties not only of the
16687 // unrefined island, but also of the surrounding patch.
16688 //
16689 // 5/ ensure patch level 1. Then the triangulation consists of
16690 // patches, i.e. of cells that are refined once. It follows that
16691 // if at least one of the children of a cell is or will be
16692 // refined than all children need to be refined. This step only
16693 // sets refinement flags and does not set coarsening flags. If
16694 // the patch_level_1 flag is set, then
16695 // eliminate_unrefined_islands, eliminate_refined_inner_islands
16696 // and eliminate_refined_boundary_islands will be fulfilled
16697 // automatically and do not need to be enforced separately.
16698 //
16699 // 6/ take care of the requirement that no double refinement is done
16700 // at each face
16701 //
16702 // 7/ take care that no double refinement is done at each line in 3d
16703 // or higher dimensions.
16704 //
16705 // 8/ make sure that all children of each cell are either flagged
16706 // for coarsening or none of the children is
16707 //
16708 // For some of these steps, it is known that they interact. Namely,
16709 // it is not possible to guarantee that after step 6 another step 5
16710 // would have no effect; the same holds for the opposite order and
16711 // also when taking into account step 7. however, it is important to
16712 // guarantee that step five or six do not undo something that step 5
16713 // did, and step 7 not something of step 6, otherwise the
16714 // requirements will not be satisfied even if the loop
16715 // terminates. this is accomplished by the fact that steps 5 and 6
16716 // only *add* refinement flags and delete coarsening flags
16717 // (therefore, step 6 can't undo something that step 4 already did),
16718 // and step 7 only deletes coarsening flags, never adds some. step 7
16719 // needs also take care that it won't tag cells for refinement for
16720 // which some neighbors are more refined or will be refined.
16721
16722 //------------------------------------
16723 // STEP 0:
16724 // Only if coarsest_level_1 or patch_level_1 is set: clear all
16725 // coarsen flags on level 1 to avoid level 0 cells being created
16726 // by coarsening.
16727 if (((smooth_grid & coarsest_level_1) || (smooth_grid & patch_level_1)) &&
16728 n_levels() >= 2)
16729 {
16730 for (const auto &cell : active_cell_iterators_on_level(1))
16731 cell->clear_coarsen_flag();
16732 }
16733
16734 bool mesh_changed_in_this_loop = false;
16735 do
16736 {
16737 //------------------------------------
16738 // STEP 1:
16739 // do not coarsen a cell if 'most of the neighbors' will be
16740 // refined after the step. This is to prevent the occurrence
16741 // of unrefined islands. If patch_level_1 is set, this will
16742 // be automatically fulfilled.
16743 if (smooth_grid & do_not_produce_unrefined_islands &&
16744 !(smooth_grid & patch_level_1))
16745 {
16746 for (const auto &cell : cell_iterators())
16747 {
16748 // only do something if this
16749 // cell will be coarsened
16750 if (!cell->is_active() && cell_will_be_coarsened(cell))
16751 possibly_do_not_produce_unrefined_islands<dim, spacedim>(cell);
16752 }
16753 }
16754
16755
16756 //------------------------------------
16757 // STEP 2:
16758 // eliminate refined islands in the interior and at the
16759 // boundary. since they don't do much harm besides increasing
16760 // the number of degrees of freedom, doing this has a rather
16761 // low priority. If patch_level_1 is set, this will be
16762 // automatically fulfilled.
16763 //
16764 // there is one corner case to consider: if this is a
16765 // distributed triangulation, there may be refined islands on
16766 // the boundary of which we own only part (e.g. a single cell
16767 // in the corner of a domain). the rest of the island is
16768 // ghost cells and it *looks* like the area around it
16769 // (artificial cells) are coarser but this is only because
16770 // they may actually be equally fine on other
16771 // processors. it's hard to detect this case but we can do
16772 // the following: only set coarsen flags to remove this
16773 // refined island if all cells we want to set flags on are
16774 // locally owned
16775 if (smooth_grid & (eliminate_refined_inner_islands |
16776 eliminate_refined_boundary_islands) &&
16777 !(smooth_grid & patch_level_1))
16778 {
16779 for (const auto &cell : cell_iterators())
16780 if (!cell->is_active() ||
16781 (cell->is_active() && cell->refine_flag_set() &&
16782 cell->is_locally_owned()))
16783 {
16784 // check whether all children are active, i.e. not
16785 // refined themselves. This is a precondition that the
16786 // children may be coarsened away. If the cell is only
16787 // flagged for refinement, then all future children
16788 // will be active
16789 bool all_children_active = true;
16790 if (!cell->is_active())
16791 for (unsigned int c = 0; c < cell->n_children(); ++c)
16792 if (!cell->child(c)->is_active() ||
16793 cell->child(c)->is_ghost() ||
16794 cell->child(c)->is_artificial())
16795 {
16796 all_children_active = false;
16797 break;
16798 }
16799
16800 if (all_children_active)
16801 {
16802 // count number of refined and unrefined neighbors
16803 // of cell. neighbors on lower levels are counted
16804 // as unrefined since they can only get to the
16805 // same level as this cell by the next refinement
16806 // cycle
16807 unsigned int unrefined_neighbors = 0, total_neighbors = 0;
16808
16809 // Keep track if this cell is at a periodic
16810 // boundary or not. TODO: We do not currently run
16811 // the algorithm for inner islands at a periodic
16812 // boundary (remains to be implemented), but we
16813 // also don't want to consider them
16814 // boundary_island cells as this can interfere
16815 // with 2:1 refinement across periodic faces.
16816 // Instead: just ignore those cells for this
16817 // smoothing operation below.
16818 bool at_periodic_boundary = false;
16819
16820 for (const unsigned int n :
16821 GeometryInfo<dim>::face_indices())
16822 {
16823 const cell_iterator neighbor = cell->neighbor(n);
16824 if (neighbor.state() == IteratorState::valid)
16825 {
16826 ++total_neighbors;
16827
16828 if (!face_will_be_refined_by_neighbor(cell, n))
16829 ++unrefined_neighbors;
16830 }
16831 else if (cell->has_periodic_neighbor(n))
16832 {
16833 ++total_neighbors;
16834 at_periodic_boundary = true;
16835 }
16836 }
16837
16838 // if all neighbors unrefined: mark this cell for
16839 // coarsening or don't refine if marked for that
16840 //
16841 // also do the distinction between the two
16842 // versions of the eliminate_refined_*_islands
16843 // flag
16844 //
16845 // the last check is whether there are any
16846 // neighbors at all. if not so, then we are (e.g.)
16847 // on the coarsest grid with one cell, for which,
16848 // of course, we do not remove the refine flag.
16849 if ((unrefined_neighbors == total_neighbors) &&
16850 ((!cell->at_boundary() &&
16851 (smooth_grid & eliminate_refined_inner_islands)) ||
16852 (cell->at_boundary() && !at_periodic_boundary &&
16853 (smooth_grid &
16854 eliminate_refined_boundary_islands))) &&
16855 (total_neighbors != 0))
16856 {
16857 if (!cell->is_active())
16858 for (unsigned int c = 0; c < cell->n_children(); ++c)
16859 {
16860 cell->child(c)->clear_refine_flag();
16861 cell->child(c)->set_coarsen_flag();
16862 }
16863 else
16864 cell->clear_refine_flag();
16865 }
16866 }
16867 }
16868 }
16869
16870 //------------------------------------
16871 // STEP 3:
16872 // limit the level difference of neighboring cells at each
16873 // vertex.
16874 //
16875 // in case of anisotropic refinement this does not make
16876 // sense. as soon as one cell is anisotropically refined, an
16877 // Assertion is thrown. therefore we can ignore this problem
16878 // later on
16879 if (smooth_grid & limit_level_difference_at_vertices)
16880 {
16881 Assert(!anisotropic_refinement,
16882 ExcMessage("In case of anisotropic refinement the "
16883 "limit_level_difference_at_vertices flag for "
16884 "mesh smoothing must not be set!"));
16885
16886 // store highest level one of the cells adjacent to a vertex
16887 // belongs to
16888 std::vector<int> vertex_level(vertices.size(), 0);
16889 for (const auto &cell : active_cell_iterators())
16890 {
16891 if (cell->refine_flag_set())
16892 for (const unsigned int vertex :
16894 vertex_level[cell->vertex_index(vertex)] =
16895 std::max(vertex_level[cell->vertex_index(vertex)],
16896 cell->level() + 1);
16897 else if (!cell->coarsen_flag_set())
16898 for (const unsigned int vertex :
16900 vertex_level[cell->vertex_index(vertex)] =
16901 std::max(vertex_level[cell->vertex_index(vertex)],
16902 cell->level());
16903 else
16904 {
16905 // if coarsen flag is set then tentatively assume
16906 // that the cell will be coarsened. this isn't
16907 // always true (the coarsen flag could be removed
16908 // again) and so we may make an error here
16909 Assert(cell->coarsen_flag_set(), ExcInternalError());
16910 for (const unsigned int vertex :
16912 vertex_level[cell->vertex_index(vertex)] =
16913 std::max(vertex_level[cell->vertex_index(vertex)],
16914 cell->level() - 1);
16915 }
16916 }
16917
16918
16919 // loop over all cells in reverse order. do so because we
16920 // can then update the vertex levels on the adjacent
16921 // vertices and maybe already flag additional cells in this
16922 // loop
16923 //
16924 // note that not only may we have to add additional
16925 // refinement flags, but we will also have to remove
16926 // coarsening flags on cells adjacent to vertices that will
16927 // see refinement
16928 for (active_cell_iterator cell = last_active(); cell != end(); --cell)
16929 if (cell->refine_flag_set() == false)
16930 {
16931 for (const unsigned int vertex :
16933 if (vertex_level[cell->vertex_index(vertex)] >=
16934 cell->level() + 1)
16935 {
16936 // remove coarsen flag...
16937 cell->clear_coarsen_flag();
16938
16939 // ...and if necessary also refine the current
16940 // cell, at the same time updating the level
16941 // information about vertices
16942 if (vertex_level[cell->vertex_index(vertex)] >
16943 cell->level() + 1)
16944 {
16945 cell->set_refine_flag();
16946
16947 for (const unsigned int v :
16949 vertex_level[cell->vertex_index(v)] =
16950 std::max(vertex_level[cell->vertex_index(v)],
16951 cell->level() + 1);
16952 }
16953
16954 // continue and see whether we may, for example,
16955 // go into the inner'if'
16956 // above based on a
16957 // different vertex
16958 }
16959 }
16960 }
16961
16962 //-----------------------------------
16963 // STEP 4:
16964 // eliminate unrefined islands. this has higher priority
16965 // since this diminishes the approximation properties not
16966 // only of the unrefined island, but also of the surrounding
16967 // patch.
16968 //
16969 // do the loop from finest to coarsest cells since we may
16970 // trigger a cascade by marking cells for refinement which
16971 // may trigger more cells further down below
16972 if (smooth_grid & eliminate_unrefined_islands)
16973 {
16974 for (active_cell_iterator cell = last_active(); cell != end(); --cell)
16975 // only do something if cell is not already flagged for
16976 // (isotropic) refinement
16977 if (cell->refine_flag_set() !=
16979 possibly_refine_unrefined_island<dim, spacedim>(
16980 cell, (smooth_grid & allow_anisotropic_smoothing) != 0);
16981 }
16982
16983 //-------------------------------
16984 // STEP 5:
16985 // ensure patch level 1.
16986 //
16987 // Introduce some terminology:
16988 // - a cell that is refined
16989 // once is a patch of
16990 // level 1 simply called patch.
16991 // - a cell that is globally
16992 // refined twice is called
16993 // a patch of level 2.
16994 // - patch level n says that
16995 // the triangulation consists
16996 // of patches of level n.
16997 // This makes sense only
16998 // if the grid is already at
16999 // least n times globally
17000 // refined.
17001 //
17002 // E.g. from patch level 1 follows: if at least one of the
17003 // children of a cell is or will be refined than enforce all
17004 // children to be refined.
17005
17006 // This step 4 only sets refinement flags and does not set
17007 // coarsening flags.
17008 if (smooth_grid & patch_level_1)
17009 {
17010 // An important assumption (A) is that before calling this
17011 // function the grid was already of patch level 1.
17012
17013 // loop over all cells whose children are all active. (By
17014 // assumption (A) either all or none of the children are
17015 // active). If the refine flag of at least one of the
17016 // children is set then set_refine_flag and
17017 // clear_coarsen_flag of all children.
17018 for (const auto &cell : cell_iterators())
17019 if (!cell->is_active())
17020 {
17021 // ensure the invariant. we can then check whether all
17022 // of its children are further refined or not by
17023 // simply looking at the first child
17024 Assert(cell_is_patch_level_1(cell), ExcInternalError());
17025 if (cell->child(0)->has_children() == true)
17026 continue;
17027
17028 // cell is found to be a patch. combine the refine
17029 // cases of all children
17030 RefinementCase<dim> combined_ref_case =
17032 for (unsigned int i = 0; i < cell->n_children(); ++i)
17033 combined_ref_case =
17034 combined_ref_case | cell->child(i)->refine_flag_set();
17035 if (combined_ref_case != RefinementCase<dim>::no_refinement)
17036 for (unsigned int i = 0; i < cell->n_children(); ++i)
17037 {
17038 cell_iterator child = cell->child(i);
17039
17040 child->clear_coarsen_flag();
17041 child->set_refine_flag(combined_ref_case);
17042 }
17043 }
17044
17045 // The code above dealt with the case where we may get a
17046 // non-patch_level_1 mesh from refinement. Now also deal
17047 // with the case where we could get such a mesh by
17048 // coarsening. Coarsen the children (and remove the
17049 // grandchildren) only if all cell->grandchild(i)
17050 // ->coarsen_flag_set() are set.
17051 //
17052 // for a case where this is a bit tricky, take a look at the
17053 // mesh_smoothing_0[12] testcases
17054 for (const auto &cell : cell_iterators())
17055 {
17056 // check if this cell has active grandchildren. note
17057 // that we know that it is patch_level_1, i.e. if one of
17058 // its children is active then so are all, and it isn't
17059 // going to have any grandchildren at all:
17060 if (cell->is_active() || cell->child(0)->is_active())
17061 continue;
17062
17063 // cell is not active, and so are none of its
17064 // children. check the grandchildren. note that the
17065 // children are also patch_level_1, and so we only ever
17066 // need to check their first child
17067 const unsigned int n_children = cell->n_children();
17068 bool has_active_grandchildren = false;
17069
17070 for (unsigned int i = 0; i < n_children; ++i)
17071 if (cell->child(i)->child(0)->is_active())
17072 {
17073 has_active_grandchildren = true;
17074 break;
17075 }
17076
17077 if (has_active_grandchildren == false)
17078 continue;
17079
17080
17081 // ok, there are active grandchildren. see if either all
17082 // or none of them are flagged for coarsening
17083 unsigned int n_grandchildren = 0;
17084
17085 // count all coarsen flags of the grandchildren.
17086 unsigned int n_coarsen_flags = 0;
17087
17088 // cell is not a patch (of level 1) as it has a
17089 // grandchild. Is cell a patch of level 2?? Therefore:
17090 // find out whether all cell->child(i) are patches
17091 for (unsigned int c = 0; c < n_children; ++c)
17092 {
17093 // get at the child. by assumption (A), and the
17094 // check by which we got here, the child is not
17095 // active
17096 cell_iterator child = cell->child(c);
17097
17098 const unsigned int nn_children = child->n_children();
17099 n_grandchildren += nn_children;
17100
17101 // if child is found to be a patch of active cells
17102 // itself, then add up how many of its children are
17103 // supposed to be coarsened
17104 if (child->child(0)->is_active())
17105 for (unsigned int cc = 0; cc < nn_children; ++cc)
17106 if (child->child(cc)->coarsen_flag_set())
17107 ++n_coarsen_flags;
17108 }
17109
17110 // if not all grandchildren are supposed to be coarsened
17111 // (e.g. because some simply don't have the flag set, or
17112 // because they are not active and therefore cannot
17113 // carry the flag), then remove the coarsen flag from
17114 // all of the active grandchildren. note that there may
17115 // be coarsen flags on the grandgrandchildren -- we
17116 // don't clear them here, but we'll get to them in later
17117 // iterations if necessary
17118 //
17119 // there is nothing we have to do if no coarsen flags
17120 // have been set at all
17121 if ((n_coarsen_flags != n_grandchildren) && (n_coarsen_flags > 0))
17122 for (unsigned int c = 0; c < n_children; ++c)
17123 {
17124 const cell_iterator child = cell->child(c);
17125 if (child->child(0)->is_active())
17126 for (unsigned int cc = 0; cc < child->n_children(); ++cc)
17127 child->child(cc)->clear_coarsen_flag();
17128 }
17129 }
17130 }
17131
17132 //--------------------------------
17133 //
17134 // at the boundary we could end up with cells with negative
17135 // volume or at least with a part, that is negative, if the
17136 // cell is refined anisotropically. we have to check, whether
17137 // that can happen
17138 this->policy->prevent_distorted_boundary_cells(*this);
17139
17140 //-------------------------------
17141 // STEP 6:
17142 // take care of the requirement that no
17143 // double refinement is done at each face
17144 //
17145 // in case of anisotropic refinement it is only likely, but
17146 // not sure, that the cells, which are more refined along a
17147 // certain face common to two cells are on a higher
17148 // level. therefore we cannot be sure, that the requirement
17149 // of no double refinement is fulfilled after a single pass
17150 // of the following actions. We could just wait for the next
17151 // global loop. when this function terminates, the
17152 // requirement will be fulfilled. However, it might be faster
17153 // to insert an inner loop here.
17154 bool changed = true;
17155 while (changed)
17156 {
17157 changed = false;
17158 active_cell_iterator cell = last_active(), endc = end();
17159
17160 for (; cell != endc; --cell)
17161 if (cell->refine_flag_set())
17162 {
17163 // loop over neighbors of cell
17164 for (const auto i : cell->face_indices())
17165 {
17166 // only do something if the face is not at the
17167 // boundary and if the face will be refined with
17168 // the RefineCase currently flagged for
17169 const bool has_periodic_neighbor =
17170 cell->has_periodic_neighbor(i);
17171 const bool has_neighbor_or_periodic_neighbor =
17172 !cell->at_boundary(i) || has_periodic_neighbor;
17173 if (has_neighbor_or_periodic_neighbor &&
17175 cell->refine_flag_set(), i) !=
17177 {
17178 // 1) if the neighbor has children: nothing to
17179 // worry about. 2) if the neighbor is active
17180 // and a coarser one, ensure, that its
17181 // refine_flag is set 3) if the neighbor is
17182 // active and as refined along the face as our
17183 // current cell, make sure, that no
17184 // coarsen_flag is set. if we remove the
17185 // coarsen flag of our neighbor,
17186 // fix_coarsen_flags() makes sure, that the
17187 // mother cell will not be coarsened
17188 if (cell->neighbor_or_periodic_neighbor(i)->is_active())
17189 {
17190 if ((!has_periodic_neighbor &&
17191 cell->neighbor_is_coarser(i)) ||
17192 (has_periodic_neighbor &&
17193 cell->periodic_neighbor_is_coarser(i)))
17194 {
17195 if (cell->neighbor_or_periodic_neighbor(i)
17196 ->coarsen_flag_set())
17197 cell->neighbor_or_periodic_neighbor(i)
17198 ->clear_coarsen_flag();
17199 // we'll set the refine flag for this
17200 // neighbor below. we note, that we
17201 // have changed something by setting
17202 // the changed flag to true. We do not
17203 // need to do so, if we just removed
17204 // the coarsen flag, as the changed
17205 // flag only indicates the need to
17206 // re-run the inner loop. however, we
17207 // only loop over cells flagged for
17208 // refinement here, so nothing to
17209 // worry about if we remove coarsen
17210 // flags
17211
17212 if (dim == 2)
17213 {
17214 if (smooth_grid &
17215 allow_anisotropic_smoothing)
17216 changed =
17217 has_periodic_neighbor ?
17218 cell->periodic_neighbor(i)
17219 ->flag_for_face_refinement(
17220 cell
17221 ->periodic_neighbor_of_coarser_periodic_neighbor(
17222 i)
17223 .first,
17225 cell->neighbor(i)
17226 ->flag_for_face_refinement(
17227 cell
17228 ->neighbor_of_coarser_neighbor(
17229 i)
17230 .first,
17232 else
17233 {
17234 if (!cell
17235 ->neighbor_or_periodic_neighbor(
17236 i)
17237 ->refine_flag_set())
17238 changed = true;
17239 cell->neighbor_or_periodic_neighbor(i)
17240 ->set_refine_flag();
17241 }
17242 }
17243 else // i.e. if (dim==3)
17244 {
17245 // ugly situations might arise here,
17246 // consider the following situation, which
17247 // shows neighboring cells at the common
17248 // face, where the upper right element is
17249 // coarser at the given face. Now the upper
17250 // child element of the lower left wants to
17251 // refine according to cut_z, such that
17252 // there is a 'horizontal' refinement of the
17253 // face marked with #####
17254 //
17255 // / /
17256 // / /
17257 // *---------------*
17258 // | |
17259 // | |
17260 // | |
17261 // | |
17262 // | |
17263 // | | /
17264 // | |/
17265 // *---------------*
17266 //
17267 //
17268 // *---------------*
17269 // /| /|
17270 // / | ##### / |
17271 // | |
17272 // *---------------*
17273 // /| /|
17274 // / | / |
17275 // | |
17276 // *---------------*
17277 // / /
17278 // / /
17279 //
17280 // this introduces too many hanging nodes
17281 // and the neighboring (coarser) cell (upper
17282 // right) has to be refined. If it is only
17283 // refined according to cut_z, then
17284 // everything is ok:
17285 //
17286 // / /
17287 // / /
17288 // *---------------*
17289 // | |
17290 // | | /
17291 // | |/
17292 // *---------------*
17293 // | |
17294 // | | /
17295 // | |/
17296 // *---------------*
17297 //
17298 //
17299 // *---------------*
17300 // /| /|
17301 // / *---------------*
17302 // /| /|
17303 // *---------------*
17304 // /| /|
17305 // / | / |
17306 // | |
17307 // *---------------*
17308 // / /
17309 // / /
17310 //
17311 // if however the cell wants to refine
17312 // itself in an other way, or if we disallow
17313 // anisotropic smoothing, then simply
17314 // refining the neighbor isotropically is
17315 // not going to work, since this introduces
17316 // a refinement of face ##### with both
17317 // cut_x and cut_y, which is not possible:
17318 //
17319 // / / /
17320 // / / /
17321 // *-------*-------*
17322 // | | |
17323 // | | | /
17324 // | | |/
17325 // *-------*-------*
17326 // | | |
17327 // | | | /
17328 // | | |/
17329 // *-------*-------*
17330 //
17331 //
17332 // *---------------*
17333 // /| /|
17334 // / *---------------*
17335 // /| /|
17336 // *---------------*
17337 // /| /|
17338 // / | / |
17339 // | |
17340 // *---------------*
17341 // / /
17342 // / /
17343 //
17344 // thus, in this case we also need to refine
17345 // our current cell in the new direction:
17346 //
17347 // / / /
17348 // / / /
17349 // *-------*-------*
17350 // | | |
17351 // | | | /
17352 // | | |/
17353 // *-------*-------*
17354 // | | |
17355 // | | | /
17356 // | | |/
17357 // *-------*-------*
17358 //
17359 //
17360 // *-------*-------*
17361 // /| /| /|
17362 // / *-------*-------*
17363 // /| /| /|
17364 // *-------*-------*
17365 // /| / /|
17366 // / | / |
17367 // | |
17368 // *---------------*
17369 // / /
17370 // / /
17371
17372 std::pair<unsigned int, unsigned int>
17373 nb_indices =
17374 has_periodic_neighbor ?
17375 cell
17376 ->periodic_neighbor_of_coarser_periodic_neighbor(
17377 i) :
17378 cell->neighbor_of_coarser_neighbor(i);
17379 unsigned int refined_along_x = 0,
17380 refined_along_y = 0,
17381 to_be_refined_along_x = 0,
17382 to_be_refined_along_y = 0;
17383
17384 const int this_face_index =
17385 cell->face_index(i);
17386
17387 // step 1: detect, along which axis the face
17388 // is currently refined
17389
17390 // first, we need an iterator pointing to
17391 // the parent face. This requires a slight
17392 // detour in case the neighbor is behind a
17393 // periodic face.
17394 const auto parent_face = [&]() {
17395 if (has_periodic_neighbor)
17396 {
17397 const auto neighbor =
17398 cell->periodic_neighbor(i);
17399 const auto parent_face_no =
17400 neighbor
17401 ->periodic_neighbor_of_periodic_neighbor(
17402 nb_indices.first);
17403 auto parent =
17404 neighbor->periodic_neighbor(
17405 nb_indices.first);
17406 return parent->face(parent_face_no);
17407 }
17408 else
17409 return cell->neighbor(i)->face(
17410 nb_indices.first);
17411 }();
17412
17413 if ((this_face_index ==
17414 parent_face->child_index(0)) ||
17415 (this_face_index ==
17416 parent_face->child_index(1)))
17417 {
17418 // this might be an
17419 // anisotropic child. get the
17420 // face refine case of the
17421 // neighbors face and count
17422 // refinements in x and y
17423 // direction.
17424 RefinementCase<dim - 1> frc =
17425 parent_face->refinement_case();
17427 ++refined_along_x;
17429 ++refined_along_y;
17430 }
17431 else
17432 // this has to be an isotropic
17433 // child
17434 {
17435 ++refined_along_x;
17436 ++refined_along_y;
17437 }
17438 // step 2: detect, along which axis the face
17439 // has to be refined given the current
17440 // refine flag
17441 RefinementCase<dim - 1> flagged_frc =
17443 cell->refine_flag_set(),
17444 i,
17445 cell->face_orientation(i),
17446 cell->face_flip(i),
17447 cell->face_rotation(i));
17448 if (flagged_frc &
17450 ++to_be_refined_along_x;
17451 if (flagged_frc &
17453 ++to_be_refined_along_y;
17454
17455 // step 3: set the refine flag of the
17456 // (coarser and active) neighbor.
17457 if ((smooth_grid &
17458 allow_anisotropic_smoothing) ||
17459 cell->neighbor_or_periodic_neighbor(i)
17460 ->refine_flag_set())
17461 {
17462 if (refined_along_x +
17463 to_be_refined_along_x >
17464 1)
17465 changed |=
17466 cell
17467 ->neighbor_or_periodic_neighbor(i)
17468 ->flag_for_face_refinement(
17469 nb_indices.first,
17470 RefinementCase<dim -
17471 1>::cut_axis(0));
17472 if (refined_along_y +
17473 to_be_refined_along_y >
17474 1)
17475 changed |=
17476 cell
17477 ->neighbor_or_periodic_neighbor(i)
17478 ->flag_for_face_refinement(
17479 nb_indices.first,
17480 RefinementCase<dim -
17481 1>::cut_axis(1));
17482 }
17483 else
17484 {
17485 if (cell
17486 ->neighbor_or_periodic_neighbor(i)
17487 ->refine_flag_set() !=
17490 changed = true;
17491 cell->neighbor_or_periodic_neighbor(i)
17492 ->set_refine_flag();
17493 }
17494
17495 // step 4: if necessary (see above) add to
17496 // the refine flag of the current cell
17497 cell_iterator nb =
17498 cell->neighbor_or_periodic_neighbor(i);
17499 RefinementCase<dim - 1> nb_frc =
17501 nb->refine_flag_set(),
17502 nb_indices.first,
17503 nb->face_orientation(nb_indices.first),
17504 nb->face_flip(nb_indices.first),
17505 nb->face_rotation(nb_indices.first));
17506 if ((nb_frc & RefinementCase<dim>::cut_x) &&
17507 !((refined_along_x != 0u) ||
17508 (to_be_refined_along_x != 0u)))
17509 changed |= cell->flag_for_face_refinement(
17510 i,
17512 if ((nb_frc & RefinementCase<dim>::cut_y) &&
17513 !((refined_along_y != 0u) ||
17514 (to_be_refined_along_y != 0u)))
17515 changed |= cell->flag_for_face_refinement(
17516 i,
17518 }
17519 } // if neighbor is coarser
17520 else // -> now the neighbor is not coarser
17521 {
17522 cell->neighbor_or_periodic_neighbor(i)
17523 ->clear_coarsen_flag();
17524 const unsigned int nb_nb =
17525 has_periodic_neighbor ?
17526 cell
17527 ->periodic_neighbor_of_periodic_neighbor(
17528 i) :
17529 cell->neighbor_of_neighbor(i);
17530 const cell_iterator neighbor =
17531 cell->neighbor_or_periodic_neighbor(i);
17532 RefinementCase<dim - 1> face_ref_case =
17534 neighbor->refine_flag_set(),
17535 nb_nb,
17536 neighbor->face_orientation(nb_nb),
17537 neighbor->face_flip(nb_nb),
17538 neighbor->face_rotation(nb_nb));
17539 RefinementCase<dim - 1> needed_face_ref_case =
17541 cell->refine_flag_set(),
17542 i,
17543 cell->face_orientation(i),
17544 cell->face_flip(i),
17545 cell->face_rotation(i));
17546 // if the neighbor wants to refine the
17547 // face with cut_x and we want cut_y
17548 // or vice versa, we have to refine
17549 // isotropically at the given face
17550 if ((face_ref_case ==
17552 needed_face_ref_case ==
17554 (face_ref_case ==
17556 needed_face_ref_case ==
17558 {
17559 changed = cell->flag_for_face_refinement(
17560 i, face_ref_case);
17561 neighbor->flag_for_face_refinement(
17562 nb_nb, needed_face_ref_case);
17563 }
17564 }
17565 }
17566 else //-> the neighbor is not active
17567 {
17568 RefinementCase<dim - 1>
17569 face_ref_case = cell->face(i)->refinement_case(),
17570 needed_face_ref_case =
17572 cell->refine_flag_set(),
17573 i,
17574 cell->face_orientation(i),
17575 cell->face_flip(i),
17576 cell->face_rotation(i));
17577 // if the face is refined with cut_x and
17578 // we want cut_y or vice versa, we have to
17579 // refine isotropically at the given face
17580 if ((face_ref_case == RefinementCase<dim>::cut_x &&
17581 needed_face_ref_case ==
17583 (face_ref_case == RefinementCase<dim>::cut_y &&
17584 needed_face_ref_case ==
17586 changed =
17587 cell->flag_for_face_refinement(i,
17588 face_ref_case);
17589 }
17590 }
17591 }
17592 }
17593 }
17594
17595 //------------------------------------
17596 // STEP 7:
17597 // take care that no double refinement is done at each line in 3d or
17598 // higher dimensions.
17599 this->policy->prepare_refinement_dim_dependent(*this);
17600
17601 //------------------------------------
17602 // STEP 8:
17603 // make sure that all children of each cell are either flagged for
17604 // coarsening or none of the children is
17605 fix_coarsen_flags();
17606
17607 // get the refinement and coarsening flags
17608 auto coarsen_flags_after_loop =
17609 internal::extract_raw_coarsen_flags(levels);
17610 auto refine_flags_after_loop = internal::extract_raw_refine_flags(levels);
17611
17612 // find out whether something was changed in this loop
17613 mesh_changed_in_this_loop =
17614 ((coarsen_flags_before_loop != coarsen_flags_after_loop) ||
17615 (refine_flags_before_loop != refine_flags_after_loop));
17616
17617 // set the flags for the next loop already
17618 coarsen_flags_before_loop.swap(coarsen_flags_after_loop);
17619 refine_flags_before_loop.swap(refine_flags_after_loop);
17620 }
17621 while (mesh_changed_in_this_loop);
17622
17623
17624 // find out whether something was really changed in this
17625 // function. Note that @p{..._flags_before_loop} represents the state
17626 // after the last loop, i.e., the present state
17627 return ((coarsen_flags_before != coarsen_flags_before_loop) ||
17628 (refine_flags_before != refine_flags_before_loop));
17629}
17630
17631
17632
17633template <int dim, int spacedim>
17636 const unsigned int magic_number1,
17637 const std::vector<bool> &v,
17638 const unsigned int magic_number2,
17639 std::ostream &out)
17640{
17641 const unsigned int N = v.size();
17642 unsigned char *flags = new unsigned char[N / 8 + 1];
17643 for (unsigned int i = 0; i < N / 8 + 1; ++i)
17644 flags[i] = 0;
17645
17646 for (unsigned int position = 0; position < N; ++position)
17647 flags[position / 8] |= (v[position] ? (1 << (position % 8)) : 0);
17648
17649 AssertThrow(out.fail() == false, ExcIO());
17650
17651 // format:
17652 // 0. magic number
17653 // 1. number of flags
17654 // 2. the flags
17655 // 3. magic number
17656 out << magic_number1 << ' ' << N << std::endl;
17657 for (unsigned int i = 0; i < N / 8 + 1; ++i)
17658 out << static_cast<unsigned int>(flags[i]) << ' ';
17659
17660 out << std::endl << magic_number2 << std::endl;
17661
17662 delete[] flags;
17663
17664 AssertThrow(out.fail() == false, ExcIO());
17665}
17666
17667
17668template <int dim, int spacedim>
17671 const unsigned int magic_number1,
17672 std::vector<bool> &v,
17673 const unsigned int magic_number2,
17674 std::istream &in)
17675{
17676 AssertThrow(in.fail() == false, ExcIO());
17677
17678 unsigned int magic_number;
17679 in >> magic_number;
17680 AssertThrow(magic_number == magic_number1, ExcGridReadError());
17681
17682 unsigned int N;
17683 in >> N;
17684 v.resize(N);
17685
17686 unsigned char *flags = new unsigned char[N / 8 + 1];
17687 unsigned short int tmp;
17688 for (unsigned int i = 0; i < N / 8 + 1; ++i)
17689 {
17690 in >> tmp;
17691 flags[i] = tmp;
17692 }
17693
17694 for (unsigned int position = 0; position != N; ++position)
17695 v[position] = ((flags[position / 8] & (1 << (position % 8))) != 0);
17696
17697 in >> magic_number;
17698 AssertThrow(magic_number == magic_number2, ExcGridReadError());
17699
17700 delete[] flags;
17701
17702 AssertThrow(in.fail() == false, ExcIO());
17703}
17704
17705
17706
17707template <int dim, int spacedim>
17710{
17711 std::size_t mem = 0;
17712 mem += sizeof(MeshSmoothing);
17713 mem += MemoryConsumption::memory_consumption(reference_cells);
17714 mem += MemoryConsumption::memory_consumption(periodic_face_pairs_level_0);
17716 for (const auto &level : levels)
17719 mem += MemoryConsumption::memory_consumption(vertices_used);
17720 mem += sizeof(manifolds);
17721 mem += sizeof(smooth_grid);
17722 mem += MemoryConsumption::memory_consumption(number_cache);
17723 mem += sizeof(faces);
17724 if (faces)
17726
17727 return mem;
17728}
17729
17730
17731
17732template <int dim, int spacedim>
17735 default;
17736
17737#endif
17738
17739// explicit instantiations
17740#include "tria.inst"
17741
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
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
Subscriptor & operator=(const Subscriptor &)
constexpr void clear()
void join() const
IteratorState::IteratorStates state() const
virtual void add_periodicity(const std::vector< GridTools::PeriodicFacePair< cell_iterator > > &)
virtual types::global_cell_index n_global_active_cells() const
quad_iterator begin_quad(const unsigned int level=0) const
typename IteratorSelector::raw_line_iterator raw_line_iterator
Definition tria.h:4086
active_vertex_iterator begin_active_vertex() const
virtual MPI_Comm get_communicator() const
void load_user_indices_quad(const std::vector< unsigned int > &v)
unsigned int n_quads() const
Triangulation & operator=(Triangulation< dim, spacedim > &&tria) noexcept
void load_user_indices(const std::vector< unsigned int > &v)
std::vector< bool > vertices_used
Definition tria.h:4462
virtual void clear()
bool anisotropic_refinement
Definition tria.h:4474
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:4532
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()
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:4457
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:4481
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:4509
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:4002
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:4451
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:4087
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:4492
void save_user_indices_hex(std::vector< unsigned int > &v) const
DistortedCellList execute_refinement()
active_line_iterator begin_active_line(const unsigned int level=0) const
void save_user_indices_quad(std::vector< unsigned int > &v) const
void load_user_pointers_hex(const std::vector< void * > &v)
cell_iterator end() const
virtual bool has_hanging_nodes() const
std::vector< GridTools::PeriodicFacePair< cell_iterator > > periodic_face_pairs_level_0
Definition tria.h:4063
unsigned int n_raw_cells(const unsigned int level) const
bool contains_cell(const CellId &cell_id) const
void load_coarsen_flags(std::istream &out)
quad_iterator end_quad() const
line_iterator begin_line(const unsigned int level=0) const
unsigned int max_adjacent_cells() const
vertex_iterator begin_vertex() const
void save_attached_data(const unsigned int global_first_cell, const unsigned int global_num_cells, const std::string &filename) const
void clear_user_flags()
unsigned int n_hexs() const
vertex_iterator end_vertex() const
void load_user_pointers_line(const std::vector< void * > &v)
hex_iterator end_hex() const
hex_iterator begin_hex(const unsigned int level=0) const
virtual void execute_coarsening_and_refinement()
active_cell_iterator end_active(const unsigned int level) const
bool is_mixed_mesh() const
cell_iterator last() const
unsigned int n_active_quads() const
void load_user_indices_hex(const std::vector< unsigned int > &v)
unsigned int n_raw_quads() const
void save_user_pointers(std::vector< void * > &v) const
face_iterator begin_face() const
unsigned int n_cells() const
virtual bool prepare_coarsening_and_refinement()
const std::vector< bool > & get_used_vertices() const
typename IteratorSelector::raw_hex_iterator raw_hex_iterator
Definition tria.h:4088
MeshSmoothing smooth_grid
Definition tria.h:3996
void save_refine_flags(std::ostream &out) const
std::unique_ptr< ::internal::TriangulationImplementation::Policy< dim, spacedim > > policy
Definition tria.h:4054
Triangulation< dim, spacedim > & get_triangulation()
void save_user_flags_quad(std::ostream &out) const
Signals signals
Definition tria.h:2507
internal::CellAttachedDataSerializer< dim, spacedim > data_serializer
Definition tria.h:3906
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:4443
unsigned int n_raw_hexs(const unsigned int level) const
void set_all_refine_flags()
unsigned int n_active_hexs() const
virtual std::vector< types::boundary_id > get_boundary_ids() const
void load_user_flags(std::istream &in)
void reset_policy()
void save_coarsen_flags(std::ostream &out) const
active_face_iterator begin_active_face() const
void clear_user_flags_line()
raw_line_iterator begin_raw_line(const unsigned int level=0) const
static void write_bool_vector(const unsigned int magic_number1, const std::vector< bool > &v, const unsigned int magic_number2, std::ostream &out)
void flip_all_direction_flags()
active_cell_iterator begin_active(const unsigned int level=0) const
void execute_coarsening()
void load_attached_data(const unsigned int global_first_cell, const unsigned int global_num_cells, const unsigned int local_num_cells, const std::string &filename, const unsigned int n_attached_deserialize_fixed, const unsigned int n_attached_deserialize_variable)
void pack_data(const std::vector< cell_relation_t > &cell_relations, const std::vector< typename internal::CellAttachedData< dim, spacedim >::pack_callback_t > &pack_callbacks_fixed, const std::vector< typename internal::CellAttachedData< dim, spacedim >::pack_callback_t > &pack_callbacks_variable, const MPI_Comm &mpi_communicator)
Definition tria.cc:141
typename std::pair< cell_iterator, CellStatus > cell_relation_t
Definition tria.h:387
void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation) override
Definition tria.cc:2560
void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation) override
Definition tria.cc:2567
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:2543
void update_neighbors(Triangulation< dim, spacedim > &tria) override
Definition tria.cc:2537
bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell) override
Definition tria.cc:2574
Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells) override
Definition tria.cc:2553
std::unique_ptr< Policy< dim, spacedim > > clone() override
Definition tria.cc:2582
virtual std::unique_ptr< Policy< dim, spacedim > > clone()=0
virtual void update_neighbors(Triangulation< dim, spacedim > &tria)=0
virtual void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation)=0
virtual void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation)=0
virtual Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells)=0
virtual bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell)=0
virtual void delete_children(Triangulation< dim, spacedim > &triangulation, typename Triangulation< dim, spacedim >::cell_iterator &cell, std::vector< unsigned int > &line_cell_count, std::vector< unsigned int > &quad_cell_count)=0
std::vector< std::pair< int, int > > neighbors
std::vector< types::global_cell_index > global_active_cell_indices
std::vector< types::global_cell_index > global_level_cell_indices
std::vector< ReferenceCell > reference_cell
std::vector< types::subdomain_id > level_subdomain_ids
std::vector< types::subdomain_id > subdomain_ids
std::vector< unsigned int > active_cell_indices
std::vector< types::manifold_id > manifold_id
std::vector< BoundaryOrMaterialId > boundary_or_material_id
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:502
#define DEAL_II_CXX20_REQUIRES(condition)
Definition config.h:177
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:503
Point< 3 > vertices[4]
Point< 2 > second
Definition grid_out.cc:4624
Point< 2 > first
Definition grid_out.cc:4623
unsigned int level
Definition grid_out.cc:4626
AdjacentCell adjacent_cells[2]
unsigned int vertex_indices[2]
unsigned int cell_index
IteratorRange< active_cell_iterator > active_cell_iterators_on_level(const unsigned int level) const
IteratorRange< active_face_iterator > active_face_iterators() const
IteratorRange< active_cell_iterator > active_cell_iterators() const
IteratorRange< cell_iterator > cell_iterators_on_level(const unsigned int level) const
IteratorRange< cell_iterator > cell_iterators() const
static ::ExceptionBase & ExcInternalErrorOnCell(int arg1)
static ::ExceptionBase & ExcIO()
static ::ExceptionBase & ExcInteriorQuadCantBeBoundary(int arg1, int arg2, int arg3, int arg4, types::boundary_id arg5)
static ::ExceptionBase & ExcNotImplemented()
static ::ExceptionBase & ExcInconsistentLineInfoOfLine(int arg1, int arg2, std::string arg3)
static ::ExceptionBase & ExcCellHasNegativeMeasure(int arg1)
#define Assert(cond, exc)
static ::ExceptionBase & ExcImpossibleInDim(int arg1)
static ::ExceptionBase & ExcMemoryInexact(int arg1, int arg2)
#define DeclException2(Exception2, type1, type2, outsequence)
Definition exceptions.h:539
#define AssertDimension(dim1, dim2)
#define AssertThrowMPI(error_code)
static ::ExceptionBase & ExcGridHasInvalidCell(int arg1)
static ::ExceptionBase & ExcMultiplySetLineInfoOfLine(int arg1, int arg2)
#define AssertNothrow(cond, exc)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcInteriorLineCantBeBoundary(int arg1, int arg2, types::boundary_id arg3)
#define DeclException3(Exception3, type1, type2, type3, outsequence)
Definition exceptions.h:562
#define DeclException1(Exception1, type1, outsequence)
Definition exceptions.h:516
static ::ExceptionBase & ExcInvalidVertexIndex(int arg1, int arg2, int arg3)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define DeclException5( Exception5, type1, type2, type3, type4, type5, outsequence)
Definition exceptions.h:611
#define AssertThrow(cond, exc)
static ::ExceptionBase & ExcInconsistentQuadInfoOfQuad(int arg1, int arg2, int arg3, int arg4, std::string arg5)
typename IteratorSelector::hex_iterator hex_iterator
Definition tria.h:1685
typename IteratorSelector::active_quad_iterator active_quad_iterator
Definition tria.h:1676
typename IteratorSelector::active_hex_iterator active_hex_iterator
Definition tria.h:1696
typename IteratorSelector::quad_iterator quad_iterator
Definition tria.h:1661
typename IteratorSelector::line_iterator line_iterator
Definition tria.h:1637
TriaIterator< CellAccessor< dim, spacedim > > cell_iterator
Definition tria.h:1550
typename IteratorSelector::active_line_iterator active_line_iterator
Definition tria.h:1652
void set_all_manifold_ids_on_boundary(const types::manifold_id number)
const Manifold< dim, spacedim > & get_manifold(const types::manifold_id number) const
virtual std::vector< types::manifold_id > get_manifold_ids() const
void reset_manifold(const types::manifold_id manifold_number)
void set_manifold(const types::manifold_id number, const Manifold< dim, spacedim > &manifold_object)
void reset_all_manifolds()
void set_all_manifold_ids(const types::manifold_id number)
Task< RT > new_task(const std::function< RT()> &function)
#define AssertIsNotUsed(obj)
#define DEAL_II_ASSERT_UNREACHABLE()
#define DEAL_II_NOT_IMPLEMENTED()
const unsigned int mn_tria_refine_flags_end
const unsigned int mn_tria_coarsen_flags_end
const unsigned int mn_tria_refine_flags_begin
const unsigned int mn_tria_hex_user_flags_end
const unsigned int mn_tria_line_user_flags_begin
const unsigned int mn_tria_line_user_flags_end
const unsigned int mn_tria_quad_user_flags_end
const unsigned int mn_tria_coarsen_flags_begin
const unsigned int mn_tria_hex_user_flags_begin
const unsigned int mn_tria_quad_user_flags_begin
const Mapping< dim, spacedim > & get_default_linear_mapping(const Triangulation< dim, spacedim > &triangulation)
Definition mapping.cc:294
void create_triangulation(Triangulation< dim, dim > &tria, const AdditionalData &additional_data=AdditionalData())
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:14822
const Manifold< dim, spacedim > & get_default_flat_manifold()
Definition tria.cc:11991
unsigned int n_cells(const internal::TriangulationImplementation::NumberCache< 1 > &c)
Definition tria.cc:14815
void reserve_space(TriaFaces &tria_faces, const unsigned int new_quads_in_pairs, const unsigned int new_quads_single)
Definition tria.cc:1995
void monitor_memory(const TriaLevel &tria_level, const unsigned int true_dimension)
Definition tria.cc:2198
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:1731
boost::signals2::signal< void(const Triangulation< dim, spacedim > &destination_tria)> copy
Definition tria.h:2353
static void update_neighbors(Triangulation< 1, spacedim > &)
Definition tria.cc:11868
static Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:11953
static bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &)
Definition tria.cc:11979
static void update_neighbors(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:11872
static void delete_children(Triangulation< dim, spacedim > &triangulation, typename Triangulation< dim, spacedim >::cell_iterator &cell, std::vector< unsigned int > &line_cell_count, std::vector< unsigned int > &quad_cell_count)
Definition tria.cc:11938
static void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:11971
static void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:11962
static void reserve_space_(TriaObjects &obj, const unsigned int size)
Definition tria.cc:3627
static void reserve_space_(TriaFaces &faces, const unsigned structdim, const unsigned int size)
Definition tria.cc:3566
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:2788
static void prevent_distorted_boundary_cells(Triangulation< 1, spacedim > &)
Definition tria.cc:11475
static void update_neighbors(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:3016
static void prepare_refinement_dim_dependent(const Triangulation< dim, spacedim > &)
Definition tria.cc:11563
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:3922
static void reserve_space_(TriaLevel &level, const unsigned int spacedim, const unsigned int size, const bool orientation_needed)
Definition tria.cc:3588
static void update_neighbors(Triangulation< 1, spacedim > &)
Definition tria.cc:3010
static Triangulation< 3, spacedim >::DistortedCellList execute_refinement(Triangulation< 3, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:7114
static Triangulation< dim, spacedim >::DistortedCellList execute_refinement_isotropic(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:4917
static void compute_number_cache(const Triangulation< dim, spacedim > &triangulation, const unsigned int level_objects, internal::TriangulationImplementation::NumberCache< dim > &number_cache)
Definition tria.cc:2988
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:4550
static void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:11482
static bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell)
Definition tria.cc:11796
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:2895
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:3680
static void prepare_refinement_dim_dependent(Triangulation< 3, spacedim > &triangulation)
Definition tria.cc:11573
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:3784
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:2700
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:5921
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:3195
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:3458
std::vector< std::vector< CellData< dim > > > cell_infos