Reference documentation for deal.II version GIT relicensing-439-g5fda5c893d 2024-04-20 06:50:02+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
tria.cc
Go to the documentation of this file.
1// ------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: LGPL-2.1-or-later
4// Copyright (C) 1999 - 2024 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Part of the source code is dual licensed under Apache-2.0 WITH
9// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
10// governing the source code and code contributions can be found in
11// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
12//
13// ------------------------------------------------------------------------
14
15
18#include <deal.II/base/mpi.templates.h>
23
25
30#include <deal.II/grid/tria.h>
35
36#include <boost/archive/text_iarchive.hpp>
37#include <boost/archive/text_oarchive.hpp>
38
39#include <algorithm>
40#include <array>
41#include <cmath>
42#include <cstdint>
43#include <fstream>
44#include <functional>
45#include <limits>
46#include <list>
47#include <map>
48#include <memory>
49#include <numeric>
50
51
53
54
55namespace internal
56{
57 namespace TriangulationImplementation
58 {
60 : n_levels(0)
61 , n_lines(0)
62 , n_active_lines(0)
63 // all other fields are
64 // default constructed
65 {}
66
67
68
69 std::size_t
71 {
72 std::size_t mem =
77 MemoryConsumption::memory_consumption(n_active_lines_level);
78
79 if (active_cell_index_partitioner)
80 mem += active_cell_index_partitioner->memory_consumption();
81
82 for (const auto &partitioner : level_cell_index_partitioners)
83 if (partitioner)
84 mem += partitioner->memory_consumption();
85
86 return mem;
87 }
88
89
91 : n_quads(0)
92 , n_active_quads(0)
93 // all other fields are
94 // default constructed
95 {}
96
97
98
99 std::size_t
108
109
110
112 : n_hexes(0)
113 , n_active_hexes(0)
114 // all other fields are
115 // default constructed
116 {}
117
118
119
120 std::size_t
129 } // namespace TriangulationImplementation
130
131
132 template <int dim, int spacedim>
135 : variable_size_data_stored(false)
136 {}
137
138
139 template <int dim, int spacedim>
141 void CellAttachedDataSerializer<dim, spacedim>::pack_data(
142 const std::vector<cell_relation_t> &cell_relations,
143 const std::vector<
144 typename internal::CellAttachedData<dim, spacedim>::pack_callback_t>
145 &pack_callbacks_fixed,
146 const std::vector<
147 typename internal::CellAttachedData<dim, spacedim>::pack_callback_t>
148 &pack_callbacks_variable,
149 const MPI_Comm &mpi_communicator)
150 {
151 Assert(src_data_fixed.empty(),
152 ExcMessage("Previously packed data has not been released yet!"));
153 Assert(src_sizes_variable.empty(), ExcInternalError());
154
155 const unsigned int n_callbacks_fixed = pack_callbacks_fixed.size();
156 const unsigned int n_callbacks_variable = pack_callbacks_variable.size();
157
158 // Store information that we packed variable size data in
159 // a member variable for later.
160 variable_size_data_stored = (n_callbacks_variable > 0);
161
162 // If variable transfer is scheduled, we will store the data size that
163 // each variable size callback function writes in this auxiliary
164 // container. The information will be stored by each cell in this vector
165 // temporarily.
166 std::vector<unsigned int> cell_sizes_variable_cumulative(
167 n_callbacks_variable);
168
169 // Prepare the buffer structure, in which each callback function will
170 // store its data for each active cell.
171 // The outmost shell in this container construct corresponds to the
172 // data packed per cell. The next layer resembles the data that
173 // each callback function packs on the corresponding cell. These
174 // buffers are chains of chars stored in an std::vector<char>.
175 // A visualisation of the data structure:
176 /* clang-format off */
177 // | cell_1 | | cell_2 | ...
178 // || callback_1 || callback_2 |...| || callback_1 || callback_2 |...| ...
179 // |||char|char|...|||char|char|...|...| |||char|char|...|||char|char|...|...| ...
180 /* clang-format on */
181 std::vector<std::vector<std::vector<char>>> packed_fixed_size_data(
182 cell_relations.size());
183 std::vector<std::vector<std::vector<char>>> packed_variable_size_data(
184 variable_size_data_stored ? cell_relations.size() : 0);
185
186 //
187 // --------- Pack data for fixed and variable size transfer ---------
188 //
189 // Iterate over all cells, call all callback functions on each cell,
190 // and store their data in the corresponding buffer scope.
191 {
192 auto cell_rel_it = cell_relations.cbegin();
193 auto data_cell_fixed_it = packed_fixed_size_data.begin();
194 auto data_cell_variable_it = packed_variable_size_data.begin();
195 for (; cell_rel_it != cell_relations.cend(); ++cell_rel_it)
196 {
197 const auto &dealii_cell = cell_rel_it->first;
198 const auto &cell_status = cell_rel_it->second;
199
200 // Assertions about the tree structure.
201 switch (cell_status)
202 {
205 // double check the condition that we will only ever attach
206 // data to active cells when we get here
207 Assert(dealii_cell->is_active(), ExcInternalError());
208 break;
209
211 // double check the condition that we will only ever attach
212 // data to cells with children when we get here. however, we
213 // can only tolerate one level of coarsening at a time, so
214 // check that the children are all active
215 Assert(dealii_cell->is_active() == false, ExcInternalError());
216 for (unsigned int c = 0;
217 c < GeometryInfo<dim>::max_children_per_cell;
218 ++c)
219 Assert(dealii_cell->child(c)->is_active(),
221 break;
222
224 // do nothing on invalid cells
225 break;
226
227 default:
229 break;
230 }
231
232 // Reserve memory corresponding to the number of callback
233 // functions that will be called.
234 // If variable size transfer is scheduled, we need to leave
235 // room for an array that holds information about how many
236 // bytes each of the variable size callback functions will
237 // write.
238 // On cells flagged with CellStatus::cell_invalid, only its CellStatus
239 // will be stored.
240 const unsigned int n_fixed_size_data_sets_on_cell =
241 1 + ((cell_status == CellStatus::cell_invalid) ?
242 0 :
243 ((variable_size_data_stored ? 1 : 0) + n_callbacks_fixed));
244 data_cell_fixed_it->resize(n_fixed_size_data_sets_on_cell);
245
246 // We continue with packing all data on this specific cell.
247 auto data_fixed_it = data_cell_fixed_it->begin();
248
249 // First, we pack the CellStatus information.
250 // to get consistent data sizes on each cell for the fixed size
251 // transfer, we won't allow compression
252 *data_fixed_it =
253 Utilities::pack(cell_status, /*allow_compression=*/false);
254 ++data_fixed_it;
255
256 // Proceed with all registered callback functions.
257 // Skip cells with the CellStatus::cell_invalid flag.
258 if (cell_status != CellStatus::cell_invalid)
259 {
260 // Pack fixed size data.
261 for (auto callback_it = pack_callbacks_fixed.cbegin();
262 callback_it != pack_callbacks_fixed.cend();
263 ++callback_it, ++data_fixed_it)
264 {
265 *data_fixed_it = (*callback_it)(dealii_cell, cell_status);
266 }
267
268 // Pack variable size data.
269 // If we store variable size data, we need to transfer
270 // the sizes of each corresponding callback function
271 // via fixed size transfer as well.
272 if (variable_size_data_stored)
273 {
274 const unsigned int n_variable_size_data_sets_on_cell =
275 ((cell_status == CellStatus::cell_invalid) ?
276 0 :
277 n_callbacks_variable);
278 data_cell_variable_it->resize(
279 n_variable_size_data_sets_on_cell);
280
281 auto callback_it = pack_callbacks_variable.cbegin();
282 auto data_variable_it = data_cell_variable_it->begin();
283 auto sizes_variable_it =
284 cell_sizes_variable_cumulative.begin();
285 for (; callback_it != pack_callbacks_variable.cend();
286 ++callback_it, ++data_variable_it, ++sizes_variable_it)
287 {
288 *data_variable_it =
289 (*callback_it)(dealii_cell, cell_status);
290
291 // Store data sizes for each callback function first.
292 // Make it cumulative below.
293 *sizes_variable_it = data_variable_it->size();
294 }
295
296 // Turn size vector into its cumulative representation.
297 std::partial_sum(cell_sizes_variable_cumulative.begin(),
298 cell_sizes_variable_cumulative.end(),
299 cell_sizes_variable_cumulative.begin());
300
301 // Serialize cumulative variable size vector
302 // value-by-value. This way we can circumvent the overhead
303 // of storing the container object as a whole, since we
304 // know its size by the number of registered callback
305 // functions.
306 data_fixed_it->resize(n_callbacks_variable *
307 sizeof(unsigned int));
308 for (unsigned int i = 0; i < n_callbacks_variable; ++i)
309 std::memcpy(&(data_fixed_it->at(i * sizeof(unsigned int))),
310 &(cell_sizes_variable_cumulative.at(i)),
311 sizeof(unsigned int));
312
313 ++data_fixed_it;
314 }
315
316 // Double check that we packed everything we wanted
317 // in the fixed size buffers.
318 Assert(data_fixed_it == data_cell_fixed_it->end(),
320 }
321
322 ++data_cell_fixed_it;
323
324 // Increment the variable size data iterator
325 // only if we actually pack this kind of data
326 // to avoid getting out of bounds.
327 if (variable_size_data_stored)
328 ++data_cell_variable_it;
329 } // loop over cell_relations
330 }
331
332 //
333 // ----------- Gather data sizes for fixed size transfer ------------
334 //
335 // Generate a vector which stores the sizes of each callback function,
336 // including the packed CellStatus transfer.
337 // Find the very first cell that we wrote to with all callback
338 // functions (i.e. a cell that was not flagged with
339 // CellStatus::cell_invalid) and store the sizes of each buffer.
340 //
341 // To deal with the case that at least one of the processors does not
342 // own any cell at all, we will exchange the information about the data
343 // sizes among them later. The code in between is still well-defined,
344 // since the following loops will be skipped.
345 std::vector<unsigned int> local_sizes_fixed(
346 1 + n_callbacks_fixed + (variable_size_data_stored ? 1 : 0));
347 for (const auto &data_cell : packed_fixed_size_data)
348 {
349 if (data_cell.size() == local_sizes_fixed.size())
350 {
351 auto sizes_fixed_it = local_sizes_fixed.begin();
352 auto data_fixed_it = data_cell.cbegin();
353 for (; data_fixed_it != data_cell.cend();
354 ++data_fixed_it, ++sizes_fixed_it)
355 {
356 *sizes_fixed_it = data_fixed_it->size();
357 }
358
359 break;
360 }
361 }
362
363 // Check if all cells have valid sizes.
364 for (auto data_cell_fixed_it = packed_fixed_size_data.cbegin();
365 data_cell_fixed_it != packed_fixed_size_data.cend();
366 ++data_cell_fixed_it)
367 {
368 Assert((data_cell_fixed_it->size() == 1) ||
369 (data_cell_fixed_it->size() == local_sizes_fixed.size()),
371 }
372
373 // Share information about the packed data sizes
374 // of all callback functions across all processors, in case one
375 // of them does not own any cells at all.
376 std::vector<unsigned int> global_sizes_fixed(local_sizes_fixed.size());
377 Utilities::MPI::max(local_sizes_fixed,
378 mpi_communicator,
379 global_sizes_fixed);
380
381 // Construct cumulative sizes, since this is the only information
382 // we need from now on.
383 sizes_fixed_cumulative.resize(global_sizes_fixed.size());
384 std::partial_sum(global_sizes_fixed.begin(),
385 global_sizes_fixed.end(),
386 sizes_fixed_cumulative.begin());
387
388 //
389 // ---------- Gather data sizes for variable size transfer ----------
390 //
391 if (variable_size_data_stored)
392 {
393 src_sizes_variable.reserve(packed_variable_size_data.size());
394 for (const auto &data_cell : packed_variable_size_data)
395 {
396 int variable_data_size_on_cell = 0;
397
398 for (const auto &data : data_cell)
399 variable_data_size_on_cell += data.size();
401 src_sizes_variable.push_back(variable_data_size_on_cell);
402 }
403 }
404
405 //
406 // ------------------------ Build buffers ---------------------------
407 //
408 const unsigned int expected_size_fixed =
409 cell_relations.size() * sizes_fixed_cumulative.back();
410 const unsigned int expected_size_variable =
411 std::accumulate(src_sizes_variable.begin(),
412 src_sizes_variable.end(),
413 std::vector<int>::size_type(0));
414
415 // Move every piece of packed fixed size data into the consecutive
416 // buffer.
417 src_data_fixed.reserve(expected_size_fixed);
418 for (const auto &data_cell_fixed : packed_fixed_size_data)
419 {
420 // Move every fraction of packed data into the buffer
421 // reserved for this particular cell.
422 for (const auto &data_fixed : data_cell_fixed)
423 std::move(data_fixed.begin(),
424 data_fixed.end(),
425 std::back_inserter(src_data_fixed));
426
427 // If we only packed the CellStatus information
428 // (i.e. encountered a cell flagged CellStatus::cell_invalid),
429 // fill the remaining space with invalid entries.
430 // We can skip this if there is nothing else to pack.
431 if ((data_cell_fixed.size() == 1) &&
432 (sizes_fixed_cumulative.size() > 1))
434 const std::size_t bytes_skipped =
435 sizes_fixed_cumulative.back() - sizes_fixed_cumulative.front();
436
437 src_data_fixed.insert(src_data_fixed.end(),
438 bytes_skipped,
439 static_cast<char>(-1)); // invalid_char
440 }
441 }
442
443 // Move every piece of packed variable size data into the consecutive
444 // buffer.
445 if (variable_size_data_stored)
446 {
447 src_data_variable.reserve(expected_size_variable);
448 for (const auto &data_cell : packed_variable_size_data)
449 {
450 // Move every fraction of packed data into the buffer
451 // reserved for this particular cell.
452 for (const auto &data : data_cell)
453 std::move(data.begin(),
454 data.end(),
455 std::back_inserter(src_data_variable));
456 }
458
459 // Double check that we packed everything correctly.
460 Assert(src_data_fixed.size() == expected_size_fixed, ExcInternalError());
461 Assert(src_data_variable.size() == expected_size_variable,
463 }
464
465
466
467 template <int dim, int spacedim>
469 void CellAttachedDataSerializer<dim, spacedim>::unpack_cell_status(
470 std::vector<
471 typename CellAttachedDataSerializer<dim, spacedim>::cell_relation_t>
472 &cell_relations) const
473 {
474 Assert(sizes_fixed_cumulative.size() > 0,
475 ExcMessage("No data has been packed!"));
476 if (cell_relations.size() > 0)
477 {
478 Assert(dest_data_fixed.size() > 0,
479 ExcMessage("No data has been received!"));
480 }
482 // Size of CellStatus object that will be unpacked on each cell.
483 const unsigned int size = sizes_fixed_cumulative.front();
484
485 // Iterate over all cells and overwrite the CellStatus
486 // information from the transferred data.
487 // Proceed buffer iterator position to next cell after
488 // each iteration.
489 auto cell_rel_it = cell_relations.begin();
490 auto dest_fixed_it = dest_data_fixed.cbegin();
491 for (; cell_rel_it != cell_relations.end();
492 ++cell_rel_it, dest_fixed_it += sizes_fixed_cumulative.back())
493 {
494 cell_rel_it->second = // cell_status
495 Utilities::unpack<CellStatus>(dest_fixed_it,
496 dest_fixed_it + size,
497 /*allow_compression=*/false);
498 }
499 }
500
501
502
503 template <int dim, int spacedim>
505 void CellAttachedDataSerializer<dim, spacedim>::unpack_data(
506 const std::vector<
507 typename CellAttachedDataSerializer<dim, spacedim>::cell_relation_t>
508 &cell_relations,
509 const unsigned int handle,
510 const std::function<
511 void(const cell_iterator &,
512 const CellStatus &,
513 const boost::iterator_range<std::vector<char>::const_iterator> &)>
514 &unpack_callback) const
515 {
516 // We decode the handle returned by register_data_attach() back into
517 // a format we can use. All even handles belong to those callback
518 // functions which write/read variable size data, all odd handles
519 // interact with fixed size buffers.
520 const bool callback_variable_transfer = (handle % 2 == 0);
521 const unsigned int callback_index = handle / 2;
522
523 // Cells will always receive fixed size data (i.e., CellStatus
524 // information), but not necessarily variable size data (e.g., with a
525 // ParticleHandler a cell might not contain any particle at all).
526 // Thus it is sufficient to check if fixed size data has been received.
527 Assert(sizes_fixed_cumulative.size() > 0,
528 ExcMessage("No data has been packed!"));
529 if (cell_relations.size() > 0)
530 {
531 Assert(dest_data_fixed.size() > 0,
532 ExcMessage("No data has been received!"));
533 }
534
535 std::vector<char>::const_iterator dest_data_it;
536 std::vector<char>::const_iterator dest_sizes_cell_it;
537
538 // Depending on whether our callback function unpacks fixed or
539 // variable size data, we have to pursue different approaches
540 // to localize the correct fraction of the buffer from which
541 // we are allowed to read.
542 unsigned int offset = numbers::invalid_unsigned_int;
543 unsigned int size = numbers::invalid_unsigned_int;
544 unsigned int data_increment = numbers::invalid_unsigned_int;
545
546 if (callback_variable_transfer)
547 {
548 // For the variable size data, we need to extract the
549 // data size from the fixed size buffer on each cell.
550 //
551 // We packed this information last, so the last packed
552 // object in the fixed size buffer corresponds to the
553 // variable data sizes.
554 //
555 // The last entry of sizes_fixed_cumulative corresponds
556 // to the size of all fixed size data packed on the cell.
557 // To get the offset for the last packed object, we need
558 // to get the next-to-last entry.
559 const unsigned int offset_variable_data_sizes =
560 sizes_fixed_cumulative[sizes_fixed_cumulative.size() - 2];
561
562 // This iterator points to the data size that the
563 // callback_function packed for each specific cell.
564 // Adjust buffer iterator to the offset of the callback
565 // function so that we only have to advance its position
566 // to the next cell after each iteration.
567 dest_sizes_cell_it = dest_data_fixed.cbegin() +
568 offset_variable_data_sizes +
569 callback_index * sizeof(unsigned int);
570
571 // Let the data iterator point to the correct buffer.
572 dest_data_it = dest_data_variable.cbegin();
573 }
574 else
575 {
576 // For the fixed size data, we can get the information about
577 // the buffer location on each cell directly from the
578 // sizes_fixed_cumulative vector.
579 offset = sizes_fixed_cumulative[callback_index];
580 size = sizes_fixed_cumulative[callback_index + 1] - offset;
581 data_increment = sizes_fixed_cumulative.back();
582
583 // Let the data iterator point to the correct buffer.
584 // Adjust buffer iterator to the offset of the callback
585 // function so that we only have to advance its position
586 // to the next cell after each iteration.
587 if (cell_relations.begin() != cell_relations.end())
588 dest_data_it = dest_data_fixed.cbegin() + offset;
589 }
590
591 // Iterate over all cells and unpack the transferred data.
592 auto cell_rel_it = cell_relations.begin();
593 auto dest_sizes_it = dest_sizes_variable.cbegin();
594 for (; cell_rel_it != cell_relations.end(); ++cell_rel_it)
595 {
596 const auto &dealii_cell = cell_rel_it->first;
597 const auto &cell_status = cell_rel_it->second;
598
599 if (callback_variable_transfer)
600 {
601 // Update the increment according to the whole data size
602 // of the current cell.
603 data_increment = *dest_sizes_it;
604
605 if (cell_status != CellStatus::cell_invalid)
606 {
607 // Extract the corresponding values for offset and size from
608 // the cumulative sizes array stored in the fixed size
609 // buffer.
610 if (callback_index == 0)
611 offset = 0;
612 else
613 std::memcpy(&offset,
614 &(*(dest_sizes_cell_it - sizeof(unsigned int))),
615 sizeof(unsigned int));
616
617 std::memcpy(&size,
618 &(*dest_sizes_cell_it),
619 sizeof(unsigned int));
620
621 size -= offset;
622
623 // Move the data iterator to the corresponding position
624 // of the callback function and adjust the increment
625 // accordingly.
626 dest_data_it += offset;
627 data_increment -= offset;
628 }
629
630 // Advance data size iterators to the next cell, avoid iterating
631 // past the end of dest_sizes_cell_it
632 if (cell_rel_it != cell_relations.end() - 1)
633 dest_sizes_cell_it += sizes_fixed_cumulative.back();
634 ++dest_sizes_it;
635 }
636
637 switch (cell_status)
638 {
641 unpack_callback(dealii_cell,
642 cell_status,
643 boost::make_iterator_range(dest_data_it,
644 dest_data_it + size));
645 break;
646
648 unpack_callback(dealii_cell->parent(),
649 cell_status,
650 boost::make_iterator_range(dest_data_it,
651 dest_data_it + size));
652 break;
653
655 // Skip this cell.
656 break;
657
658 default:
660 break;
661 }
662
663 if (cell_rel_it != cell_relations.end() - 1)
664 dest_data_it += data_increment;
665 }
666 }
667
668
669
670 template <int dim, int spacedim>
672 void CellAttachedDataSerializer<dim, spacedim>::save(
673 const unsigned int global_first_cell,
674 const unsigned int global_num_cells,
675 const std::string &filename,
676 const MPI_Comm &mpi_communicator) const
677 {
678 Assert(sizes_fixed_cumulative.size() > 0,
679 ExcMessage("No data has been packed!"));
680
681#ifdef DEAL_II_WITH_MPI
682 // Large fractions of this function have been copied from
683 // DataOutInterface::write_vtu_in_parallel.
684 // TODO: Write general MPIIO interface.
685
686 const int myrank = Utilities::MPI::this_mpi_process(mpi_communicator);
687 const int mpisize = Utilities::MPI::n_mpi_processes(mpi_communicator);
688
689 if (mpisize > 1)
690 {
691 const unsigned int bytes_per_cell = sizes_fixed_cumulative.back();
692
693 //
694 // ---------- Fixed size data ----------
695 //
696 {
697 const std::string fname_fixed = std::string(filename) + "_fixed.data";
698
699 MPI_Info info;
700 int ierr = MPI_Info_create(&info);
701 AssertThrowMPI(ierr);
702
703 MPI_File fh;
704 ierr = MPI_File_open(mpi_communicator,
705 fname_fixed.c_str(),
706 MPI_MODE_CREATE | MPI_MODE_WRONLY,
707 info,
708 &fh);
709 AssertThrowMPI(ierr);
710
711 ierr = MPI_File_set_size(fh, 0); // delete the file contents
712 AssertThrowMPI(ierr);
713 // this barrier is necessary, because otherwise others might already
714 // write while one core is still setting the size to zero.
715 ierr = MPI_Barrier(mpi_communicator);
716 AssertThrowMPI(ierr);
717 ierr = MPI_Info_free(&info);
718 AssertThrowMPI(ierr);
719 // ------------------
720
721 // Write cumulative sizes to file.
722 // Since each processor owns the same information about the data
723 // sizes, it is sufficient to let only the first processor perform
724 // this task.
725 if (myrank == 0)
726 {
728 fh,
729 0,
730 sizes_fixed_cumulative.data(),
731 sizes_fixed_cumulative.size(),
732 MPI_UNSIGNED,
733 MPI_STATUS_IGNORE);
734 AssertThrowMPI(ierr);
735 }
736
737 // Write packed data to file simultaneously.
738 const MPI_Offset size_header =
739 sizes_fixed_cumulative.size() * sizeof(unsigned int);
740
741 // Make sure we do the following computation in 64bit integers to be
742 // able to handle 4GB+ files:
743 const MPI_Offset my_global_file_position =
744 size_header +
745 static_cast<MPI_Offset>(global_first_cell) * bytes_per_cell;
746
747 ierr =
749 my_global_file_position,
750 src_data_fixed.data(),
751 src_data_fixed.size(),
752 MPI_BYTE,
753 MPI_STATUS_IGNORE);
754 AssertThrowMPI(ierr);
755
756 ierr = MPI_File_close(&fh);
757 AssertThrowMPI(ierr);
758 }
759
760
761
762 //
763 // ---------- Variable size data ----------
764 //
765 if (variable_size_data_stored)
766 {
767 const std::string fname_variable =
768 std::string(filename) + "_variable.data";
769
770 MPI_Info info;
771 int ierr = MPI_Info_create(&info);
772 AssertThrowMPI(ierr);
773
774 MPI_File fh;
775 ierr = MPI_File_open(mpi_communicator,
776 fname_variable.c_str(),
777 MPI_MODE_CREATE | MPI_MODE_WRONLY,
778 info,
779 &fh);
780 AssertThrowMPI(ierr);
781
782 ierr = MPI_File_set_size(fh, 0); // delete the file contents
783 AssertThrowMPI(ierr);
784 // this barrier is necessary, because otherwise others might already
785 // write while one core is still setting the size to zero.
786 ierr = MPI_Barrier(mpi_communicator);
787 AssertThrowMPI(ierr);
788 ierr = MPI_Info_free(&info);
789 AssertThrowMPI(ierr);
790
791 // Write sizes of each cell into file simultaneously.
792 {
793 const MPI_Offset my_global_file_position =
794 static_cast<MPI_Offset>(global_first_cell) *
795 sizeof(unsigned int);
796
797 // It is very unlikely that a single process has more than
798 // 2 billion cells, but we might as well check.
799 AssertThrow(src_sizes_variable.size() <
800 static_cast<std::size_t>(
801 std::numeric_limits<int>::max()),
803
805 fh,
806 my_global_file_position,
807 src_sizes_variable.data(),
808 src_sizes_variable.size(),
809 MPI_INT,
810 MPI_STATUS_IGNORE);
811 AssertThrowMPI(ierr);
812 }
813
814 // Gather size of data in bytes we want to store from this
815 // processor and compute the prefix sum. We do this in 64 bit
816 // to avoid overflow for files larger than 4GB:
817 const std::uint64_t size_on_proc = src_data_variable.size();
818 std::uint64_t prefix_sum = 0;
819 ierr = MPI_Exscan(&size_on_proc,
820 &prefix_sum,
821 1,
822 MPI_UINT64_T,
823 MPI_SUM,
824 mpi_communicator);
825 AssertThrowMPI(ierr);
826
827 const MPI_Offset my_global_file_position =
828 static_cast<MPI_Offset>(global_num_cells) * sizeof(unsigned int) +
829 prefix_sum;
830
831 // Write data consecutively into file.
833 fh,
834 my_global_file_position,
835 src_data_variable.data(),
836 src_data_variable.size(),
837 MPI_BYTE,
838 MPI_STATUS_IGNORE);
839 AssertThrowMPI(ierr);
840
841
842 ierr = MPI_File_close(&fh);
843 AssertThrowMPI(ierr);
844 }
845 } // if (mpisize > 1)
846 else
847#endif
848 {
849 (void)global_first_cell;
850 (void)global_num_cells;
851 (void)mpi_communicator;
852
853 //
854 // ---------- Fixed size data ----------
855 //
856 {
857 const std::string fname_fixed = std::string(filename) + "_fixed.data";
858
859 std::ofstream file(fname_fixed, std::ios::binary | std::ios::out);
860
861 // Write header data.
862 file.write(reinterpret_cast<const char *>(
863 sizes_fixed_cumulative.data()),
864 sizes_fixed_cumulative.size() * sizeof(unsigned int));
865
866 // Write packed data.
867 file.write(reinterpret_cast<const char *>(src_data_fixed.data()),
868 src_data_fixed.size() * sizeof(char));
869
870 file.close();
871 }
872
873 //
874 // ---------- Variable size data ----------
875 //
876 if (variable_size_data_stored)
877 {
878 const std::string fname_variable =
879 std::string(filename) + "_variable.data";
880
881 std::ofstream file(fname_variable,
882 std::ios::binary | std::ios::out);
883
884 // Write header data.
885 file.write(reinterpret_cast<const char *>(
886 src_sizes_variable.data()),
887 src_sizes_variable.size() * sizeof(int));
888
889 // Write packed data.
890 file.write(reinterpret_cast<const char *>(src_data_variable.data()),
891 src_data_variable.size() * sizeof(char));
892
893 file.close();
894 }
895 }
896 }
897
898
899 template <int dim, int spacedim>
901 void CellAttachedDataSerializer<dim, spacedim>::load(
902 const unsigned int global_first_cell,
903 const unsigned int global_num_cells,
904 const unsigned int local_num_cells,
905 const std::string &filename,
906 const unsigned int n_attached_deserialize_fixed,
907 const unsigned int n_attached_deserialize_variable,
908 const MPI_Comm &mpi_communicator)
909 {
910 Assert(dest_data_fixed.empty(),
911 ExcMessage("Previously loaded data has not been released yet!"));
912
913 variable_size_data_stored = (n_attached_deserialize_variable > 0);
914
915#ifdef DEAL_II_WITH_MPI
916 // Large fractions of this function have been copied from
917 // DataOutInterface::write_vtu_in_parallel.
918 // TODO: Write general MPIIO interface.
919
920 const int mpisize = Utilities::MPI::n_mpi_processes(mpi_communicator);
921
922 if (mpisize > 1)
923 {
924 //
925 // ---------- Fixed size data ----------
926 //
927 {
928 const std::string fname_fixed = std::string(filename) + "_fixed.data";
929
930 MPI_Info info;
931 int ierr = MPI_Info_create(&info);
932 AssertThrowMPI(ierr);
933
934 MPI_File fh;
935 ierr = MPI_File_open(
936 mpi_communicator, fname_fixed.c_str(), MPI_MODE_RDONLY, info, &fh);
937 AssertThrowMPI(ierr);
938
939 ierr = MPI_Info_free(&info);
940 AssertThrowMPI(ierr);
941
942 // Read cumulative sizes from file.
943 // Since all processors need the same information about the data
944 // sizes, let each of them retrieve it by reading from the same
945 // location in the file.
946 sizes_fixed_cumulative.resize(1 + n_attached_deserialize_fixed +
947 (variable_size_data_stored ? 1 : 0));
949 fh,
950 0,
951 sizes_fixed_cumulative.data(),
952 sizes_fixed_cumulative.size(),
953 MPI_UNSIGNED,
954 MPI_STATUS_IGNORE);
955 AssertThrowMPI(ierr);
956
957 // Allocate sufficient memory.
958 const unsigned int bytes_per_cell = sizes_fixed_cumulative.back();
959 dest_data_fixed.resize(static_cast<size_t>(local_num_cells) *
960 bytes_per_cell);
961
962 // Read packed data from file simultaneously.
963 const MPI_Offset size_header =
964 sizes_fixed_cumulative.size() * sizeof(unsigned int);
965
966 // Make sure we do the following computation in 64bit integers to be
967 // able to handle 4GB+ files:
968 const MPI_Offset my_global_file_position =
969 size_header +
970 static_cast<MPI_Offset>(global_first_cell) * bytes_per_cell;
971
972 ierr =
974 my_global_file_position,
975 dest_data_fixed.data(),
976 dest_data_fixed.size(),
977 MPI_BYTE,
978 MPI_STATUS_IGNORE);
979 AssertThrowMPI(ierr);
980
981
982 ierr = MPI_File_close(&fh);
983 AssertThrowMPI(ierr);
984 }
985
986 //
987 // ---------- Variable size data ----------
988 //
989 if (variable_size_data_stored)
990 {
991 const std::string fname_variable =
992 std::string(filename) + "_variable.data";
993
994 MPI_Info info;
995 int ierr = MPI_Info_create(&info);
996 AssertThrowMPI(ierr);
997
998 MPI_File fh;
999 ierr = MPI_File_open(mpi_communicator,
1000 fname_variable.c_str(),
1001 MPI_MODE_RDONLY,
1002 info,
1003 &fh);
1004 AssertThrowMPI(ierr);
1005
1006 ierr = MPI_Info_free(&info);
1007 AssertThrowMPI(ierr);
1008
1009 // Read sizes of all locally owned cells.
1010 dest_sizes_variable.resize(local_num_cells);
1011
1012 const MPI_Offset my_global_file_position_sizes =
1013 static_cast<MPI_Offset>(global_first_cell) * sizeof(unsigned int);
1014
1016 fh,
1017 my_global_file_position_sizes,
1018 dest_sizes_variable.data(),
1019 dest_sizes_variable.size(),
1020 MPI_INT,
1021 MPI_STATUS_IGNORE);
1022 AssertThrowMPI(ierr);
1023
1024
1025 // Compute my data size in bytes and compute prefix sum. We do this
1026 // in 64 bit to avoid overflow for files larger than 4 GB:
1027 const std::uint64_t size_on_proc =
1028 std::accumulate(dest_sizes_variable.begin(),
1029 dest_sizes_variable.end(),
1030 0ULL);
1031
1032 std::uint64_t prefix_sum = 0;
1033 ierr = MPI_Exscan(&size_on_proc,
1034 &prefix_sum,
1035 1,
1036 MPI_UINT64_T,
1037 MPI_SUM,
1038 mpi_communicator);
1039 AssertThrowMPI(ierr);
1040
1041 const MPI_Offset my_global_file_position =
1042 static_cast<MPI_Offset>(global_num_cells) * sizeof(unsigned int) +
1043 prefix_sum;
1044
1045 dest_data_variable.resize(size_on_proc);
1046
1048 fh,
1049 my_global_file_position,
1050 dest_data_variable.data(),
1051 dest_data_variable.size(),
1052 MPI_BYTE,
1053 MPI_STATUS_IGNORE);
1054 AssertThrowMPI(ierr);
1055
1056 ierr = MPI_File_close(&fh);
1057 AssertThrowMPI(ierr);
1058 }
1059 }
1060 else // if (mpisize > 1)
1061#endif
1062 {
1063 (void)global_first_cell;
1064 (void)global_num_cells;
1065 (void)mpi_communicator;
1066
1067 //
1068 // ---------- Fixed size data ----------
1069 //
1070 {
1071 const std::string fname_fixed = std::string(filename) + "_fixed.data";
1072
1073 std::ifstream file(fname_fixed, std::ios::binary | std::ios::in);
1074 sizes_fixed_cumulative.resize(1 + n_attached_deserialize_fixed +
1075 (variable_size_data_stored ? 1 : 0));
1076
1077 // Read header data.
1078 file.read(reinterpret_cast<char *>(sizes_fixed_cumulative.data()),
1079 sizes_fixed_cumulative.size() * sizeof(unsigned int));
1080
1081 const unsigned int bytes_per_cell = sizes_fixed_cumulative.back();
1082 dest_data_fixed.resize(static_cast<size_t>(local_num_cells) *
1083 bytes_per_cell);
1084
1085 // Read packed data.
1086 file.read(reinterpret_cast<char *>(dest_data_fixed.data()),
1087 dest_data_fixed.size() * sizeof(char));
1088
1089 file.close();
1090 }
1091
1092 //
1093 // ---------- Variable size data ----------
1094 //
1095 if (variable_size_data_stored)
1096 {
1097 const std::string fname_variable =
1098 std::string(filename) + "_variable.data";
1099
1100 std::ifstream file(fname_variable, std::ios::binary | std::ios::in);
1101
1102 // Read header data.
1103 dest_sizes_variable.resize(local_num_cells);
1104 file.read(reinterpret_cast<char *>(dest_sizes_variable.data()),
1105 dest_sizes_variable.size() * sizeof(int));
1106
1107 // Read packed data.
1108 const std::uint64_t size =
1109 std::accumulate(dest_sizes_variable.begin(),
1110 dest_sizes_variable.end(),
1111 0ULL);
1112 dest_data_variable.resize(size);
1113 file.read(reinterpret_cast<char *>(dest_data_variable.data()),
1114 dest_data_variable.size() * sizeof(char));
1115
1116 file.close();
1117 }
1118 }
1119 }
1120
1121
1122 template <int dim, int spacedim>
1124 void CellAttachedDataSerializer<dim, spacedim>::clear()
1125 {
1126 variable_size_data_stored = false;
1127
1128 // free information about data sizes
1129 sizes_fixed_cumulative.clear();
1130 sizes_fixed_cumulative.shrink_to_fit();
1131
1132 // free fixed size transfer data
1133 src_data_fixed.clear();
1134 src_data_fixed.shrink_to_fit();
1135
1136 dest_data_fixed.clear();
1137 dest_data_fixed.shrink_to_fit();
1138
1139 // free variable size transfer data
1140 src_sizes_variable.clear();
1141 src_sizes_variable.shrink_to_fit();
1142
1143 src_data_variable.clear();
1144 src_data_variable.shrink_to_fit();
1145
1146 dest_sizes_variable.clear();
1147 dest_sizes_variable.shrink_to_fit();
1148
1149 dest_data_variable.clear();
1150 dest_data_variable.shrink_to_fit();
1151 }
1152
1153} // namespace internal
1154
1155// anonymous namespace for internal helper functions
1156namespace
1157{
1158 // return whether the given cell is
1159 // patch_level_1, i.e. determine
1160 // whether either all or none of
1161 // its children are further
1162 // refined. this function can only
1163 // be called for non-active cells.
1164 template <int dim, int spacedim>
1165 bool
1166 cell_is_patch_level_1(
1168 {
1169 Assert(cell->is_active() == false, ExcInternalError());
1170
1171 unsigned int n_active_children = 0;
1172 for (unsigned int i = 0; i < cell->n_children(); ++i)
1173 if (cell->child(i)->is_active())
1174 ++n_active_children;
1175
1176 return (n_active_children == 0) ||
1177 (n_active_children == cell->n_children());
1178 }
1179
1180
1181
1182 // return, whether a given @p cell will be
1183 // coarsened, which is the case if all
1184 // children are active and have their coarsen
1185 // flag set. In case only part of the coarsen
1186 // flags are set, remove them.
1187 template <int dim, int spacedim>
1188 bool
1189 cell_will_be_coarsened(
1191 {
1192 // only cells with children should be
1193 // considered for coarsening
1194
1195 if (cell->has_children())
1196 {
1197 unsigned int children_to_coarsen = 0;
1198 const unsigned int n_children = cell->n_children();
1199
1200 for (unsigned int c = 0; c < n_children; ++c)
1201 if (cell->child(c)->is_active() && cell->child(c)->coarsen_flag_set())
1202 ++children_to_coarsen;
1203 if (children_to_coarsen == n_children)
1204 return true;
1205 else
1206 for (unsigned int c = 0; c < n_children; ++c)
1207 if (cell->child(c)->is_active())
1208 cell->child(c)->clear_coarsen_flag();
1209 }
1210 // no children, so no coarsening
1211 // possible. however, no children also
1212 // means that this cell will be in the same
1213 // state as if it had children and was
1214 // coarsened. So, what should we return -
1215 // false or true?
1216 // make sure we do not have to do this at
1217 // all...
1218 Assert(cell->has_children(), ExcInternalError());
1219 // ... and then simply return false
1220 return false;
1221 }
1222
1223
1224 // return, whether the face @p face_no of the
1225 // given @p cell will be refined after the
1226 // current refinement step, considering
1227 // refine and coarsen flags and considering
1228 // only those refinemnts that will be caused
1229 // by the neighboring cell.
1230
1231 // this function is used on both active cells
1232 // and cells with children. on cells with
1233 // children it also of interest to know 'how'
1234 // the face will be refined. thus there is an
1235 // additional third argument @p
1236 // expected_face_ref_case returning just
1237 // that. be aware, that this variable will
1238 // only contain useful information if this
1239 // function is called for an active cell.
1240 //
1241 // thus, this is an internal function, users
1242 // should call one of the two alternatives
1243 // following below.
1244 template <int dim, int spacedim>
1245 bool
1246 face_will_be_refined_by_neighbor_internal(
1248 const unsigned int face_no,
1249 RefinementCase<dim - 1> &expected_face_ref_case)
1250 {
1251 // first of all: set the default value for
1252 // expected_face_ref_case, which is no
1253 // refinement at all
1254 expected_face_ref_case = RefinementCase<dim - 1>::no_refinement;
1255
1256 const typename Triangulation<dim, spacedim>::cell_iterator neighbor =
1257 cell->neighbor(face_no);
1258
1259 // If we are at the boundary, there is no
1260 // neighbor which could refine the face
1261 if (neighbor.state() != IteratorState::valid)
1262 return false;
1263
1264 if (neighbor->has_children())
1265 {
1266 // if the neighbor is refined, it may be
1267 // coarsened. if so, then it won't refine
1268 // the face, no matter what else happens
1269 if (cell_will_be_coarsened(neighbor))
1270 return false;
1271 else
1272 // if the neighbor is refined, then it
1273 // is also refined at our current
1274 // face. It will stay so without
1275 // coarsening, so return true in that
1276 // case.
1277 {
1278 expected_face_ref_case = cell->face(face_no)->refinement_case();
1279 return true;
1280 }
1281 }
1282
1283 // now, the neighbor is not refined, but
1284 // perhaps it will be
1285 const RefinementCase<dim> nb_ref_flag = neighbor->refine_flag_set();
1286 if (nb_ref_flag != RefinementCase<dim>::no_refinement)
1287 {
1288 // now we need to know, which of the
1289 // neighbors faces points towards us
1290 const unsigned int neighbor_neighbor = cell->neighbor_face_no(face_no);
1291 // check, whether the cell will be
1292 // refined in a way that refines our
1293 // face
1294 const RefinementCase<dim - 1> face_ref_case =
1296 nb_ref_flag,
1297 neighbor_neighbor,
1298 neighbor->face_orientation(neighbor_neighbor),
1299 neighbor->face_flip(neighbor_neighbor),
1300 neighbor->face_rotation(neighbor_neighbor));
1301 if (face_ref_case != RefinementCase<dim - 1>::no_refinement)
1302 {
1304 neighbor_face = neighbor->face(neighbor_neighbor);
1305 const int this_face_index = cell->face_index(face_no);
1306
1307 // there are still two basic
1308 // possibilities here: the neighbor
1309 // might be coarser or as coarse
1310 // as we are
1311 if (neighbor_face->index() == this_face_index)
1312 // the neighbor is as coarse as
1313 // we are and will be refined at
1314 // the face of consideration, so
1315 // return true
1316 {
1317 expected_face_ref_case = face_ref_case;
1318 return true;
1319 }
1320 else
1321 {
1322 // the neighbor is coarser.
1323 // this is the most complicated
1324 // case. It might be, that the
1325 // neighbor's face will be
1326 // refined, but that we will
1327 // not see this, as we are
1328 // refined in a similar way.
1329
1330 // so, the neighbor's face must
1331 // have children. check, if our
1332 // cell's face is one of these
1333 // (it could also be a
1334 // grand_child)
1335 for (unsigned int c = 0; c < neighbor_face->n_children(); ++c)
1336 if (neighbor_face->child_index(c) == this_face_index)
1337 {
1338 // if the flagged refine
1339 // case of the face is a
1340 // subset or the same as
1341 // the current refine case,
1342 // then the face, as seen
1343 // from our cell, won't be
1344 // refined by the neighbor
1345 if ((neighbor_face->refinement_case() | face_ref_case) ==
1346 neighbor_face->refinement_case())
1347 return false;
1348 else
1349 {
1350 // if we are active, we
1351 // must be an
1352 // anisotropic child
1353 // and the coming
1354 // face_ref_case is
1355 // isotropic. Thus,
1356 // from our cell we
1357 // will see exactly the
1358 // opposite refine case
1359 // that the face has
1360 // now...
1361 Assert(
1362 face_ref_case ==
1365 expected_face_ref_case =
1366 ~neighbor_face->refinement_case();
1367 return true;
1368 }
1369 }
1370
1371 // so, obviously we were not
1372 // one of the children, but a
1373 // grandchild. This is only
1374 // possible in 3d.
1375 Assert(dim == 3, ExcInternalError());
1376 // In that case, however, no
1377 // matter what the neighbor
1378 // does, it won't be finer
1379 // after the next refinement
1380 // step.
1381 return false;
1382 }
1383 } // if face will be refined
1384 } // if neighbor is flagged for refinement
1385
1386 // no cases left, so the neighbor will not
1387 // refine the face
1388 return false;
1389 }
1390
1391 // version of above function for both active
1392 // and non-active cells
1393 template <int dim, int spacedim>
1394 bool
1395 face_will_be_refined_by_neighbor(
1397 const unsigned int face_no)
1398 {
1399 RefinementCase<dim - 1> dummy = RefinementCase<dim - 1>::no_refinement;
1400 return face_will_be_refined_by_neighbor_internal(cell, face_no, dummy);
1401 }
1402
1403 // version of above function for active cells
1404 // only. Additionally returning the refine
1405 // case (to come) of the face under
1406 // consideration
1407 template <int dim, int spacedim>
1408 bool
1409 face_will_be_refined_by_neighbor(
1411 const unsigned int face_no,
1412 RefinementCase<dim - 1> &expected_face_ref_case)
1413 {
1414 return face_will_be_refined_by_neighbor_internal(cell,
1415 face_no,
1416 expected_face_ref_case);
1417 }
1418
1419
1420
1421 template <int dim, int spacedim>
1422 bool
1423 satisfies_level1_at_vertex_rule(
1425 {
1426 std::vector<unsigned int> min_adjacent_cell_level(
1427 triangulation.n_vertices(), triangulation.n_levels());
1428 std::vector<unsigned int> max_adjacent_cell_level(
1429 triangulation.n_vertices(), 0);
1430
1431 for (const auto &cell : triangulation.active_cell_iterators())
1432 for (const unsigned int v : cell->vertex_indices())
1433 {
1434 min_adjacent_cell_level[cell->vertex_index(v)] =
1435 std::min<unsigned int>(
1436 min_adjacent_cell_level[cell->vertex_index(v)], cell->level());
1437 max_adjacent_cell_level[cell->vertex_index(v)] =
1438 std::max<unsigned int>(
1439 min_adjacent_cell_level[cell->vertex_index(v)], cell->level());
1440 }
1441
1442 for (unsigned int k = 0; k < triangulation.n_vertices(); ++k)
1443 if (triangulation.vertex_used(k))
1444 if (max_adjacent_cell_level[k] - min_adjacent_cell_level[k] > 1)
1445 return false;
1446 return true;
1447 }
1448
1449
1450
1468 template <int dim, int spacedim>
1469 unsigned int
1470 middle_vertex_index(
1472 {
1473 if (line->has_children())
1474 return line->child(0)->vertex_index(1);
1476 }
1477
1478
1479 template <int dim, int spacedim>
1480 unsigned int
1481 middle_vertex_index(
1483 {
1484 switch (static_cast<unsigned char>(quad->refinement_case()))
1485 {
1487 return middle_vertex_index<dim, spacedim>(quad->child(0)->line(1));
1488 break;
1490 return middle_vertex_index<dim, spacedim>(quad->child(0)->line(3));
1491 break;
1493 return quad->child(0)->vertex_index(3);
1494 break;
1495 default:
1496 break;
1497 }
1499 }
1500
1501
1502 template <int dim, int spacedim>
1503 unsigned int
1504 middle_vertex_index(
1506 {
1507 switch (static_cast<unsigned char>(hex->refinement_case()))
1508 {
1510 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(1));
1511 break;
1513 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(3));
1514 break;
1516 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(5));
1517 break;
1519 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(11));
1520 break;
1522 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(5));
1523 break;
1525 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(7));
1526 break;
1528 return hex->child(0)->vertex_index(7);
1529 break;
1530 default:
1531 break;
1532 }
1534 }
1535
1536
1549 template <class TRIANGULATION>
1550 inline typename TRIANGULATION::DistortedCellList
1551 collect_distorted_coarse_cells(const TRIANGULATION &)
1552 {
1553 return typename TRIANGULATION::DistortedCellList();
1554 }
1555
1556
1557
1566 template <int dim>
1568 collect_distorted_coarse_cells(const Triangulation<dim, dim> &triangulation)
1569 {
1570 typename Triangulation<dim, dim>::DistortedCellList distorted_cells;
1571 for (const auto &cell : triangulation.cell_iterators_on_level(0))
1572 {
1574 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1575 vertices[i] = cell->vertex(i);
1576
1579
1580 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1581 if (determinants[i] <=
1582 1e-9 * Utilities::fixed_power<dim>(cell->diameter()))
1583 {
1584 distorted_cells.distorted_cells.push_back(cell);
1585 break;
1586 }
1587 }
1588
1589 return distorted_cells;
1590 }
1591
1592
1599 template <int dim>
1600 bool
1601 has_distorted_children(
1602 const typename Triangulation<dim, dim>::cell_iterator &cell)
1603 {
1604 Assert(cell->has_children(), ExcInternalError());
1605
1606 for (unsigned int c = 0; c < cell->n_children(); ++c)
1607 {
1609 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1610 vertices[i] = cell->child(c)->vertex(i);
1611
1614
1615 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1616 if (determinants[i] <=
1617 1e-9 * Utilities::fixed_power<dim>(cell->child(c)->diameter()))
1618 return true;
1619 }
1620
1621 return false;
1622 }
1623
1624
1632 template <int dim, int spacedim>
1633 bool
1634 has_distorted_children(
1636 {
1637 return false;
1638 }
1639
1640
1641 template <int dim, int spacedim>
1642 void
1643 update_periodic_face_map_recursively(
1644 const typename Triangulation<dim, spacedim>::cell_iterator &cell_1,
1645 const typename Triangulation<dim, spacedim>::cell_iterator &cell_2,
1646 unsigned int n_face_1,
1647 unsigned int n_face_2,
1648 const unsigned char orientation,
1649 typename std::map<
1651 unsigned int>,
1652 std::pair<std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
1653 unsigned int>,
1654 unsigned char>> &periodic_face_map)
1655 {
1656 using FaceIterator = typename Triangulation<dim, spacedim>::face_iterator;
1657 const FaceIterator face_1 = cell_1->face(n_face_1);
1658 const FaceIterator face_2 = cell_2->face(n_face_2);
1659
1660 const unsigned char inverse_orientation =
1661 face_1->reference_cell().get_inverse_combined_orientation(orientation);
1662
1663#ifdef DEBUG
1664 const auto [face_orientation, face_rotation, face_flip] =
1666
1667 Assert((dim != 1) || (face_orientation == true && face_flip == false &&
1668 face_rotation == false),
1669 ExcMessage("The supplied orientation "
1670 "(face_orientation, face_flip, face_rotation) "
1671 "is invalid for 1d"));
1672
1673 Assert((dim != 2) || (face_flip == false && face_rotation == false),
1674 ExcMessage("The supplied orientation "
1675 "(face_orientation, face_flip, face_rotation) "
1676 "is invalid for 2d"));
1677#endif
1678
1679 Assert(face_1 != face_2, ExcMessage("face_1 and face_2 are equal!"));
1680
1681 Assert(face_1->at_boundary() && face_2->at_boundary(),
1682 ExcMessage("Periodic faces must be on the boundary"));
1683
1684 // Check if the requirement that each edge can only have at most one hanging
1685 // node, and as a consequence neighboring cells can differ by at most
1686 // one refinement level is enforced. In 1d, there are no hanging nodes and
1687 // so neighboring cells can differ by more than one refinement level.
1688 Assert(dim == 1 || std::abs(cell_1->level() - cell_2->level()) < 2,
1690
1691 // insert periodic face pair for both cells
1692 using CellFace =
1693 std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
1694 unsigned int>;
1695 const CellFace cell_face_1(cell_1, n_face_1);
1696 const CellFace cell_face_2(cell_2, n_face_2);
1697 const std::pair<CellFace, unsigned char> cell_face_orientation_2(
1698 cell_face_2, orientation);
1699
1700 const std::pair<CellFace, std::pair<CellFace, unsigned char>>
1701 periodic_faces(cell_face_1, cell_face_orientation_2);
1702
1703 // Only one periodic neighbor is allowed
1704 Assert(periodic_face_map.count(cell_face_1) == 0, ExcInternalError());
1705 periodic_face_map.insert(periodic_faces);
1706
1707 if (dim == 1)
1708 {
1709 if (cell_1->has_children())
1710 {
1711 if (cell_2->has_children())
1712 {
1713 update_periodic_face_map_recursively<dim, spacedim>(
1714 cell_1->child(n_face_1),
1715 cell_2->child(n_face_2),
1716 n_face_1,
1717 n_face_2,
1718 orientation,
1719 periodic_face_map);
1720 }
1721 else // only face_1 has children
1722 {
1723 update_periodic_face_map_recursively<dim, spacedim>(
1724 cell_1->child(n_face_1),
1725 cell_2,
1726 n_face_1,
1727 n_face_2,
1728 orientation,
1729 periodic_face_map);
1730 }
1731 }
1732 }
1733 else // dim == 2 || dim == 3
1734 {
1735 if (cell_1->has_children())
1736 {
1737 if (cell_2->has_children())
1738 {
1739 // In the case that both faces have children, we loop over all
1740 // children and apply update_periodic_face_map_recursively
1741 // recursively:
1742
1743 Assert(face_1->n_children() ==
1745 face_2->n_children() ==
1748
1749 const auto reference_cell = cell_1->reference_cell();
1750
1751 for (unsigned int i = 0;
1752 i < GeometryInfo<dim>::max_children_per_face;
1753 ++i)
1754 {
1755 // Lookup the index for the second face
1756 const unsigned int j =
1757 reference_cell.standard_to_real_face_vertex(
1758 i, n_face_1, inverse_orientation);
1759
1760 // find subcell ids that belong to the subface indices
1761 unsigned int child_cell_1 =
1763 cell_1->refinement_case(),
1764 n_face_1,
1765 i,
1766 cell_1->face_orientation(n_face_1),
1767 cell_1->face_flip(n_face_1),
1768 cell_1->face_rotation(n_face_1),
1769 face_1->refinement_case());
1770 unsigned int child_cell_2 =
1772 cell_2->refinement_case(),
1773 n_face_2,
1774 j,
1775 cell_2->face_orientation(n_face_2),
1776 cell_2->face_flip(n_face_2),
1777 cell_2->face_rotation(n_face_2),
1778 face_2->refinement_case());
1779
1780 Assert(cell_1->child(child_cell_1)->face(n_face_1) ==
1781 face_1->child(i),
1783 Assert(cell_2->child(child_cell_2)->face(n_face_2) ==
1784 face_2->child(j),
1786
1787 // precondition: subcell has the same orientation as cell
1788 // (so that the face numbers coincide) recursive call
1789 update_periodic_face_map_recursively<dim, spacedim>(
1790 cell_1->child(child_cell_1),
1791 cell_2->child(child_cell_2),
1792 n_face_1,
1793 n_face_2,
1794 orientation,
1795 periodic_face_map);
1796 }
1797 }
1798 else // only face_1 has children
1799 {
1800 for (unsigned int i = 0;
1801 i < GeometryInfo<dim>::max_children_per_face;
1802 ++i)
1803 {
1804 // find subcell ids that belong to the subface indices
1805 unsigned int child_cell_1 =
1807 cell_1->refinement_case(),
1808 n_face_1,
1809 i,
1810 cell_1->face_orientation(n_face_1),
1811 cell_1->face_flip(n_face_1),
1812 cell_1->face_rotation(n_face_1),
1813 face_1->refinement_case());
1814
1815 // recursive call
1816 update_periodic_face_map_recursively<dim, spacedim>(
1817 cell_1->child(child_cell_1),
1818 cell_2,
1819 n_face_1,
1820 n_face_2,
1821 orientation,
1822 periodic_face_map);
1823 }
1824 }
1825 }
1826 }
1827 }
1828
1829
1830} // end of anonymous namespace
1831
1832
1833namespace internal
1834{
1835 namespace TriangulationImplementation
1836 {
1837 // make sure that if in the following we
1838 // write Triangulation<dim,spacedim>
1839 // we mean the *class*
1840 // ::Triangulation, not the
1841 // enclosing namespace
1842 // internal::TriangulationImplementation
1843 using ::Triangulation;
1844
1850 int,
1851 << "Something went wrong upon construction of cell "
1852 << arg1);
1863 int,
1864 << "Cell " << arg1
1865 << " has negative measure. This typically "
1866 << "indicates some distortion in the cell, or a mistakenly "
1867 << "swapped pair of vertices in the input to "
1868 << "Triangulation::create_triangulation().");
1877 int,
1878 int,
1879 int,
1880 << "Error while creating cell " << arg1
1881 << ": the vertex index " << arg2 << " must be between 0 and "
1882 << arg3 << '.');
1889 int,
1890 int,
1892 << "The input data for creating a triangulation contained "
1893 << "information about a line with indices " << arg1 << " and " << arg2
1894 << " that is described to have boundary indicator "
1895 << static_cast<int>(arg3)
1896 << ". However, this is an internal line not located on the "
1897 << "boundary. You cannot assign a boundary indicator to it." << std::endl
1898 << std::endl
1899 << "If this happened at a place where you call "
1900 << "Triangulation::create_triangulation() yourself, you need "
1901 << "to check the SubCellData object you pass to this function."
1902 << std::endl
1903 << std::endl
1904 << "If this happened in a place where you are reading a mesh "
1905 << "from a file, then you need to investigate why such a line "
1906 << "ended up in the input file. A typical case is a geometry "
1907 << "that consisted of multiple parts and for which the mesh "
1908 << "generator program assumes that the interface between "
1909 << "two parts is a boundary when that isn't supposed to be "
1910 << "the case, or where the mesh generator simply assigns "
1911 << "'geometry indicators' to lines at the perimeter of "
1912 << "a part that are not supposed to be interpreted as "
1913 << "'boundary indicators'.");
1920 int,
1921 int,
1922 int,
1923 int,
1925 << "The input data for creating a triangulation contained "
1926 << "information about a quad with indices " << arg1 << ", " << arg2
1927 << ", " << arg3 << ", and " << arg4
1928 << " that is described to have boundary indicator "
1929 << static_cast<int>(arg5)
1930 << ". However, this is an internal quad not located on the "
1931 << "boundary. You cannot assign a boundary indicator to it." << std::endl
1932 << std::endl
1933 << "If this happened at a place where you call "
1934 << "Triangulation::create_triangulation() yourself, you need "
1935 << "to check the SubCellData object you pass to this function."
1936 << std::endl
1937 << std::endl
1938 << "If this happened in a place where you are reading a mesh "
1939 << "from a file, then you need to investigate why such a quad "
1940 << "ended up in the input file. A typical case is a geometry "
1941 << "that consisted of multiple parts and for which the mesh "
1942 << "generator program assumes that the interface between "
1943 << "two parts is a boundary when that isn't supposed to be "
1944 << "the case, or where the mesh generator simply assigns "
1945 << "'geometry indicators' to quads at the surface of "
1946 << "a part that are not supposed to be interpreted as "
1947 << "'boundary indicators'.");
1954 int,
1955 int,
1956 << "In SubCellData the line info of the line with vertex indices " << arg1
1957 << " and " << arg2 << " appears more than once. "
1958 << "This is not allowed.");
1965 int,
1966 int,
1967 std::string,
1968 << "In SubCellData the line info of the line with vertex indices " << arg1
1969 << " and " << arg2 << " appears multiple times with different (valid) "
1970 << arg3 << ". This is not allowed.");
1977 int,
1978 int,
1979 int,
1980 int,
1981 std::string,
1982 << "In SubCellData the quad info of the quad with line indices " << arg1
1983 << ", " << arg2 << ", " << arg3 << " and " << arg4
1984 << " appears multiple times with different (valid) " << arg5
1985 << ". This is not allowed.");
1986
1987 /*
1988 * Reserve space for TriaFaces. Details:
1989 *
1990 * Reserve space for line_orientations.
1991 *
1992 * @note Used only for dim=3.
1993 */
1994 void
1996 const unsigned int new_quads_in_pairs,
1997 const unsigned int new_quads_single)
1998 {
1999 AssertDimension(tria_faces.dim, 3);
2000
2001 Assert(new_quads_in_pairs % 2 == 0, ExcInternalError());
2002
2003 unsigned int next_free_single = 0;
2004 unsigned int next_free_pair = 0;
2005
2006 // count the number of objects, of unused single objects and of
2007 // unused pairs of objects
2008 unsigned int n_quads = 0;
2009 unsigned int n_unused_pairs = 0;
2010 unsigned int n_unused_singles = 0;
2011 for (unsigned int i = 0; i < tria_faces.quads.used.size(); ++i)
2012 {
2013 if (tria_faces.quads.used[i])
2014 ++n_quads;
2015 else if (i + 1 < tria_faces.quads.used.size())
2016 {
2017 if (tria_faces.quads.used[i + 1])
2018 {
2019 ++n_unused_singles;
2020 if (next_free_single == 0)
2021 next_free_single = i;
2022 }
2023 else
2024 {
2025 ++n_unused_pairs;
2026 if (next_free_pair == 0)
2027 next_free_pair = i;
2028 ++i;
2029 }
2030 }
2031 else
2032 ++n_unused_singles;
2033 }
2034 Assert(n_quads + 2 * n_unused_pairs + n_unused_singles ==
2035 tria_faces.quads.used.size(),
2037 (void)n_quads;
2038
2039 // how many single quads are needed in addition to n_unused_quads?
2040 const int additional_single_quads = new_quads_single - n_unused_singles;
2041
2042 unsigned int new_size =
2043 tria_faces.quads.used.size() + new_quads_in_pairs - 2 * n_unused_pairs;
2044 if (additional_single_quads > 0)
2045 new_size += additional_single_quads;
2046
2047 // see above...
2048 if (new_size > tria_faces.quads.n_objects())
2049 {
2050 // reserve the field of the derived class
2051 tria_faces.quads_line_orientations.resize(
2052 new_size * GeometryInfo<3>::lines_per_face, true);
2053
2054 auto &q_is_q = tria_faces.quad_is_quadrilateral;
2055 q_is_q.reserve(new_size);
2056 q_is_q.insert(q_is_q.end(), new_size - q_is_q.size(), true);
2057 }
2058 }
2059
2060
2061
2075 void
2077 const unsigned int total_cells,
2078 const unsigned int dimension,
2079 const unsigned int space_dimension)
2080 {
2081 // we need space for total_cells cells. Maybe we have more already
2082 // with those cells which are unused, so only allocate new space if
2083 // needed.
2084 //
2085 // note that all arrays should have equal sizes (checked by
2086 // @p{monitor_memory}
2087 if (total_cells > tria_level.refine_flags.size())
2088 {
2089 tria_level.refine_flags.reserve(total_cells);
2090 tria_level.refine_flags.insert(tria_level.refine_flags.end(),
2091 total_cells -
2092 tria_level.refine_flags.size(),
2093 /*RefinementCase::no_refinement=*/0);
2094
2095 tria_level.coarsen_flags.reserve(total_cells);
2096 tria_level.coarsen_flags.insert(tria_level.coarsen_flags.end(),
2097 total_cells -
2098 tria_level.coarsen_flags.size(),
2099 false);
2100
2101 tria_level.active_cell_indices.reserve(total_cells);
2102 tria_level.active_cell_indices.insert(
2103 tria_level.active_cell_indices.end(),
2104 total_cells - tria_level.active_cell_indices.size(),
2106
2107 tria_level.subdomain_ids.reserve(total_cells);
2108 tria_level.subdomain_ids.insert(tria_level.subdomain_ids.end(),
2109 total_cells -
2110 tria_level.subdomain_ids.size(),
2111 0);
2112
2113 tria_level.level_subdomain_ids.reserve(total_cells);
2114 tria_level.level_subdomain_ids.insert(
2115 tria_level.level_subdomain_ids.end(),
2116 total_cells - tria_level.level_subdomain_ids.size(),
2117 0);
2118
2119 tria_level.global_active_cell_indices.reserve(total_cells);
2120 tria_level.global_active_cell_indices.insert(
2121 tria_level.global_active_cell_indices.end(),
2122 total_cells - tria_level.global_active_cell_indices.size(),
2124
2125 tria_level.global_level_cell_indices.reserve(total_cells);
2126 tria_level.global_level_cell_indices.insert(
2127 tria_level.global_level_cell_indices.end(),
2128 total_cells - tria_level.global_level_cell_indices.size(),
2130
2131 if (dimension == space_dimension - 1)
2132 {
2133 tria_level.direction_flags.reserve(total_cells);
2134 tria_level.direction_flags.insert(
2135 tria_level.direction_flags.end(),
2136 total_cells - tria_level.direction_flags.size(),
2137 true);
2138 }
2139 else
2140 tria_level.direction_flags.clear();
2141
2142 tria_level.parents.reserve((total_cells + 1) / 2);
2143 tria_level.parents.insert(tria_level.parents.end(),
2144 (total_cells + 1) / 2 -
2145 tria_level.parents.size(),
2146 -1);
2147
2148 tria_level.neighbors.reserve(total_cells * (2 * dimension));
2149 tria_level.neighbors.insert(tria_level.neighbors.end(),
2150 total_cells * (2 * dimension) -
2151 tria_level.neighbors.size(),
2152 std::make_pair(-1, -1));
2153
2154 if (tria_level.dim == 2 || tria_level.dim == 3)
2155 {
2156 const unsigned int max_faces_per_cell = 2 * dimension;
2157 tria_level.face_orientations.resize(total_cells *
2158 max_faces_per_cell);
2159
2160 tria_level.reference_cell.reserve(total_cells);
2161 tria_level.reference_cell.insert(
2162 tria_level.reference_cell.end(),
2163 total_cells - tria_level.reference_cell.size(),
2164 tria_level.dim == 2 ? ReferenceCells::Quadrilateral :
2166 }
2167 }
2168 }
2169
2170
2171
2176 int,
2177 int,
2178 << "The containers have sizes " << arg1 << " and " << arg2
2179 << ", which is not as expected.");
2180
2186 void
2187 monitor_memory(const TriaLevel &tria_level,
2188 const unsigned int true_dimension)
2189 {
2190 (void)tria_level;
2191 (void)true_dimension;
2192 Assert(2 * true_dimension * tria_level.refine_flags.size() ==
2193 tria_level.neighbors.size(),
2194 ExcMemoryInexact(tria_level.refine_flags.size(),
2195 tria_level.neighbors.size()));
2196 Assert(2 * true_dimension * tria_level.coarsen_flags.size() ==
2197 tria_level.neighbors.size(),
2198 ExcMemoryInexact(tria_level.coarsen_flags.size(),
2199 tria_level.neighbors.size()));
2200 }
2201
2202
2203
2216 void
2218 const unsigned int new_objects_in_pairs,
2219 const unsigned int new_objects_single = 0)
2220 {
2221 if (tria_objects.structdim <= 2)
2222 {
2223 Assert(new_objects_in_pairs % 2 == 0, ExcInternalError());
2224
2225 tria_objects.next_free_single = 0;
2226 tria_objects.next_free_pair = 0;
2227 tria_objects.reverse_order_next_free_single = false;
2228
2229 // count the number of objects, of unused single objects and of
2230 // unused pairs of objects
2231 unsigned int n_objects = 0;
2232 unsigned int n_unused_pairs = 0;
2233 unsigned int n_unused_singles = 0;
2234 for (unsigned int i = 0; i < tria_objects.used.size(); ++i)
2235 {
2236 if (tria_objects.used[i])
2237 ++n_objects;
2238 else if (i + 1 < tria_objects.used.size())
2239 {
2240 if (tria_objects.used[i + 1])
2241 {
2242 ++n_unused_singles;
2243 if (tria_objects.next_free_single == 0)
2244 tria_objects.next_free_single = i;
2245 }
2246 else
2247 {
2248 ++n_unused_pairs;
2249 if (tria_objects.next_free_pair == 0)
2250 tria_objects.next_free_pair = i;
2251 ++i;
2252 }
2253 }
2254 else
2255 ++n_unused_singles;
2256 }
2257 Assert(n_objects + 2 * n_unused_pairs + n_unused_singles ==
2258 tria_objects.used.size(),
2260 (void)n_objects;
2261
2262 // how many single objects are needed in addition to
2263 // n_unused_objects?
2264 const int additional_single_objects =
2265 new_objects_single - n_unused_singles;
2266
2267 unsigned int new_size = tria_objects.used.size() +
2268 new_objects_in_pairs - 2 * n_unused_pairs;
2269 if (additional_single_objects > 0)
2270 new_size += additional_single_objects;
2271
2272 // only allocate space if necessary
2273 if (new_size > tria_objects.n_objects())
2274 {
2275 const unsigned int max_faces_per_cell =
2276 2 * tria_objects.structdim;
2277 const unsigned int max_children_per_cell =
2278 1 << tria_objects.structdim;
2279
2280 tria_objects.cells.reserve(new_size * max_faces_per_cell);
2281 tria_objects.cells.insert(tria_objects.cells.end(),
2282 (new_size - tria_objects.n_objects()) *
2283 max_faces_per_cell,
2284 -1);
2285
2286 tria_objects.used.reserve(new_size);
2287 tria_objects.used.insert(tria_objects.used.end(),
2288 new_size - tria_objects.used.size(),
2289 false);
2290
2291 tria_objects.user_flags.reserve(new_size);
2292 tria_objects.user_flags.insert(tria_objects.user_flags.end(),
2293 new_size -
2294 tria_objects.user_flags.size(),
2295 false);
2296
2297 const unsigned int factor = max_children_per_cell / 2;
2298 tria_objects.children.reserve(factor * new_size);
2299 tria_objects.children.insert(tria_objects.children.end(),
2300 factor * new_size -
2301 tria_objects.children.size(),
2302 -1);
2303
2304 if (tria_objects.structdim > 1)
2305 {
2306 tria_objects.refinement_cases.reserve(new_size);
2307 tria_objects.refinement_cases.insert(
2308 tria_objects.refinement_cases.end(),
2309 new_size - tria_objects.refinement_cases.size(),
2310 /*RefinementCase::no_refinement=*/0);
2311 }
2312
2313 // first reserve, then resize. Otherwise the std library can
2314 // decide to allocate more entries.
2315 tria_objects.boundary_or_material_id.reserve(new_size);
2316 tria_objects.boundary_or_material_id.resize(new_size);
2317
2318 tria_objects.user_data.reserve(new_size);
2319 tria_objects.user_data.resize(new_size);
2320
2321 tria_objects.manifold_id.reserve(new_size);
2322 tria_objects.manifold_id.insert(tria_objects.manifold_id.end(),
2323 new_size -
2324 tria_objects.manifold_id.size(),
2326 }
2327
2328 if (n_unused_singles == 0)
2329 {
2330 tria_objects.next_free_single = new_size - 1;
2331 tria_objects.reverse_order_next_free_single = true;
2332 }
2333 }
2334 else
2335 {
2336 const unsigned int new_hexes = new_objects_in_pairs;
2337
2338 const unsigned int new_size =
2339 new_hexes + std::count(tria_objects.used.begin(),
2340 tria_objects.used.end(),
2341 true);
2342
2343 // see above...
2344 if (new_size > tria_objects.n_objects())
2345 {
2346 const unsigned int max_faces_per_cell =
2347 2 * tria_objects.structdim;
2348
2349 tria_objects.cells.reserve(new_size * max_faces_per_cell);
2350 tria_objects.cells.insert(tria_objects.cells.end(),
2351 (new_size - tria_objects.n_objects()) *
2352 max_faces_per_cell,
2353 -1);
2354
2355 tria_objects.used.reserve(new_size);
2356 tria_objects.used.insert(tria_objects.used.end(),
2357 new_size - tria_objects.used.size(),
2358 false);
2359
2360 tria_objects.user_flags.reserve(new_size);
2361 tria_objects.user_flags.insert(tria_objects.user_flags.end(),
2362 new_size -
2363 tria_objects.user_flags.size(),
2364 false);
2365
2366 tria_objects.children.reserve(4 * new_size);
2367 tria_objects.children.insert(tria_objects.children.end(),
2368 4 * new_size -
2369 tria_objects.children.size(),
2370 -1);
2371
2372 // for the following fields, we know exactly how many elements
2373 // we need, so first reserve then resize (resize itself, at least
2374 // with some compiler libraries, appears to round up the size it
2375 // actually reserves)
2376 tria_objects.boundary_or_material_id.reserve(new_size);
2377 tria_objects.boundary_or_material_id.resize(new_size);
2378
2379 tria_objects.manifold_id.reserve(new_size);
2380 tria_objects.manifold_id.insert(tria_objects.manifold_id.end(),
2381 new_size -
2382 tria_objects.manifold_id.size(),
2384
2385 tria_objects.user_data.reserve(new_size);
2386 tria_objects.user_data.resize(new_size);
2387
2388 tria_objects.refinement_cases.reserve(new_size);
2389 tria_objects.refinement_cases.insert(
2390 tria_objects.refinement_cases.end(),
2391 new_size - tria_objects.refinement_cases.size(),
2392 /*RefinementCase::no_refinement=*/0);
2393 }
2394 tria_objects.next_free_single = tria_objects.next_free_pair = 0;
2395 }
2396 }
2397
2398
2399
2405 void
2406 monitor_memory(const TriaObjects &tria_object, const unsigned int)
2407 {
2408 Assert(tria_object.n_objects() == tria_object.used.size(),
2409 ExcMemoryInexact(tria_object.n_objects(),
2410 tria_object.used.size()));
2411 Assert(tria_object.n_objects() == tria_object.user_flags.size(),
2412 ExcMemoryInexact(tria_object.n_objects(),
2413 tria_object.user_flags.size()));
2414 Assert(tria_object.n_objects() ==
2415 tria_object.boundary_or_material_id.size(),
2416 ExcMemoryInexact(tria_object.n_objects(),
2417 tria_object.boundary_or_material_id.size()));
2418 Assert(tria_object.n_objects() == tria_object.manifold_id.size(),
2419 ExcMemoryInexact(tria_object.n_objects(),
2420 tria_object.manifold_id.size()));
2421 Assert(tria_object.n_objects() == tria_object.user_data.size(),
2422 ExcMemoryInexact(tria_object.n_objects(),
2423 tria_object.user_data.size()));
2424
2425 if (tria_object.structdim == 1)
2426 {
2427 Assert(1 * tria_object.n_objects() == tria_object.children.size(),
2428 ExcMemoryInexact(tria_object.n_objects(),
2429 tria_object.children.size()));
2430 }
2431 else if (tria_object.structdim == 2)
2432 {
2433 Assert(2 * tria_object.n_objects() == tria_object.children.size(),
2434 ExcMemoryInexact(tria_object.n_objects(),
2435 tria_object.children.size()));
2436 }
2437 else if (tria_object.structdim == 3)
2438 {
2439 Assert(4 * tria_object.n_objects() == tria_object.children.size(),
2440 ExcMemoryInexact(tria_object.n_objects(),
2441 tria_object.children.size()));
2442 }
2443 }
2444
2445
2446
2451 template <int dim, int spacedim>
2453 {
2454 public:
2458 virtual ~Policy() = default;
2459
2463 virtual void
2465
2469 virtual void
2473 std::vector<unsigned int> &line_cell_count,
2474 std::vector<unsigned int> &quad_cell_count) = 0;
2475
2481 const bool check_for_distorted_cells) = 0;
2482
2486 virtual void
2489
2493 virtual void
2496
2500 virtual bool
2502 const typename Triangulation<dim, spacedim>::cell_iterator &cell) = 0;
2503
2510 virtual std::unique_ptr<Policy<dim, spacedim>>
2511 clone() = 0;
2512 };
2513
2514
2515
2521 template <int dim, int spacedim, typename T>
2522 class PolicyWrapper : public Policy<dim, spacedim>
2523 {
2524 public:
2525 void
2527 {
2528 T::update_neighbors(tria);
2529 }
2530
2531 void
2535 std::vector<unsigned int> &line_cell_count,
2536 std::vector<unsigned int> &quad_cell_count) override
2537 {
2538 T::delete_children(tria, cell, line_cell_count, quad_cell_count);
2539 }
2540
2543 const bool check_for_distorted_cells) override
2544 {
2545 return T::execute_refinement(triangulation, check_for_distorted_cells);
2546 }
2547
2548 void
2551 {
2552 T::prevent_distorted_boundary_cells(triangulation);
2553 }
2554
2555 void
2558 {
2559 T::prepare_refinement_dim_dependent(triangulation);
2560 }
2561
2562 bool
2565 override
2566 {
2567 return T::template coarsening_allowed<dim, spacedim>(cell);
2568 }
2569
2570 std::unique_ptr<Policy<dim, spacedim>>
2571 clone() override
2572 {
2573 return std::make_unique<PolicyWrapper<dim, spacedim, T>>();
2574 }
2575 };
2576
2577
2578
2675 {
2687 template <int dim, int spacedim>
2688 static void
2691 const unsigned int level_objects,
2693 {
2694 using line_iterator =
2696
2697 number_cache.n_levels = 0;
2698 if (level_objects > 0)
2699 // find the last level on which there are used cells
2700 for (unsigned int level = 0; level < level_objects; ++level)
2701 if (triangulation.begin(level) != triangulation.end(level))
2702 number_cache.n_levels = level + 1;
2703
2704 // no cells at all?
2705 Assert(number_cache.n_levels > 0, ExcInternalError());
2706
2707 //---------------------------------
2708 // update the number of lines on the different levels in the
2709 // cache
2710 number_cache.n_lines = 0;
2711 number_cache.n_active_lines = 0;
2712
2713 // for 1d, lines have levels so take count the objects per
2714 // level and globally
2715 if (dim == 1)
2716 {
2717 number_cache.n_lines_level.resize(number_cache.n_levels);
2718 number_cache.n_active_lines_level.resize(number_cache.n_levels);
2719
2720 for (unsigned int level = 0; level < number_cache.n_levels; ++level)
2721 {
2722 // count lines on this level
2723 number_cache.n_lines_level[level] = 0;
2724 number_cache.n_active_lines_level[level] = 0;
2725
2726 line_iterator line = triangulation.begin_line(level),
2727 endc =
2728 (level == number_cache.n_levels - 1 ?
2729 line_iterator(triangulation.end_line()) :
2730 triangulation.begin_line(level + 1));
2731 for (; line != endc; ++line)
2732 {
2733 ++number_cache.n_lines_level[level];
2734 if (line->has_children() == false)
2735 ++number_cache.n_active_lines_level[level];
2736 }
2737
2738 // update total number of lines
2739 number_cache.n_lines += number_cache.n_lines_level[level];
2740 number_cache.n_active_lines +=
2741 number_cache.n_active_lines_level[level];
2742 }
2743 }
2744 else
2745 {
2746 // for dim>1, there are no levels for lines
2747 number_cache.n_lines_level.clear();
2748 number_cache.n_active_lines_level.clear();
2749
2750 line_iterator line = triangulation.begin_line(),
2751 endc = triangulation.end_line();
2752 for (; line != endc; ++line)
2753 {
2754 ++number_cache.n_lines;
2755 if (line->has_children() == false)
2756 ++number_cache.n_active_lines;
2757 }
2758 }
2759 }
2760
2775 template <int dim, int spacedim>
2776 static void
2779 const unsigned int level_objects,
2781 {
2782 // update lines and n_levels in number_cache. since we don't
2783 // access any of these numbers, we can do this in the
2784 // background
2786 static_cast<
2787 void (*)(const Triangulation<dim, spacedim> &,
2788 const unsigned int,
2790 &compute_number_cache_dim<dim, spacedim>),
2792 level_objects,
2794 number_cache));
2795
2796 using quad_iterator =
2798
2799 //---------------------------------
2800 // update the number of quads on the different levels in the
2801 // cache
2802 number_cache.n_quads = 0;
2803 number_cache.n_active_quads = 0;
2804
2805 // for 2d, quads have levels so take count the objects per
2806 // level and globally
2807 if (dim == 2)
2808 {
2809 // count the number of levels; the function we called above
2810 // on a separate Task for lines also does this and puts it into
2811 // number_cache.n_levels, but this datum may not yet be
2812 // available as we call the function on a separate task
2813 unsigned int n_levels = 0;
2814 if (level_objects > 0)
2815 // find the last level on which there are used cells
2816 for (unsigned int level = 0; level < level_objects; ++level)
2817 if (triangulation.begin(level) != triangulation.end(level))
2818 n_levels = level + 1;
2819
2820 number_cache.n_quads_level.resize(n_levels);
2821 number_cache.n_active_quads_level.resize(n_levels);
2822
2823 for (unsigned int level = 0; level < n_levels; ++level)
2824 {
2825 // count quads on this level
2826 number_cache.n_quads_level[level] = 0;
2827 number_cache.n_active_quads_level[level] = 0;
2828
2829 quad_iterator quad = triangulation.begin_quad(level),
2830 endc =
2831 (level == n_levels - 1 ?
2832 quad_iterator(triangulation.end_quad()) :
2833 triangulation.begin_quad(level + 1));
2834 for (; quad != endc; ++quad)
2835 {
2836 ++number_cache.n_quads_level[level];
2837 if (quad->has_children() == false)
2838 ++number_cache.n_active_quads_level[level];
2839 }
2840
2841 // update total number of quads
2842 number_cache.n_quads += number_cache.n_quads_level[level];
2843 number_cache.n_active_quads +=
2844 number_cache.n_active_quads_level[level];
2845 }
2846 }
2847 else
2848 {
2849 // for dim>2, there are no levels for quads
2850 number_cache.n_quads_level.clear();
2851 number_cache.n_active_quads_level.clear();
2852
2853 quad_iterator quad = triangulation.begin_quad(),
2854 endc = triangulation.end_quad();
2855 for (; quad != endc; ++quad)
2856 {
2857 ++number_cache.n_quads;
2858 if (quad->has_children() == false)
2859 ++number_cache.n_active_quads;
2860 }
2861 }
2862
2863 // wait for the background computation for lines
2864 update_lines.join();
2865 }
2866
2882 template <int dim, int spacedim>
2883 static void
2886 const unsigned int level_objects,
2888 {
2889 // update quads, lines and n_levels in number_cache. since we
2890 // don't access any of these numbers, we can do this in the
2891 // background
2892 Threads::Task<void> update_quads_and_lines = Threads::new_task(
2893 static_cast<
2894 void (*)(const Triangulation<dim, spacedim> &,
2895 const unsigned int,
2897 &compute_number_cache_dim<dim, spacedim>),
2899 level_objects,
2901 number_cache));
2902
2903 using hex_iterator =
2905
2906 //---------------------------------
2907 // update the number of hexes on the different levels in the
2908 // cache
2909 number_cache.n_hexes = 0;
2910 number_cache.n_active_hexes = 0;
2911
2912 // for 3d, hexes have levels so take count the objects per
2913 // level and globally
2914 if (dim == 3)
2915 {
2916 // count the number of levels; the function we called
2917 // above on a separate Task for quads (recursively, via
2918 // the lines function) also does this and puts it into
2919 // number_cache.n_levels, but this datum may not yet be
2920 // available as we call the function on a separate task
2921 unsigned int n_levels = 0;
2922 if (level_objects > 0)
2923 // find the last level on which there are used cells
2924 for (unsigned int level = 0; level < level_objects; ++level)
2925 if (triangulation.begin(level) != triangulation.end(level))
2926 n_levels = level + 1;
2927
2928 number_cache.n_hexes_level.resize(n_levels);
2929 number_cache.n_active_hexes_level.resize(n_levels);
2930
2931 for (unsigned int level = 0; level < n_levels; ++level)
2932 {
2933 // count hexes on this level
2934 number_cache.n_hexes_level[level] = 0;
2935 number_cache.n_active_hexes_level[level] = 0;
2936
2937 hex_iterator hex = triangulation.begin_hex(level),
2938 endc = (level == n_levels - 1 ?
2939 hex_iterator(triangulation.end_hex()) :
2940 triangulation.begin_hex(level + 1));
2941 for (; hex != endc; ++hex)
2942 {
2943 ++number_cache.n_hexes_level[level];
2944 if (hex->has_children() == false)
2945 ++number_cache.n_active_hexes_level[level];
2946 }
2947
2948 // update total number of hexes
2949 number_cache.n_hexes += number_cache.n_hexes_level[level];
2950 number_cache.n_active_hexes +=
2951 number_cache.n_active_hexes_level[level];
2952 }
2953 }
2954 else
2955 {
2956 // for dim>3, there are no levels for hexes
2957 number_cache.n_hexes_level.clear();
2958 number_cache.n_active_hexes_level.clear();
2959
2960 hex_iterator hex = triangulation.begin_hex(),
2961 endc = triangulation.end_hex();
2962 for (; hex != endc; ++hex)
2963 {
2964 ++number_cache.n_hexes;
2965 if (hex->has_children() == false)
2966 ++number_cache.n_active_hexes;
2967 }
2968 }
2969
2970 // wait for the background computation for quads
2971 update_quads_and_lines.join();
2972 }
2973
2974
2975 template <int dim, int spacedim>
2976 static void
2979 const unsigned int level_objects,
2981 {
2982 compute_number_cache_dim(triangulation, level_objects, number_cache);
2983
2984 number_cache.active_cell_index_partitioner =
2985 std::make_shared<const Utilities::MPI::Partitioner>(
2986 triangulation.n_active_cells());
2987
2988 number_cache.level_cell_index_partitioners.resize(
2989 triangulation.n_levels());
2990 for (unsigned int level = 0; level < triangulation.n_levels(); ++level)
2991 number_cache.level_cell_index_partitioners[level] =
2992 std::make_shared<const Utilities::MPI::Partitioner>(
2993 triangulation.n_cells(level));
2994 }
2995
2996
2997 template <int spacedim>
2998 static void
3001
3002
3003 template <int dim, int spacedim>
3004 static void
3006 {
3007 // each face can be neighbored on two sides
3008 // by cells. according to the face's
3009 // intrinsic normal we define the left
3010 // neighbor as the one for which the face
3011 // normal points outward, and store that
3012 // one first; the second one is then
3013 // the right neighbor for which the
3014 // face normal points inward. This
3015 // information depends on the type of cell
3016 // and local number of face for the
3017 // 'standard ordering and orientation' of
3018 // faces and then on the face_orientation
3019 // information for the real mesh. Set up a
3020 // table to have fast access to those
3021 // offsets (0 for left and 1 for
3022 // right). Some of the values are invalid
3023 // as they reference too large face
3024 // numbers, but we just leave them at a
3025 // zero value.
3026 //
3027 // Note, that in 2d for lines as faces the
3028 // normal direction given in the
3029 // GeometryInfo class is not consistent. We
3030 // thus define here that the normal for a
3031 // line points to the right if the line
3032 // points upwards.
3033 //
3034 // There is one more point to
3035 // consider, however: if we have
3036 // dim<spacedim, then we may have
3037 // cases where cells are
3038 // inverted. In effect, both
3039 // cells think they are the left
3040 // neighbor of an edge, for
3041 // example, which leads us to
3042 // forget neighborship
3043 // information (a case that shows
3044 // this is
3045 // codim_one/hanging_nodes_02). We
3046 // store whether a cell is
3047 // inverted using the
3048 // direction_flag, so if a cell
3049 // has a false direction_flag,
3050 // then we need to invert our
3051 // selection whether we are a
3052 // left or right neighbor in all
3053 // following computations.
3054 //
3055 // first index: dimension (minus 2)
3056 // second index: local face index
3057 // third index: face_orientation (false and true)
3058 static const unsigned int left_right_offset[2][6][2] = {
3059 // quadrilateral
3060 {{0, 1}, // face 0, face_orientation = false and true
3061 {1, 0}, // face 1, face_orientation = false and true
3062 {1, 0}, // face 2, face_orientation = false and true
3063 {0, 1}, // face 3, face_orientation = false and true
3064 {0, 0}, // face 4, invalid face
3065 {0, 0}}, // face 5, invalid face
3066 // hexahedron
3067 {{0, 1}, {1, 0}, {0, 1}, {1, 0}, {0, 1}, {1, 0}}};
3068
3069 // now create a vector of the two active
3070 // neighbors (left and right) for each face
3071 // and fill it by looping over all cells. For
3072 // cases with anisotropic refinement and more
3073 // then one cell neighboring at a given side
3074 // of the face we will automatically get the
3075 // active one on the highest level as we loop
3076 // over cells from lower levels first.
3078 std::vector<typename Triangulation<dim, spacedim>::cell_iterator>
3079 adjacent_cells(2 * triangulation.n_raw_faces(), dummy);
3080
3081 for (const auto &cell : triangulation.cell_iterators())
3082 for (auto f : cell->face_indices())
3083 {
3085 cell->face(f);
3086
3087 const unsigned int offset =
3088 (cell->direction_flag() ?
3089 left_right_offset[dim - 2][f][cell->face_orientation(f)] :
3090 1 -
3091 left_right_offset[dim - 2][f][cell->face_orientation(f)]);
3092
3093 adjacent_cells[2 * face->index() + offset] = cell;
3094
3095 // if this cell is not refined, but the
3096 // face is, then we'll have to set our
3097 // cell as neighbor for the child faces
3098 // as well. Fortunately the normal
3099 // orientation of children will be just
3100 // the same.
3101 if (dim == 2)
3102 {
3103 if (cell->is_active() && face->has_children())
3104 {
3105 adjacent_cells[2 * face->child(0)->index() + offset] =
3106 cell;
3107 adjacent_cells[2 * face->child(1)->index() + offset] =
3108 cell;
3109 }
3110 }
3111 else // -> dim == 3
3112 {
3113 // We need the same as in 2d
3114 // here. Furthermore, if the face is
3115 // refined with cut_x or cut_y then
3116 // those children again in the other
3117 // direction, and if this cell is
3118 // refined isotropically (along the
3119 // face) then the neighbor will
3120 // (probably) be refined as cut_x or
3121 // cut_y along the face. For those
3122 // neighboring children cells, their
3123 // neighbor will be the current,
3124 // inactive cell, as our children are
3125 // too fine to be neighbors. Catch that
3126 // case by also acting on inactive
3127 // cells with isotropic refinement
3128 // along the face. If the situation
3129 // described is not present, the data
3130 // will be overwritten later on when we
3131 // visit cells on finer levels, so no
3132 // harm will be done.
3133 if (face->has_children() &&
3134 (cell->is_active() ||
3136 cell->refinement_case(), f) ==
3137 RefinementCase<dim - 1>::isotropic_refinement))
3138 {
3139 for (unsigned int c = 0; c < face->n_children(); ++c)
3140 adjacent_cells[2 * face->child(c)->index() + offset] =
3141 cell;
3142 if (face->child(0)->has_children())
3143 {
3144 adjacent_cells[2 * face->child(0)->child(0)->index() +
3145 offset] = cell;
3146 adjacent_cells[2 * face->child(0)->child(1)->index() +
3147 offset] = cell;
3148 }
3149 if (face->child(1)->has_children())
3150 {
3151 adjacent_cells[2 * face->child(1)->child(0)->index() +
3152 offset] = cell;
3153 adjacent_cells[2 * face->child(1)->child(1)->index() +
3154 offset] = cell;
3155 }
3156 } // if cell active and face refined
3157 } // else -> dim==3
3158 } // for all faces of all cells
3159
3160 // now loop again over all cells and set the
3161 // corresponding neighbor cell. Note, that we
3162 // have to use the opposite of the
3163 // left_right_offset in this case as we want
3164 // the offset of the neighbor, not our own.
3165 for (const auto &cell : triangulation.cell_iterators())
3166 for (auto f : cell->face_indices())
3167 {
3168 const unsigned int offset =
3169 (cell->direction_flag() ?
3170 left_right_offset[dim - 2][f][cell->face_orientation(f)] :
3171 1 -
3172 left_right_offset[dim - 2][f][cell->face_orientation(f)]);
3173 cell->set_neighbor(
3174 f, adjacent_cells[2 * cell->face(f)->index() + 1 - offset]);
3175 }
3176 }
3177
3178
3182 template <int dim, int spacedim>
3183 static void
3185 const std::vector<CellData<dim>> &cells,
3186 const SubCellData &subcelldata,
3188 {
3189 AssertThrow(vertices.size() > 0, ExcMessage("No vertices given"));
3190 AssertThrow(cells.size() > 0, ExcMessage("No cells given"));
3191
3192 // Check that all cells have positive volume.
3193#ifndef _MSC_VER
3194 // TODO: The following code does not compile with MSVC. Find a way
3195 // around it
3196 if (dim == spacedim)
3197 for (unsigned int cell_no = 0; cell_no < cells.size(); ++cell_no)
3198 {
3199 // If we should check for distorted cells, then we permit them
3200 // to exist. If a cell has negative measure, then it must be
3201 // distorted (the converse is not necessarily true); hence
3202 // throw an exception if no such cells should exist.
3204 {
3205 const double cell_measure = GridTools::cell_measure<spacedim>(
3206 vertices,
3207 ArrayView<const unsigned int>(cells[cell_no].vertices));
3208 AssertThrow(cell_measure > 0, ExcGridHasInvalidCell(cell_no));
3209 }
3210 }
3211#endif
3212
3213 // clear old content
3214 tria.levels.clear();
3215 tria.levels.push_back(
3216 std::make_unique<
3218
3219 if (dim > 1)
3220 tria.faces = std::make_unique<
3222
3223 // copy vertices
3224 tria.vertices = vertices;
3225 tria.vertices_used.assign(vertices.size(), true);
3226
3227 // compute connectivity
3228 const auto connectivity = build_connectivity<unsigned int>(cells);
3229 const unsigned int n_cell = cells.size();
3230
3231 // TriaObjects: lines
3232 if (dim >= 2)
3233 {
3234 auto &lines_0 = tria.faces->lines; // data structure to be filled
3235
3236 // get connectivity between quads and lines
3237 const auto &crs = connectivity.entity_to_entities(1, 0);
3238 const unsigned int n_lines = crs.ptr.size() - 1;
3239
3240 // allocate memory
3241 reserve_space_(lines_0, n_lines);
3242
3243 // loop over lines
3244 for (unsigned int line = 0; line < n_lines; ++line)
3245 for (unsigned int i = crs.ptr[line], j = 0; i < crs.ptr[line + 1];
3246 ++i, ++j)
3247 lines_0.cells[line * GeometryInfo<1>::faces_per_cell + j] =
3248 crs.col[i]; // set vertex indices
3249 }
3250
3251 // TriaObjects: quads
3252 if (dim == 3)
3253 {
3254 auto &quads_0 = tria.faces->quads; // data structures to be filled
3255 auto &faces = *tria.faces;
3256
3257 // get connectivity between quads and lines
3258 const auto &crs = connectivity.entity_to_entities(2, 1);
3259 const unsigned int n_quads = crs.ptr.size() - 1;
3260
3261 // allocate memory
3262 reserve_space_(quads_0, n_quads);
3263 reserve_space_(faces, 2 /*structdim*/, n_quads);
3264
3265 // loop over all quads -> entity type, line indices/orientations
3266 for (unsigned int q = 0, k = 0; q < n_quads; ++q)
3267 {
3268 // set entity type of quads
3269 faces.set_quad_type(q, connectivity.entity_types(2)[q]);
3270
3271 // loop over all its lines
3272 for (unsigned int i = crs.ptr[q], j = 0; i < crs.ptr[q + 1];
3273 ++i, ++j, ++k)
3274 {
3275 // set line index
3276 quads_0.cells[q * GeometryInfo<3>::lines_per_face + j] =
3277 crs.col[i];
3278
3279 // set line orientations
3280 const unsigned char combined_orientation =
3281 connectivity.entity_orientations(1)
3282 .get_combined_orientation(k);
3283 // it doesn't make sense to set any flags except
3284 // orientation for a line
3285 Assert(
3286 combined_orientation ==
3288 combined_orientation ==
3291 faces.quads_line_orientations
3293 combined_orientation ==
3295 }
3296 }
3297 }
3298
3299 // TriaObjects/TriaLevel: cell
3300 {
3301 auto &cells_0 = tria.levels[0]->cells; // data structure to be filled
3302 auto &level = *tria.levels[0];
3303
3304 // get connectivity between cells/faces and cells/cells
3305 const auto &crs = connectivity.entity_to_entities(dim, dim - 1);
3306 const auto &nei = connectivity.entity_to_entities(dim, dim);
3307
3308 // in 2d optional: since in in pure QUAD meshes same line
3309 // orientations can be guaranteed
3310 bool orientation_needed = false;
3311 if (dim == 3)
3312 orientation_needed = true;
3313 else if (dim == 2)
3314 {
3315 const auto &orientations = connectivity.entity_orientations(1);
3316 for (unsigned int i = 0; i < orientations.n_objects(); ++i)
3317 if (orientations.get_combined_orientation(i) !=
3319 {
3320 orientation_needed = true;
3321 break;
3322 }
3323 }
3324
3325 // allocate memory
3326 reserve_space_(cells_0, n_cell);
3327 reserve_space_(level, spacedim, n_cell, orientation_needed);
3328
3329 // loop over all cells
3330 for (unsigned int cell = 0; cell < n_cell; ++cell)
3331 {
3332 // set material ids
3333 cells_0.boundary_or_material_id[cell].material_id =
3334 cells[cell].material_id;
3335
3336 // set manifold ids
3337 cells_0.manifold_id[cell] = cells[cell].manifold_id;
3338
3339 // set entity types
3340 level.reference_cell[cell] = connectivity.entity_types(dim)[cell];
3341
3342 // loop over faces
3343 for (unsigned int i = crs.ptr[cell], j = 0; i < crs.ptr[cell + 1];
3344 ++i, ++j)
3345 {
3346 // set neighbor if not at boundary
3347 if (nei.col[i] != static_cast<unsigned int>(-1))
3348 level.neighbors[cell * GeometryInfo<dim>::faces_per_cell +
3349 j] = {0, nei.col[i]};
3350
3351 // set face indices
3352 cells_0.cells[cell * GeometryInfo<dim>::faces_per_cell + j] =
3353 crs.col[i];
3354
3355 // set face orientation if needed
3356 if (orientation_needed)
3357 {
3358 level.face_orientations.set_combined_orientation(
3360 connectivity.entity_orientations(dim - 1)
3361 .get_combined_orientation(i));
3362 }
3363 }
3364 }
3365 }
3366
3367 // TriaFaces: boundary id of boundary faces
3368 if (dim > 1)
3369 {
3370 auto &bids_face = dim == 3 ?
3371 tria.faces->quads.boundary_or_material_id :
3372 tria.faces->lines.boundary_or_material_id;
3373
3374 // count number of cells a face is belonging to
3375 std::vector<unsigned int> count(bids_face.size(), 0);
3376
3377 // get connectivity between cells/faces
3378 const auto &crs = connectivity.entity_to_entities(dim, dim - 1);
3379
3380 // count how many cells are adjacent to the same face
3381 for (unsigned int cell = 0; cell < cells.size(); ++cell)
3382 for (unsigned int i = crs.ptr[cell]; i < crs.ptr[cell + 1]; ++i)
3383 count[crs.col[i]]++;
3384
3385 // loop over all faces
3386 for (unsigned int face = 0; face < count.size(); ++face)
3387 {
3388 if (count[face] != 1) // inner face
3389 continue;
3390
3391 // boundary faces ...
3392 bids_face[face].boundary_id = 0;
3393
3394 if (dim != 3)
3395 continue;
3396
3397 // ... and the lines of quads in 3d
3398 const auto &crs = connectivity.entity_to_entities(2, 1);
3399 for (unsigned int i = crs.ptr[face]; i < crs.ptr[face + 1]; ++i)
3400 tria.faces->lines.boundary_or_material_id[crs.col[i]]
3401 .boundary_id = 0;
3402 }
3403 }
3404 else // 1d
3405 {
3406 static const unsigned int t_tba = static_cast<unsigned int>(-1);
3407 static const unsigned int t_inner = static_cast<unsigned int>(-2);
3408
3409 std::vector<unsigned int> type(vertices.size(), t_tba);
3410
3411 const auto &crs = connectivity.entity_to_entities(1, 0);
3412
3413 for (unsigned int cell = 0; cell < cells.size(); ++cell)
3414 for (unsigned int i = crs.ptr[cell], j = 0; i < crs.ptr[cell + 1];
3415 ++i, ++j)
3416 if (type[crs.col[i]] != t_inner)
3417 type[crs.col[i]] = type[crs.col[i]] == t_tba ? j : t_inner;
3418
3419 for (unsigned int face = 0; face < type.size(); ++face)
3420 {
3421 // note: we also treat manifolds here!?
3422 (*tria.vertex_to_manifold_id_map_1d)[face] =
3424 if (type[face] != t_inner && type[face] != t_tba)
3425 (*tria.vertex_to_boundary_id_map_1d)[face] = type[face];
3426 }
3427 }
3428
3429 // SubCellData: line
3430 if (dim >= 2)
3431 process_subcelldata(connectivity.entity_to_entities(1, 0),
3432 tria.faces->lines,
3433 subcelldata.boundary_lines,
3434 vertices);
3435
3436 // SubCellData: quad
3437 if (dim == 3)
3438 process_subcelldata(connectivity.entity_to_entities(2, 0),
3439 tria.faces->quads,
3440 subcelldata.boundary_quads,
3441 vertices);
3442 }
3443
3444
3445 template <int structdim, int spacedim, typename T>
3446 static void
3448 const CRS<T> &crs,
3449 TriaObjects &obj,
3450 const std::vector<CellData<structdim>> &boundary_objects_in,
3451 const std::vector<Point<spacedim>> &vertex_locations)
3452 {
3453 AssertDimension(obj.structdim, structdim);
3454
3455 if (boundary_objects_in.empty())
3456 return; // empty subcelldata -> nothing to do
3457
3458 // pre-sort subcelldata
3459 auto boundary_objects = boundary_objects_in;
3460
3461 // ... sort vertices
3462 for (auto &boundary_object : boundary_objects)
3463 std::sort(boundary_object.vertices.begin(),
3464 boundary_object.vertices.end());
3465
3466 // ... sort cells
3467 std::sort(boundary_objects.begin(),
3468 boundary_objects.end(),
3469 [](const auto &a, const auto &b) {
3470 return a.vertices < b.vertices;
3471 });
3472
3473 unsigned int counter = 0;
3474
3475 std::vector<unsigned int> key;
3477
3478 for (unsigned int o = 0; o < obj.n_objects(); ++o)
3479 {
3480 auto &boundary_id = obj.boundary_or_material_id[o].boundary_id;
3481 auto &manifold_id = obj.manifold_id[o];
3482
3483 // assert that object has not been visited yet and its value
3484 // has not been modified yet
3485 AssertThrow(boundary_id == 0 ||
3490
3491 // create key
3492 key.assign(crs.col.data() + crs.ptr[o],
3493 crs.col.data() + crs.ptr[o + 1]);
3494 std::sort(key.begin(), key.end());
3495
3496 // is subcelldata provided? -> binary search
3497 const auto subcell_object =
3498 std::lower_bound(boundary_objects.begin(),
3499 boundary_objects.end(),
3500 key,
3501 [&](const auto &cell, const auto &key) {
3502 return cell.vertices < key;
3503 });
3504
3505 // no subcelldata provided for this object
3506 if (subcell_object == boundary_objects.end() ||
3507 subcell_object->vertices != key)
3508 continue;
3509
3510 ++counter;
3511
3512 // set manifold id
3513 manifold_id = subcell_object->manifold_id;
3514
3515 // set boundary id
3516 if (subcell_object->boundary_id !=
3518 {
3519 (void)vertex_locations;
3522 ExcMessage(
3523 "The input arguments for creating a triangulation "
3524 "specified a boundary id for an internal face. This "
3525 "is not allowed."
3526 "\n\n"
3527 "The object in question has vertex indices " +
3528 [subcell_object]() {
3529 std::string s;
3530 for (const auto v : subcell_object->vertices)
3531 s += std::to_string(v) + ',';
3532 return s;
3533 }() +
3534 " which are located at positions " +
3535 [vertex_locations, subcell_object]() {
3536 std::ostringstream s;
3537 for (const auto v : subcell_object->vertices)
3538 s << '(' << vertex_locations[v] << ')';
3539 return s.str();
3540 }() +
3541 "."));
3542 boundary_id = subcell_object->boundary_id;
3543 }
3544 }
3545
3546 // make sure that all subcelldata entries have been processed
3547 // TODO: this is not guaranteed, why?
3548 // AssertDimension(counter, boundary_objects_in.size());
3549 (void)counter;
3550 }
3551
3552
3553
3554 static void
3556 const unsigned structdim,
3557 const unsigned int size)
3558 {
3559 const unsigned int dim = faces.dim;
3560
3561 const unsigned int max_lines_per_face = 2 * structdim;
3562
3563 if (dim == 3 && structdim == 2)
3564 {
3565 // quad entity types
3566 faces.quad_is_quadrilateral.assign(size, true);
3567
3568 // quad line orientations
3569 faces.quads_line_orientations.assign(size * max_lines_per_face,
3570 true);
3571 }
3572 }
3573
3574
3575
3576 static void
3578 const unsigned int spacedim,
3579 const unsigned int size,
3580 const bool orientation_needed)
3581 {
3582 const unsigned int dim = level.dim;
3583
3584 const unsigned int max_faces_per_cell = 2 * dim;
3585
3586 level.active_cell_indices.assign(size, -1);
3587 level.subdomain_ids.assign(size, 0);
3588 level.level_subdomain_ids.assign(size, 0);
3589
3590 level.refine_flags.assign(size, 0u);
3591 level.coarsen_flags.assign(size, false);
3592
3593 level.parents.assign((size + 1) / 2, -1);
3594
3595 if (dim == spacedim - 1)
3596 level.direction_flags.assign(size, true);
3597
3598 level.neighbors.assign(size * max_faces_per_cell, {-1, -1});
3599
3600 level.reference_cell.assign(size, ReferenceCells::Invalid);
3601
3602 if (orientation_needed)
3603 level.face_orientations.reinit(size * max_faces_per_cell);
3604
3605
3606 level.global_active_cell_indices.assign(size,
3608 level.global_level_cell_indices.assign(size,
3610 }
3611
3612
3613
3614 static void
3615 reserve_space_(TriaObjects &obj, const unsigned int size)
3616 {
3617 const unsigned int structdim = obj.structdim;
3618
3619 const unsigned int max_children_per_cell = 1 << structdim;
3620 const unsigned int max_faces_per_cell = 2 * structdim;
3621
3622 obj.used.assign(size, true);
3623 obj.boundary_or_material_id.assign(
3624 size,
3626 BoundaryOrMaterialId());
3627 obj.manifold_id.assign(size, -1);
3628 obj.user_flags.assign(size, false);
3629 obj.user_data.resize(size);
3630
3631 if (structdim > 1) // TODO: why?
3632 obj.refinement_cases.assign(size, 0);
3633
3634 obj.children.assign(max_children_per_cell / 2 * size, -1);
3635
3636 obj.cells.assign(max_faces_per_cell * size, -1);
3637
3638 if (structdim <= 2)
3639 {
3640 obj.next_free_single = size - 1;
3641 obj.next_free_pair = 0;
3643 }
3644 else
3645 {
3646 obj.next_free_single = obj.next_free_pair = 0;
3647 }
3648 }
3649
3650
3666 template <int spacedim>
3667 static void
3670 std::vector<unsigned int> &,
3671 std::vector<unsigned int> &)
3672 {
3673 const unsigned int dim = 1;
3674
3675 // first we need to reset the
3676 // neighbor pointers of the
3677 // neighbors of this cell's
3678 // children to this cell. This is
3679 // different for one dimension,
3680 // since there neighbors can have a
3681 // refinement level differing from
3682 // that of this cell's children by
3683 // more than one level.
3684
3685 Assert(!cell->child(0)->has_children() &&
3686 !cell->child(1)->has_children(),
3688
3689 // first do it for the cells to the
3690 // left
3691 if (cell->neighbor(0).state() == IteratorState::valid)
3692 if (cell->neighbor(0)->has_children())
3693 {
3695 cell->neighbor(0);
3696 Assert(neighbor->level() == cell->level(), ExcInternalError());
3697
3698 // right child
3699 neighbor = neighbor->child(1);
3700 while (true)
3701 {
3702 Assert(neighbor->neighbor(1) == cell->child(0),
3704 neighbor->set_neighbor(1, cell);
3705
3706 // move on to further
3707 // children on the
3708 // boundary between this
3709 // cell and its neighbor
3710 if (neighbor->has_children())
3711 neighbor = neighbor->child(1);
3712 else
3713 break;
3714 }
3715 }
3716
3717 // now do it for the cells to the
3718 // left
3719 if (cell->neighbor(1).state() == IteratorState::valid)
3720 if (cell->neighbor(1)->has_children())
3721 {
3723 cell->neighbor(1);
3724 Assert(neighbor->level() == cell->level(), ExcInternalError());
3725
3726 // left child
3727 neighbor = neighbor->child(0);
3728 while (true)
3729 {
3730 Assert(neighbor->neighbor(0) == cell->child(1),
3732 neighbor->set_neighbor(0, cell);
3733
3734 // move on to further
3735 // children on the
3736 // boundary between this
3737 // cell and its neighbor
3738 if (neighbor->has_children())
3739 neighbor = neighbor->child(0);
3740 else
3741 break;
3742 }
3743 }
3744
3745
3746 // delete the vertex which will not
3747 // be needed anymore. This vertex
3748 // is the second of the first child
3749 triangulation.vertices_used[cell->child(0)->vertex_index(1)] = false;
3750
3751 // invalidate children. clear user
3752 // pointers, to avoid that they may
3753 // appear at unwanted places later
3754 // on...
3755 for (unsigned int child = 0; child < cell->n_children(); ++child)
3756 {
3757 cell->child(child)->clear_user_data();
3758 cell->child(child)->clear_user_flag();
3759 cell->child(child)->clear_used_flag();
3760 }
3761
3762
3763 // delete pointer to children
3764 cell->clear_children();
3765 cell->clear_user_flag();
3766 }
3767
3768
3769
3770 template <int spacedim>
3771 static void
3774 std::vector<unsigned int> &line_cell_count,
3775 std::vector<unsigned int> &)
3776 {
3777 const unsigned int dim = 2;
3778 const RefinementCase<dim> ref_case = cell->refinement_case();
3779
3780 Assert(line_cell_count.size() == triangulation.n_raw_lines(),
3782
3783 // vectors to hold all lines which
3784 // may be deleted
3785 std::vector<typename Triangulation<dim, spacedim>::line_iterator>
3786 lines_to_delete(0);
3787
3788 lines_to_delete.reserve(4 * 2 + 4);
3789
3790 // now we decrease the counters for
3791 // lines contained in the child
3792 // cells
3793 for (unsigned int c = 0; c < cell->n_children(); ++c)
3794 {
3796 cell->child(c);
3797 for (unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++l)
3798 --line_cell_count[child->line_index(l)];
3799 }
3800
3801
3802 // delete the vertex which will not
3803 // be needed anymore. This vertex
3804 // is the second of the second line
3805 // of the first child, if the cell
3806 // is refined with cut_xy, else there
3807 // is no inner vertex.
3808 // additionally delete unneeded inner
3809 // lines
3810 if (ref_case == RefinementCase<dim>::cut_xy)
3811 {
3813 .vertices_used[cell->child(0)->line(1)->vertex_index(1)] = false;
3814
3815 lines_to_delete.push_back(cell->child(0)->line(1));
3816 lines_to_delete.push_back(cell->child(0)->line(3));
3817 lines_to_delete.push_back(cell->child(3)->line(0));
3818 lines_to_delete.push_back(cell->child(3)->line(2));
3819 }
3820 else
3821 {
3822 unsigned int inner_face_no =
3823 ref_case == RefinementCase<dim>::cut_x ? 1 : 3;
3824
3825 // the inner line will not be
3826 // used any more
3827 lines_to_delete.push_back(cell->child(0)->line(inner_face_no));
3828 }
3829
3830 // invalidate children
3831 for (unsigned int child = 0; child < cell->n_children(); ++child)
3832 {
3833 cell->child(child)->clear_user_data();
3834 cell->child(child)->clear_user_flag();
3835 cell->child(child)->clear_used_flag();
3836 }
3837
3838
3839 // delete pointer to children
3840 cell->clear_children();
3841 cell->clear_refinement_case();
3842 cell->clear_user_flag();
3843
3844 // look at the refinement of outer
3845 // lines. if nobody needs those
3846 // anymore we can add them to the
3847 // list of lines to be deleted.
3848 for (unsigned int line_no = 0;
3849 line_no < GeometryInfo<dim>::lines_per_cell;
3850 ++line_no)
3851 {
3853 cell->line(line_no);
3854
3855 if (line->has_children())
3856 {
3857 // if one of the cell counters is
3858 // zero, the other has to be as well
3859
3860 Assert((line_cell_count[line->child_index(0)] == 0 &&
3861 line_cell_count[line->child_index(1)] == 0) ||
3862 (line_cell_count[line->child_index(0)] > 0 &&
3863 line_cell_count[line->child_index(1)] > 0),
3865
3866 if (line_cell_count[line->child_index(0)] == 0)
3867 {
3868 for (unsigned int c = 0; c < 2; ++c)
3869 Assert(!line->child(c)->has_children(),
3871
3872 // we may delete the line's
3873 // children and the middle vertex
3874 // as no cell references them
3875 // anymore
3877 .vertices_used[line->child(0)->vertex_index(1)] = false;
3878
3879 lines_to_delete.push_back(line->child(0));
3880 lines_to_delete.push_back(line->child(1));
3881
3882 line->clear_children();
3883 }
3884 }
3885 }
3886
3887 // finally, delete unneeded lines
3888
3889 // clear user pointers, to avoid that
3890 // they may appear at unwanted places
3891 // later on...
3892 // same for user flags, then finally
3893 // delete the lines
3894 typename std::vector<
3896 line = lines_to_delete.begin(),
3897 endline = lines_to_delete.end();
3898 for (; line != endline; ++line)
3899 {
3900 (*line)->clear_user_data();
3901 (*line)->clear_user_flag();
3902 (*line)->clear_used_flag();
3903 }
3904 }
3905
3906
3907
3908 template <int spacedim>
3909 static void
3912 std::vector<unsigned int> &line_cell_count,
3913 std::vector<unsigned int> &quad_cell_count)
3914 {
3915 const unsigned int dim = 3;
3916
3917 Assert(line_cell_count.size() == triangulation.n_raw_lines(),
3919 Assert(quad_cell_count.size() == triangulation.n_raw_quads(),
3921
3922 // first of all, we store the RefineCase of
3923 // this cell
3924 const RefinementCase<dim> ref_case = cell->refinement_case();
3925 // vectors to hold all lines and quads which
3926 // may be deleted
3927 std::vector<typename Triangulation<dim, spacedim>::line_iterator>
3928 lines_to_delete(0);
3929 std::vector<typename Triangulation<dim, spacedim>::quad_iterator>
3930 quads_to_delete(0);
3931
3932 lines_to_delete.reserve(12 * 2 + 6 * 4 + 6);
3933 quads_to_delete.reserve(6 * 4 + 12);
3934
3935 // now we decrease the counters for lines and
3936 // quads contained in the child cells
3937 for (unsigned int c = 0; c < cell->n_children(); ++c)
3938 {
3940 cell->child(c);
3941 const auto line_indices = TriaAccessorImplementation::
3942 Implementation::get_line_indices_of_cell(*child);
3943 for (const unsigned int l : cell->line_indices())
3944 --line_cell_count[line_indices[l]];
3945 for (auto f : GeometryInfo<dim>::face_indices())
3946 --quad_cell_count[child->quad_index(f)];
3947 }
3948
3949 //-------------------------------------
3950 // delete interior quads and lines and the
3951 // interior vertex, depending on the
3952 // refinement case of the cell
3953 //
3954 // for append quads and lines: only append
3955 // them to the list of objects to be deleted
3956
3957 switch (ref_case)
3958 {
3960 quads_to_delete.push_back(cell->child(0)->face(1));
3961 break;
3963 quads_to_delete.push_back(cell->child(0)->face(3));
3964 break;
3966 quads_to_delete.push_back(cell->child(0)->face(5));
3967 break;
3969 quads_to_delete.push_back(cell->child(0)->face(1));
3970 quads_to_delete.push_back(cell->child(0)->face(3));
3971 quads_to_delete.push_back(cell->child(3)->face(0));
3972 quads_to_delete.push_back(cell->child(3)->face(2));
3973
3974 lines_to_delete.push_back(cell->child(0)->line(11));
3975 break;
3977 quads_to_delete.push_back(cell->child(0)->face(1));
3978 quads_to_delete.push_back(cell->child(0)->face(5));
3979 quads_to_delete.push_back(cell->child(3)->face(0));
3980 quads_to_delete.push_back(cell->child(3)->face(4));
3981
3982 lines_to_delete.push_back(cell->child(0)->line(5));
3983 break;
3985 quads_to_delete.push_back(cell->child(0)->face(3));
3986 quads_to_delete.push_back(cell->child(0)->face(5));
3987 quads_to_delete.push_back(cell->child(3)->face(2));
3988 quads_to_delete.push_back(cell->child(3)->face(4));
3989
3990 lines_to_delete.push_back(cell->child(0)->line(7));
3991 break;
3993 quads_to_delete.push_back(cell->child(0)->face(1));
3994 quads_to_delete.push_back(cell->child(2)->face(1));
3995 quads_to_delete.push_back(cell->child(4)->face(1));
3996 quads_to_delete.push_back(cell->child(6)->face(1));
3997
3998 quads_to_delete.push_back(cell->child(0)->face(3));
3999 quads_to_delete.push_back(cell->child(1)->face(3));
4000 quads_to_delete.push_back(cell->child(4)->face(3));
4001 quads_to_delete.push_back(cell->child(5)->face(3));
4002
4003 quads_to_delete.push_back(cell->child(0)->face(5));
4004 quads_to_delete.push_back(cell->child(1)->face(5));
4005 quads_to_delete.push_back(cell->child(2)->face(5));
4006 quads_to_delete.push_back(cell->child(3)->face(5));
4007
4008 lines_to_delete.push_back(cell->child(0)->line(5));
4009 lines_to_delete.push_back(cell->child(0)->line(7));
4010 lines_to_delete.push_back(cell->child(0)->line(11));
4011 lines_to_delete.push_back(cell->child(7)->line(0));
4012 lines_to_delete.push_back(cell->child(7)->line(2));
4013 lines_to_delete.push_back(cell->child(7)->line(8));
4014 // delete the vertex which will not
4015 // be needed anymore. This vertex
4016 // is the vertex at the heart of
4017 // this cell, which is the sixth of
4018 // the first child
4019 triangulation.vertices_used[cell->child(0)->vertex_index(7)] =
4020 false;
4021 break;
4022 default:
4023 // only remaining case is
4024 // no_refinement, thus an error
4026 break;
4027 }
4028
4029
4030 // invalidate children
4031 for (unsigned int child = 0; child < cell->n_children(); ++child)
4032 {
4033 cell->child(child)->clear_user_data();
4034 cell->child(child)->clear_user_flag();
4035
4036 for (auto f : GeometryInfo<dim>::face_indices())
4037 // set flags denoting deviations from standard orientation of
4038 // faces back to initialization values
4039 cell->child(child)->set_combined_face_orientation(
4041
4042 cell->child(child)->clear_used_flag();
4043 }
4044
4045
4046 // delete pointer to children
4047 cell->clear_children();
4048 cell->clear_refinement_case();
4049 cell->clear_user_flag();
4050
4051 // so far we only looked at inner quads,
4052 // lines and vertices. Now we have to
4053 // consider outer ones as well. here, we have
4054 // to check, whether there are other cells
4055 // still needing these objects. otherwise we
4056 // can delete them. first for quads (and
4057 // their inner lines).
4058
4059 for (const unsigned int quad_no : GeometryInfo<dim>::face_indices())
4060 {
4062 cell->face(quad_no);
4063
4064 Assert(
4065 (GeometryInfo<dim>::face_refinement_case(ref_case, quad_no) &&
4066 quad->has_children()) ||
4067 GeometryInfo<dim>::face_refinement_case(ref_case, quad_no) ==
4070
4071 switch (quad->refinement_case())
4072 {
4073 case RefinementCase<dim - 1>::no_refinement:
4074 // nothing to do as the quad
4075 // is not refined
4076 break;
4077 case RefinementCase<dim - 1>::cut_x:
4078 case RefinementCase<dim - 1>::cut_y:
4079 {
4080 // if one of the cell counters is
4081 // zero, the other has to be as
4082 // well
4083 Assert((quad_cell_count[quad->child_index(0)] == 0 &&
4084 quad_cell_count[quad->child_index(1)] == 0) ||
4085 (quad_cell_count[quad->child_index(0)] > 0 &&
4086 quad_cell_count[quad->child_index(1)] > 0),
4088 // it might be, that the quad is
4089 // refined twice anisotropically,
4090 // first check, whether we may
4091 // delete possible grand_children
4092 unsigned int deleted_grandchildren = 0;
4093 unsigned int number_of_child_refinements = 0;
4094
4095 for (unsigned int c = 0; c < 2; ++c)
4096 if (quad->child(c)->has_children())
4097 {
4098 ++number_of_child_refinements;
4099 // if one of the cell counters is
4100 // zero, the other has to be as
4101 // well
4102 Assert(
4103 (quad_cell_count[quad->child(c)->child_index(0)] ==
4104 0 &&
4105 quad_cell_count[quad->child(c)->child_index(1)] ==
4106 0) ||
4107 (quad_cell_count[quad->child(c)->child_index(0)] >
4108 0 &&
4109 quad_cell_count[quad->child(c)->child_index(1)] >
4110 0),
4112 if (quad_cell_count[quad->child(c)->child_index(0)] ==
4113 0)
4114 {
4115 // Assert, that the two
4116 // anisotropic
4117 // refinements add up to
4118 // isotropic refinement
4119 Assert(quad->refinement_case() +
4120 quad->child(c)->refinement_case() ==
4123 // we may delete the
4124 // quad's children and
4125 // the inner line as no
4126 // cell references them
4127 // anymore
4128 quads_to_delete.push_back(
4129 quad->child(c)->child(0));
4130 quads_to_delete.push_back(
4131 quad->child(c)->child(1));
4132 if (quad->child(c)->refinement_case() ==
4134 lines_to_delete.push_back(
4135 quad->child(c)->child(0)->line(1));
4136 else
4137 lines_to_delete.push_back(
4138 quad->child(c)->child(0)->line(3));
4139 quad->child(c)->clear_children();
4140 quad->child(c)->clear_refinement_case();
4141 ++deleted_grandchildren;
4142 }
4143 }
4144 // if no grandchildren are left, we
4145 // may as well delete the
4146 // refinement of the inner line
4147 // between our children and the
4148 // corresponding vertex
4149 if (number_of_child_refinements > 0 &&
4150 deleted_grandchildren == number_of_child_refinements)
4151 {
4153 middle_line;
4154 if (quad->refinement_case() == RefinementCase<2>::cut_x)
4155 middle_line = quad->child(0)->line(1);
4156 else
4157 middle_line = quad->child(0)->line(3);
4158
4159 lines_to_delete.push_back(middle_line->child(0));
4160 lines_to_delete.push_back(middle_line->child(1));
4162 .vertices_used[middle_vertex_index<dim, spacedim>(
4163 middle_line)] = false;
4164 middle_line->clear_children();
4165 }
4166
4167 // now consider the direct children
4168 // of the given quad
4169 if (quad_cell_count[quad->child_index(0)] == 0)
4170 {
4171 // we may delete the quad's
4172 // children and the inner line
4173 // as no cell references them
4174 // anymore
4175 quads_to_delete.push_back(quad->child(0));
4176 quads_to_delete.push_back(quad->child(1));
4177 if (quad->refinement_case() == RefinementCase<2>::cut_x)
4178 lines_to_delete.push_back(quad->child(0)->line(1));
4179 else
4180 lines_to_delete.push_back(quad->child(0)->line(3));
4181
4182 // if the counters just dropped
4183 // to zero, otherwise the
4184 // children would have been
4185 // deleted earlier, then this
4186 // cell's children must have
4187 // contained the anisotropic
4188 // quad children. thus, if
4189 // those have again anisotropic
4190 // children, which are in
4191 // effect isotropic children of
4192 // the original quad, those are
4193 // still needed by a
4194 // neighboring cell and we
4195 // cannot delete them. instead,
4196 // we have to reset this quad's
4197 // refine case to isotropic and
4198 // set the children
4199 // accordingly.
4200 if (quad->child(0)->has_children())
4201 if (quad->refinement_case() ==
4203 {
4204 // now evereything is
4205 // quite complicated. we
4206 // have the children
4207 // numbered according to
4208 //
4209 // *---*---*
4210 // |n+1|m+1|
4211 // *---*---*
4212 // | n | m |
4213 // *---*---*
4214 //
4215 // from the original
4216 // anisotropic
4217 // refinement. we have to
4218 // reorder them as
4219 //
4220 // *---*---*
4221 // | m |m+1|
4222 // *---*---*
4223 // | n |n+1|
4224 // *---*---*
4225 //
4226 // for isotropic refinement.
4227 //
4228 // this is a bit ugly, of
4229 // course: loop over all
4230 // cells on all levels
4231 // and look for faces n+1
4232 // (switch_1) and m
4233 // (switch_2).
4234 const typename Triangulation<dim, spacedim>::
4235 quad_iterator switch_1 =
4236 quad->child(0)->child(1),
4237 switch_2 =
4238 quad->child(1)->child(0);
4239
4240 Assert(!switch_1->has_children(),
4242 Assert(!switch_2->has_children(),
4244
4245 const int switch_1_index = switch_1->index();
4246 const int switch_2_index = switch_2->index();
4247 for (unsigned int l = 0;
4248 l < triangulation.levels.size();
4249 ++l)
4250 for (unsigned int h = 0;
4251 h <
4252 triangulation.levels[l]->cells.n_objects();
4253 ++h)
4254 for (const unsigned int q :
4256 {
4257 const int index =
4259 ->cells.get_bounding_object_indices(
4260 h)[q];
4261 if (index == switch_1_index)
4262 triangulation.levels[l]
4263 ->cells.get_bounding_object_indices(
4264 h)[q] = switch_2_index;
4265 else if (index == switch_2_index)
4266 triangulation.levels[l]
4267 ->cells.get_bounding_object_indices(
4268 h)[q] = switch_1_index;
4269 }
4270 // now we have to copy
4271 // all information of the
4272 // two quads
4273 const int switch_1_lines[4] = {
4274 static_cast<signed int>(
4275 switch_1->line_index(0)),
4276 static_cast<signed int>(
4277 switch_1->line_index(1)),
4278 static_cast<signed int>(
4279 switch_1->line_index(2)),
4280 static_cast<signed int>(
4281 switch_1->line_index(3))};
4282 const bool switch_1_line_orientations[4] = {
4283 switch_1->line_orientation(0),
4284 switch_1->line_orientation(1),
4285 switch_1->line_orientation(2),
4286 switch_1->line_orientation(3)};
4287 const types::boundary_id switch_1_boundary_id =
4288 switch_1->boundary_id();
4289 const unsigned int switch_1_user_index =
4290 switch_1->user_index();
4291 const bool switch_1_user_flag =
4292 switch_1->user_flag_set();
4293
4294 switch_1->set_bounding_object_indices(
4295 {switch_2->line_index(0),
4296 switch_2->line_index(1),
4297 switch_2->line_index(2),
4298 switch_2->line_index(3)});
4299 switch_1->set_line_orientation(
4300 0, switch_2->line_orientation(0));
4301 switch_1->set_line_orientation(
4302 1, switch_2->line_orientation(1));
4303 switch_1->set_line_orientation(
4304 2, switch_2->line_orientation(2));
4305 switch_1->set_line_orientation(
4306 3, switch_2->line_orientation(3));
4307 switch_1->set_boundary_id_internal(
4308 switch_2->boundary_id());
4309 switch_1->set_manifold_id(
4310 switch_2->manifold_id());
4311 switch_1->set_user_index(switch_2->user_index());
4312 if (switch_2->user_flag_set())
4313 switch_1->set_user_flag();
4314 else
4315 switch_1->clear_user_flag();
4316
4317 switch_2->set_bounding_object_indices(
4318 {switch_1_lines[0],
4319 switch_1_lines[1],
4320 switch_1_lines[2],
4321 switch_1_lines[3]});
4322 switch_2->set_line_orientation(
4323 0, switch_1_line_orientations[0]);
4324 switch_2->set_line_orientation(
4325 1, switch_1_line_orientations[1]);
4326 switch_2->set_line_orientation(
4327 2, switch_1_line_orientations[2]);
4328 switch_2->set_line_orientation(
4329 3, switch_1_line_orientations[3]);
4330 switch_2->set_boundary_id_internal(
4331 switch_1_boundary_id);
4332 switch_2->set_manifold_id(
4333 switch_1->manifold_id());
4334 switch_2->set_user_index(switch_1_user_index);
4335 if (switch_1_user_flag)
4336 switch_2->set_user_flag();
4337 else
4338 switch_2->clear_user_flag();
4339
4340 const unsigned int child_0 =
4341 quad->child(0)->child_index(0);
4342 const unsigned int child_2 =
4343 quad->child(1)->child_index(0);
4344 quad->clear_children();
4345 quad->clear_refinement_case();
4346 quad->set_refinement_case(
4348 quad->set_children(0, child_0);
4349 quad->set_children(2, child_2);
4350 std::swap(quad_cell_count[child_0 + 1],
4351 quad_cell_count[child_2]);
4352 }
4353 else
4354 {
4355 // the face was refined
4356 // with cut_y, thus the
4357 // children are already
4358 // in correct order. we
4359 // only have to set them
4360 // correctly, deleting
4361 // the indirection of two
4362 // anisotropic refinement
4363 // and going directly
4364 // from the quad to
4365 // isotropic children
4366 const unsigned int child_0 =
4367 quad->child(0)->child_index(0);
4368 const unsigned int child_2 =
4369 quad->child(1)->child_index(0);
4370 quad->clear_children();
4371 quad->clear_refinement_case();
4372 quad->set_refinement_case(
4374 quad->set_children(0, child_0);
4375 quad->set_children(2, child_2);
4376 }
4377 else
4378 {
4379 quad->clear_children();
4380 quad->clear_refinement_case();
4381 }
4382 }
4383 break;
4384 }
4385 case RefinementCase<dim - 1>::cut_xy:
4386 {
4387 // if one of the cell counters is
4388 // zero, the others have to be as
4389 // well
4390
4391 Assert((quad_cell_count[quad->child_index(0)] == 0 &&
4392 quad_cell_count[quad->child_index(1)] == 0 &&
4393 quad_cell_count[quad->child_index(2)] == 0 &&
4394 quad_cell_count[quad->child_index(3)] == 0) ||
4395 (quad_cell_count[quad->child_index(0)] > 0 &&
4396 quad_cell_count[quad->child_index(1)] > 0 &&
4397 quad_cell_count[quad->child_index(2)] > 0 &&
4398 quad_cell_count[quad->child_index(3)] > 0),
4400
4401 if (quad_cell_count[quad->child_index(0)] == 0)
4402 {
4403 // we may delete the quad's
4404 // children, the inner lines
4405 // and the middle vertex as no
4406 // cell references them anymore
4407 lines_to_delete.push_back(quad->child(0)->line(1));
4408 lines_to_delete.push_back(quad->child(3)->line(0));
4409 lines_to_delete.push_back(quad->child(0)->line(3));
4410 lines_to_delete.push_back(quad->child(3)->line(2));
4411
4412 for (unsigned int child = 0; child < quad->n_children();
4413 ++child)
4414 quads_to_delete.push_back(quad->child(child));
4415
4417 .vertices_used[quad->child(0)->vertex_index(3)] =
4418 false;
4419
4420 quad->clear_children();
4421 quad->clear_refinement_case();
4422 }
4423 }
4424 break;
4425
4426 default:
4428 break;
4429 }
4430 }
4431
4432 // now we repeat a similar procedure
4433 // for the outer lines of this cell.
4434
4435 // if in debug mode: check that each
4436 // of the lines for which we consider
4437 // deleting the children in fact has
4438 // children (the bits/coarsening_3d
4439 // test tripped over this initially)
4440 for (unsigned int line_no = 0;
4441 line_no < GeometryInfo<dim>::lines_per_cell;
4442 ++line_no)
4443 {
4445 cell->line(line_no);
4446
4447 Assert(
4448 (GeometryInfo<dim>::line_refinement_case(ref_case, line_no) &&
4449 line->has_children()) ||
4450 GeometryInfo<dim>::line_refinement_case(ref_case, line_no) ==
4453
4454 if (line->has_children())
4455 {
4456 // if one of the cell counters is
4457 // zero, the other has to be as well
4458
4459 Assert((line_cell_count[line->child_index(0)] == 0 &&
4460 line_cell_count[line->child_index(1)] == 0) ||
4461 (line_cell_count[line->child_index(0)] > 0 &&
4462 line_cell_count[line->child_index(1)] > 0),
4464
4465 if (line_cell_count[line->child_index(0)] == 0)
4466 {
4467 for (unsigned int c = 0; c < 2; ++c)
4468 Assert(!line->child(c)->has_children(),
4470
4471 // we may delete the line's
4472 // children and the middle vertex
4473 // as no cell references them
4474 // anymore
4476 .vertices_used[line->child(0)->vertex_index(1)] = false;
4477
4478 lines_to_delete.push_back(line->child(0));
4479 lines_to_delete.push_back(line->child(1));
4480
4481 line->clear_children();
4482 }
4483 }
4484 }
4485
4486 // finally, delete unneeded quads and lines
4487
4488 // clear user pointers, to avoid that
4489 // they may appear at unwanted places
4490 // later on...
4491 // same for user flags, then finally
4492 // delete the quads and lines
4493 typename std::vector<
4495 line = lines_to_delete.begin(),
4496 endline = lines_to_delete.end();
4497 for (; line != endline; ++line)
4498 {
4499 (*line)->clear_user_data();
4500 (*line)->clear_user_flag();
4501 (*line)->clear_used_flag();
4502 }
4503
4504 typename std::vector<
4506 quad = quads_to_delete.begin(),
4507 endquad = quads_to_delete.end();
4508 for (; quad != endquad; ++quad)
4509 {
4510 (*quad)->clear_user_data();
4511 (*quad)->clear_children();
4512 (*quad)->clear_refinement_case();
4513 (*quad)->clear_user_flag();
4514 (*quad)->clear_used_flag();
4515 }
4516 }
4517
4518
4536 template <int spacedim>
4537 static void
4540 unsigned int &next_unused_vertex,
4542 &next_unused_line,
4544 &next_unused_cell,
4545 const typename Triangulation<2, spacedim>::cell_iterator &cell)
4546 {
4547 const unsigned int dim = 2;
4548 // clear refinement flag
4549 const RefinementCase<dim> ref_case = cell->refine_flag_set();
4550 cell->clear_refine_flag();
4551
4552 /* For the refinement process: since we go the levels up from the
4553 lowest, there are (unlike above) only two possibilities: a neighbor
4554 cell is on the same level or one level up (in both cases, it may or
4555 may not be refined later on, but we don't care here).
4556
4557 First:
4558 Set up an array of the 3x3 vertices, which are distributed on the
4559 cell (the array consists of indices into the @p{vertices} std::vector
4560
4561 2--7--3
4562 | | |
4563 4--8--5
4564 | | |
4565 0--6--1
4566
4567 note: in case of cut_x or cut_y not all these vertices are needed for
4568 the new cells
4569
4570 Second:
4571 Set up an array of the new lines (the array consists of iterator
4572 pointers into the lines arrays)
4573
4574 .-6-.-7-. The directions are: .->-.->-.
4575 1 9 3 ^ ^ ^
4576 .-10.11-. .->-.->-.
4577 0 8 2 ^ ^ ^
4578 .-4-.-5-. .->-.->-.
4579
4580 cut_x:
4581 .-4-.-5-.
4582 | | |
4583 0 6 1
4584 | | |
4585 .-2-.-3-.
4586
4587 cut_y:
4588 .---5---.
4589 1 3
4590 .---6---.
4591 0 2
4592 .---4---.
4593
4594
4595 Third:
4596 Set up an array of neighbors:
4597
4598 6 7
4599 .--.--.
4600 1| | |3
4601 .--.--.
4602 0| | |2
4603 .--.--.
4604 4 5
4605
4606 We need this array for two reasons: first to get the lines which will
4607 bound the four subcells (if the neighboring cell is refined, these
4608 lines already exist), and second to update neighborship information.
4609 Since if a neighbor is not refined, its neighborship record only
4610 points to the present, unrefined, cell rather than the children we
4611 are presently creating, we only need the neighborship information
4612 if the neighbor cells are refined. In all other cases, we store
4613 the unrefined neighbor address
4614
4615 We also need for every neighbor (if refined) which number among its
4616 neighbors the present (unrefined) cell has, since that number is to
4617 be replaced and because that also is the number of the subline which
4618 will be the interface between that neighbor and the to be created
4619 cell. We will store this number (between 0 and 3) in the field
4620 @p{neighbors_neighbor}.
4621
4622 It would be sufficient to use the children of the common line to the
4623 neighbor, if we only wanted to get the new sublines and the new
4624 vertex, but because we need to update the neighborship information of
4625 the two refined subcells of the neighbor, we need to search these
4626 anyway.
4627
4628 Convention:
4629 The created children are numbered like this:
4630
4631 .--.--.
4632 |2 . 3|
4633 .--.--.
4634 |0 | 1|
4635 .--.--.
4636 */
4637 // collect the indices of the eight surrounding vertices
4638 // 2--7--3
4639 // | | |
4640 // 4--8--5
4641 // | | |
4642 // 0--6--1
4643 int new_vertices[9];
4644 for (unsigned int vertex_no = 0; vertex_no < 4; ++vertex_no)
4645 new_vertices[vertex_no] = cell->vertex_index(vertex_no);
4646 for (unsigned int line_no = 0; line_no < 4; ++line_no)
4647 if (cell->line(line_no)->has_children())
4648 new_vertices[4 + line_no] =
4649 cell->line(line_no)->child(0)->vertex_index(1);
4650
4651 if (ref_case == RefinementCase<dim>::cut_xy)
4652 {
4653 // find the next
4654 // unused vertex and
4655 // allocate it for
4656 // the new vertex we
4657 // need here
4658 while (triangulation.vertices_used[next_unused_vertex] == true)
4659 ++next_unused_vertex;
4660 Assert(next_unused_vertex < triangulation.vertices.size(),
4661 ExcMessage(
4662 "Internal error: During refinement, the triangulation "
4663 "wants to access an element of the 'vertices' array "
4664 "but it turns out that the array is not large enough."));
4665 triangulation.vertices_used[next_unused_vertex] = true;
4666
4667 new_vertices[8] = next_unused_vertex;
4668
4669 // determine middle vertex by transfinite interpolation to be
4670 // consistent with what happens to quads in a
4671 // Triangulation<3,3> when they are refined
4672 triangulation.vertices[next_unused_vertex] =
4673 cell->center(true, true);
4674 }
4675
4676
4677 // Now the lines:
4679 unsigned int lmin = 8;
4680 unsigned int lmax = 12;
4681 if (ref_case != RefinementCase<dim>::cut_xy)
4682 {
4683 lmin = 6;
4684 lmax = 7;
4685 }
4686
4687 for (unsigned int l = lmin; l < lmax; ++l)
4688 {
4689 while (next_unused_line->used() == true)
4690 ++next_unused_line;
4691 new_lines[l] = next_unused_line;
4692 ++next_unused_line;
4693
4694 AssertIsNotUsed(new_lines[l]);
4695 }
4696
4697 if (ref_case == RefinementCase<dim>::cut_xy)
4698 {
4699 // .-6-.-7-.
4700 // 1 9 3
4701 // .-10.11-.
4702 // 0 8 2
4703 // .-4-.-5-.
4704
4705 // lines 0-7 already exist, create only the four interior
4706 // lines 8-11
4707 unsigned int l = 0;
4708 for (const unsigned int face_no : GeometryInfo<dim>::face_indices())
4709 for (unsigned int c = 0; c < 2; ++c, ++l)
4710 new_lines[l] = cell->line(face_no)->child(c);
4711 Assert(l == 8, ExcInternalError());
4712
4713 new_lines[8]->set_bounding_object_indices(
4714 {new_vertices[6], new_vertices[8]});
4715 new_lines[9]->set_bounding_object_indices(
4716 {new_vertices[8], new_vertices[7]});
4717 new_lines[10]->set_bounding_object_indices(
4718 {new_vertices[4], new_vertices[8]});
4719 new_lines[11]->set_bounding_object_indices(
4720 {new_vertices[8], new_vertices[5]});
4721 }
4722 else if (ref_case == RefinementCase<dim>::cut_x)
4723 {
4724 // .-4-.-5-.
4725 // | | |
4726 // 0 6 1
4727 // | | |
4728 // .-2-.-3-.
4729 new_lines[0] = cell->line(0);
4730 new_lines[1] = cell->line(1);
4731 new_lines[2] = cell->line(2)->child(0);
4732 new_lines[3] = cell->line(2)->child(1);
4733 new_lines[4] = cell->line(3)->child(0);
4734 new_lines[5] = cell->line(3)->child(1);
4735 new_lines[6]->set_bounding_object_indices(
4736 {new_vertices[6], new_vertices[7]});
4737 }
4738 else
4739 {
4741 // .---5---.
4742 // 1 3
4743 // .---6---.
4744 // 0 2
4745 // .---4---.
4746 new_lines[0] = cell->line(0)->child(0);
4747 new_lines[1] = cell->line(0)->child(1);
4748 new_lines[2] = cell->line(1)->child(0);
4749 new_lines[3] = cell->line(1)->child(1);
4750 new_lines[4] = cell->line(2);
4751 new_lines[5] = cell->line(3);
4752 new_lines[6]->set_bounding_object_indices(
4753 {new_vertices[4], new_vertices[5]});
4754 }
4755
4756 for (unsigned int l = lmin; l < lmax; ++l)
4757 {
4758 new_lines[l]->set_used_flag();
4759 new_lines[l]->clear_user_flag();
4760 new_lines[l]->clear_user_data();
4761 new_lines[l]->clear_children();
4762 // interior line
4763 new_lines[l]->set_boundary_id_internal(
4765 new_lines[l]->set_manifold_id(cell->manifold_id());
4766 }
4767
4768 // Now add the four (two)
4769 // new cells!
4772 while (next_unused_cell->used() == true)
4773 ++next_unused_cell;
4774
4775 const unsigned int n_children = GeometryInfo<dim>::n_children(ref_case);
4776 for (unsigned int i = 0; i < n_children; ++i)
4777 {
4778 AssertIsNotUsed(next_unused_cell);
4779 subcells[i] = next_unused_cell;
4780 ++next_unused_cell;
4781 if (i % 2 == 1 && i < n_children - 1)
4782 while (next_unused_cell->used() == true)
4783 ++next_unused_cell;
4784 }
4785
4786 if (ref_case == RefinementCase<dim>::cut_xy)
4787 {
4788 // children:
4789 // .--.--.
4790 // |2 . 3|
4791 // .--.--.
4792 // |0 | 1|
4793 // .--.--.
4794 // lines:
4795 // .-6-.-7-.
4796 // 1 9 3
4797 // .-10.11-.
4798 // 0 8 2
4799 // .-4-.-5-.
4800 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
4801 new_lines[8]->index(),
4802 new_lines[4]->index(),
4803 new_lines[10]->index()});
4804 subcells[1]->set_bounding_object_indices({new_lines[8]->index(),
4805 new_lines[2]->index(),
4806 new_lines[5]->index(),
4807 new_lines[11]->index()});
4808 subcells[2]->set_bounding_object_indices({new_lines[1]->index(),
4809 new_lines[9]->index(),
4810 new_lines[10]->index(),
4811 new_lines[6]->index()});
4812 subcells[3]->set_bounding_object_indices({new_lines[9]->index(),
4813 new_lines[3]->index(),
4814 new_lines[11]->index(),
4815 new_lines[7]->index()});
4816 }
4817 else if (ref_case == RefinementCase<dim>::cut_x)
4818 {
4819 // children:
4820 // .--.--.
4821 // | . |
4822 // .0 . 1.
4823 // | | |
4824 // .--.--.
4825 // lines:
4826 // .-4-.-5-.
4827 // | | |
4828 // 0 6 1
4829 // | | |
4830 // .-2-.-3-.
4831 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
4832 new_lines[6]->index(),
4833 new_lines[2]->index(),
4834 new_lines[4]->index()});
4835 subcells[1]->set_bounding_object_indices({new_lines[6]->index(),
4836 new_lines[1]->index(),
4837 new_lines[3]->index(),
4838 new_lines[5]->index()});
4839 }
4840 else
4841 {
4843 // children:
4844 // .-----.
4845 // | 1 |
4846 // .-----.
4847 // | 0 |
4848 // .-----.
4849 // lines:
4850 // .---5---.
4851 // 1 3
4852 // .---6---.
4853 // 0 2
4854 // .---4---.
4855 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
4856 new_lines[2]->index(),
4857 new_lines[4]->index(),
4858 new_lines[6]->index()});
4859 subcells[1]->set_bounding_object_indices({new_lines[1]->index(),
4860 new_lines[3]->index(),
4861 new_lines[6]->index(),
4862 new_lines[5]->index()});
4863 }
4864
4865 types::subdomain_id subdomainid = cell->subdomain_id();
4866
4867 for (unsigned int i = 0; i < n_children; ++i)
4868 {
4869 subcells[i]->set_used_flag();
4870 subcells[i]->clear_refine_flag();
4871 subcells[i]->clear_user_flag();
4872 subcells[i]->clear_user_data();
4873 subcells[i]->clear_children();
4874 // inherit material properties
4875 subcells[i]->set_material_id(cell->material_id());
4876 subcells[i]->set_manifold_id(cell->manifold_id());
4877 subcells[i]->set_subdomain_id(subdomainid);
4878
4879 if (i % 2 == 0)
4880 subcells[i]->set_parent(cell->index());
4881 }
4882
4883
4884
4885 // set child index for even children i=0,2 (0)
4886 for (unsigned int i = 0; i < n_children / 2; ++i)
4887 cell->set_children(2 * i, subcells[2 * i]->index());
4888 // set the refine case
4889 cell->set_refinement_case(ref_case);
4890
4891 // note that the
4892 // refinement flag was
4893 // already cleared at the
4894 // beginning of this function
4895
4896 if (dim == spacedim - 1)
4897 for (unsigned int c = 0; c < n_children; ++c)
4898 cell->child(c)->set_direction_flag(cell->direction_flag());
4899 }
4900
4901
4902
4903 template <int dim, int spacedim>
4906 const bool check_for_distorted_cells)
4907 {
4908 AssertDimension(dim, 2);
4909
4910 // Check whether a new level is needed. We have to check for
4911 // this on the highest level only
4912 for (const auto &cell : triangulation.active_cell_iterators_on_level(
4913 triangulation.levels.size() - 1))
4914 if (cell->refine_flag_set())
4915 {
4916 triangulation.levels.push_back(
4917 std::make_unique<
4919 break;
4920 }
4921
4924 line != triangulation.end_line();
4925 ++line)
4926 {
4927 line->clear_user_flag();
4928 line->clear_user_data();
4929 }
4930
4931 unsigned int n_single_lines = 0;
4932 unsigned int n_lines_in_pairs = 0;
4933 unsigned int needed_vertices = 0;
4934
4935 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
4936 {
4937 // count number of flagged cells on this level and compute
4938 // how many new vertices and new lines will be needed
4939 unsigned int needed_cells = 0;
4940
4941 for (const auto &cell :
4942 triangulation.active_cell_iterators_on_level(level))
4943 if (cell->refine_flag_set())
4944 {
4945 if (cell->reference_cell() == ReferenceCells::Triangle)
4946 {
4947 needed_cells += 4;
4948 needed_vertices += 0;
4949 n_single_lines += 3;
4950 }
4951 else if (cell->reference_cell() ==
4953 {
4954 needed_cells += 4;
4955 needed_vertices += 1;
4956 n_single_lines += 4;
4957 }
4958 else
4959 {
4961 }
4962
4963 for (const auto line_no : cell->face_indices())
4964 {
4965 auto line = cell->line(line_no);
4966 if (line->has_children() == false)
4967 line->set_user_flag();
4968 }
4969 }
4970
4971
4972 const unsigned int used_cells =
4973 std::count(triangulation.levels[level + 1]->cells.used.begin(),
4974 triangulation.levels[level + 1]->cells.used.end(),
4975 true);
4976
4977
4978 reserve_space(*triangulation.levels[level + 1],
4979 used_cells + needed_cells,
4980 2,
4981 spacedim);
4982
4983 reserve_space(triangulation.levels[level + 1]->cells,
4984 needed_cells,
4985 0);
4986 }
4987
4988 for (auto line = triangulation.begin_line();
4989 line != triangulation.end_line();
4990 ++line)
4991 if (line->user_flag_set())
4992 {
4993 Assert(line->has_children() == false, ExcInternalError());
4994 n_lines_in_pairs += 2;
4995 needed_vertices += 1;
4996 }
4997
4998 reserve_space(triangulation.faces->lines, n_lines_in_pairs, 0);
4999
5000 needed_vertices += std::count(triangulation.vertices_used.begin(),
5001 triangulation.vertices_used.end(),
5002 true);
5003
5004 if (needed_vertices > triangulation.vertices.size())
5005 {
5006 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
5007 triangulation.vertices_used.resize(needed_vertices, false);
5008 }
5009
5010 unsigned int next_unused_vertex = 0;
5011
5012 {
5015 endl = triangulation.end_line();
5017 next_unused_line = triangulation.begin_raw_line();
5018
5019 for (; line != endl; ++line)
5020 if (line->user_flag_set())
5021 {
5022 // This line needs to be refined. Find the next unused vertex
5023 // and set it appropriately
5024 while (triangulation.vertices_used[next_unused_vertex] == true)
5025 ++next_unused_vertex;
5026 Assert(
5027 next_unused_vertex < triangulation.vertices.size(),
5028 ExcMessage(
5029 "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."));
5030 triangulation.vertices_used[next_unused_vertex] = true;
5031
5032 triangulation.vertices[next_unused_vertex] = line->center(true);
5033
5034 bool pair_found = false;
5035 (void)pair_found;
5036 for (; next_unused_line != endl; ++next_unused_line)
5037 if (!next_unused_line->used() &&
5038 !(++next_unused_line)->used())
5039 {
5040 --next_unused_line;
5041 pair_found = true;
5042 break;
5043 }
5044 Assert(pair_found, ExcInternalError());
5045
5046 line->set_children(0, next_unused_line->index());
5047
5049 children[2] = {next_unused_line, ++next_unused_line};
5050
5051 AssertIsNotUsed(children[0]);
5052 AssertIsNotUsed(children[1]);
5053
5054 children[0]->set_bounding_object_indices(
5055 {line->vertex_index(0), next_unused_vertex});
5056 children[1]->set_bounding_object_indices(
5057 {next_unused_vertex, line->vertex_index(1)});
5058
5059 for (auto &child : children)
5060 {
5061 child->set_used_flag();
5062 child->clear_children();
5063 child->clear_user_data();
5064 child->clear_user_flag();
5065 child->set_boundary_id_internal(line->boundary_id());
5066 child->set_manifold_id(line->manifold_id());
5067 // Line orientation is relative to the cell it is on so
5068 // those cannot be set at this point.
5069 }
5070
5071 line->clear_user_flag();
5072 }
5073 }
5074
5075 reserve_space(triangulation.faces->lines, 0, n_single_lines);
5076
5078 cells_with_distorted_children;
5079
5081 next_unused_line = triangulation.begin_raw_line();
5082
5083 const auto create_children = [](auto &triangulation,
5084 unsigned int &next_unused_vertex,
5085 auto &next_unused_line,
5086 auto &next_unused_cell,
5087 const auto &cell) {
5088 const auto ref_case = cell->refine_flag_set();
5089 cell->clear_refine_flag();
5090
5091 unsigned int n_new_vertices = 0;
5092
5093 if (cell->reference_cell() == ReferenceCells::Triangle)
5094 n_new_vertices = 6;
5095 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5096 n_new_vertices = 9;
5097 else
5099
5100 std::vector<unsigned int> new_vertices(n_new_vertices,
5102 for (unsigned int vertex_no = 0; vertex_no < cell->n_vertices();
5103 ++vertex_no)
5104 new_vertices[vertex_no] = cell->vertex_index(vertex_no);
5105 for (unsigned int line_no = 0; line_no < cell->n_lines(); ++line_no)
5106 if (cell->line(line_no)->has_children())
5107 new_vertices[cell->n_vertices() + line_no] =
5108 cell->line(line_no)->child(0)->vertex_index(1);
5109
5110 if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5111 {
5112 while (triangulation.vertices_used[next_unused_vertex] == true)
5113 ++next_unused_vertex;
5114 Assert(
5115 next_unused_vertex < triangulation.vertices.size(),
5116 ExcMessage(
5117 "Internal error: During refinement, the triangulation wants "
5118 "to access an element of the 'vertices' array but it turns "
5119 "out that the array is not large enough."));
5120 triangulation.vertices_used[next_unused_vertex] = true;
5121
5122 new_vertices[8] = next_unused_vertex;
5123
5124 triangulation.vertices[next_unused_vertex] =
5125 cell->center(true, true);
5126 }
5127
5128 std::array<typename Triangulation<dim, spacedim>::raw_line_iterator,
5129 12>
5130 new_lines;
5131 std::array<unsigned char, 12> inherited_orientations;
5132 inherited_orientations.fill(
5134 unsigned int lmin = 0;
5135 unsigned int lmax = 0;
5136
5137 if (cell->reference_cell() == ReferenceCells::Triangle)
5138 {
5139 lmin = 6;
5140 lmax = 9;
5141 // For triangles, the innermost faces are always reversed for the
5142 // first three children and are in the standard orientation for
5143 // the last one.
5144 std::fill(inherited_orientations.begin() + lmin,
5145 inherited_orientations.begin() + lmax,
5147 }
5148 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5149 {
5150 lmin = 8;
5151 lmax = 12;
5152 }
5153 else
5154 {
5156 }
5157
5158 for (unsigned int l = lmin; l < lmax; ++l)
5159 {
5160 while (next_unused_line->used() == true)
5161 ++next_unused_line;
5162 new_lines[l] = next_unused_line;
5163 ++next_unused_line;
5164
5165 AssertIsNotUsed(new_lines[l]);
5166 }
5167
5168 // set up lines which have parents:
5169 for (const unsigned int face_no : cell->face_indices())
5170 {
5171 // Check the face (line) orientation to ensure that the (six or
5172 // eight) outer lines in new_lines are indexed in the default
5173 // orientation. This way we can index into this array in the
5174 // without special casing orientations (e.g., quadrilateral child
5175 // 3 will always have lines 9, 3, 11, 7) when setting child lines.
5176 const unsigned char combined_orientation =
5177 cell->combined_face_orientation(face_no);
5178 Assert(combined_orientation ==
5180 combined_orientation ==
5183 for (unsigned int c = 0; c < 2; ++c)
5184 {
5185 new_lines[2 * face_no + c] = cell->line(face_no)->child(c);
5186 inherited_orientations[2 * face_no + c] =
5187 cell->combined_face_orientation(face_no);
5188 }
5189 if (combined_orientation ==
5191 std::swap(new_lines[2 * face_no], new_lines[2 * face_no + 1]);
5192 }
5193
5194 // set up lines which do not have parents:
5195 if (cell->reference_cell() == ReferenceCells::Triangle)
5196 {
5197 new_lines[6]->set_bounding_object_indices(
5198 {new_vertices[3], new_vertices[4]});
5199 new_lines[7]->set_bounding_object_indices(
5200 {new_vertices[4], new_vertices[5]});
5201 new_lines[8]->set_bounding_object_indices(
5202 {new_vertices[5], new_vertices[3]});
5203 }
5204 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5205 {
5206 new_lines[8]->set_bounding_object_indices(
5207 {new_vertices[6], new_vertices[8]});
5208 new_lines[9]->set_bounding_object_indices(
5209 {new_vertices[8], new_vertices[7]});
5210 new_lines[10]->set_bounding_object_indices(
5211 {new_vertices[4], new_vertices[8]});
5212 new_lines[11]->set_bounding_object_indices(
5213 {new_vertices[8], new_vertices[5]});
5214 }
5215 else
5216 {
5218 }
5219
5220 for (unsigned int l = lmin; l < lmax; ++l)
5221 {
5222 new_lines[l]->set_used_flag();
5223 new_lines[l]->clear_user_flag();
5224 new_lines[l]->clear_user_data();
5225 new_lines[l]->clear_children();
5226 // new lines are always internal.
5227 new_lines[l]->set_boundary_id_internal(
5229 new_lines[l]->set_manifold_id(cell->manifold_id());
5230 }
5231
5234 while (next_unused_cell->used() == true)
5235 ++next_unused_cell;
5236
5237 unsigned int n_children = 0;
5238 if (cell->reference_cell() == ReferenceCells::Triangle)
5239 n_children = 4;
5240 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5241 n_children = 4;
5242 else
5244
5245 for (unsigned int i = 0; i < n_children; ++i)
5246 {
5247 AssertIsNotUsed(next_unused_cell);
5248 subcells[i] = next_unused_cell;
5249 ++next_unused_cell;
5250 if (i % 2 == 1 && i < n_children - 1)
5251 while (next_unused_cell->used() == true)
5252 ++next_unused_cell;
5253 }
5254
5255 // Assign lines to child cells:
5256 constexpr unsigned int X = numbers::invalid_unsigned_int;
5257 static constexpr ::ndarray<unsigned int, 4, 4> tri_child_lines =
5258 {{{{0, 8, 5, X}}, {{1, 2, 6, X}}, {{7, 3, 4, X}}, {{6, 7, 8, X}}}};
5259 static constexpr ::ndarray<unsigned int, 4, 4>
5260 quad_child_lines = {{{{0, 8, 4, 10}},
5261 {{8, 2, 5, 11}},
5262 {{1, 9, 10, 6}},
5263 {{9, 3, 11, 7}}}};
5264 // Here and below we assume that child cells have the same reference
5265 // cell type as the parent.
5266 const auto &child_lines =
5267 cell->reference_cell() == ReferenceCells::Triangle ?
5268 tri_child_lines :
5269 quad_child_lines;
5270 for (unsigned int i = 0; i < n_children; ++i)
5271 {
5272 if (cell->reference_cell() == ReferenceCells::Triangle)
5273 subcells[i]->set_bounding_object_indices(
5274 {new_lines[child_lines[i][0]]->index(),
5275 new_lines[child_lines[i][1]]->index(),
5276 new_lines[child_lines[i][2]]->index()});
5277 else
5278 subcells[i]->set_bounding_object_indices(
5279 {new_lines[child_lines[i][0]]->index(),
5280 new_lines[child_lines[i][1]]->index(),
5281 new_lines[child_lines[i][2]]->index(),
5282 new_lines[child_lines[i][3]]->index()});
5283
5284 subcells[i]->set_used_flag();
5285 subcells[i]->clear_refine_flag();
5286 subcells[i]->clear_user_flag();
5287 subcells[i]->clear_user_data();
5288 subcells[i]->clear_children();
5289 // inherit material properties
5290 subcells[i]->set_material_id(cell->material_id());
5291 subcells[i]->set_manifold_id(cell->manifold_id());
5292 subcells[i]->set_subdomain_id(cell->subdomain_id());
5293
5294 triangulation.levels[subcells[i]->level()]
5295 ->reference_cell[subcells[i]->index()] = cell->reference_cell();
5296
5297 // Finally, now that children are marked as used, we can set
5298 // orientation flags:
5299 for (unsigned int face_no : cell->face_indices())
5300 subcells[i]->set_combined_face_orientation(
5301 face_no, inherited_orientations[child_lines[i][face_no]]);
5302
5303 if (i % 2 == 0)
5304 subcells[i]->set_parent(cell->index());
5305 }
5306
5307 // Unlike the same lines on other children, the innermost triangle's
5308 // faces are all in the default orientation:
5309 if (cell->reference_cell() == ReferenceCells::Triangle)
5310 for (unsigned int face_no : cell->face_indices())
5311 subcells[3]->set_combined_face_orientation(
5313
5314 for (unsigned int i = 0; i < n_children / 2; ++i)
5315 cell->set_children(2 * i, subcells[2 * i]->index());
5316
5317 cell->set_refinement_case(ref_case);
5318
5319 if (dim == spacedim - 1)
5320 for (unsigned int c = 0; c < n_children; ++c)
5321 cell->child(c)->set_direction_flag(cell->direction_flag());
5322 };
5323
5324 for (int level = 0;
5325 level < static_cast<int>(triangulation.levels.size()) - 1;
5326 ++level)
5327 {
5329 next_unused_cell = triangulation.begin_raw(level + 1);
5330
5331 for (const auto &cell :
5332 triangulation.active_cell_iterators_on_level(level))
5333 if (cell->refine_flag_set())
5334 {
5335 create_children(triangulation,
5336 next_unused_vertex,
5337 next_unused_line,
5338 next_unused_cell,
5339 cell);
5340
5341 if (cell->reference_cell() == ReferenceCells::Quadrilateral &&
5342 check_for_distorted_cells &&
5343 has_distorted_children<dim, spacedim>(cell))
5344 cells_with_distorted_children.distorted_cells.push_back(
5345 cell);
5346
5347 triangulation.signals.post_refinement_on_cell(cell);
5348 }
5349 }
5350
5351 return cells_with_distorted_children;
5352 }
5353
5354
5355
5360 template <int spacedim>
5363 const bool /*check_for_distorted_cells*/)
5364 {
5365 const unsigned int dim = 1;
5366
5367 // Check whether a new level is needed. We have to check for
5368 // this on the highest level only
5369 for (const auto &cell : triangulation.active_cell_iterators_on_level(
5370 triangulation.levels.size() - 1))
5371 if (cell->refine_flag_set())
5372 {
5373 triangulation.levels.push_back(
5374 std::make_unique<
5376 break;
5377 }
5378
5379
5380 // check how much space is needed on every level. We need not
5381 // check the highest level since either - on the highest level
5382 // no cells are flagged for refinement - there are, but
5383 // prepare_refinement added another empty level
5384 unsigned int needed_vertices = 0;
5385 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5386 {
5387 // count number of flagged
5388 // cells on this level
5389 unsigned int flagged_cells = 0;
5390
5391 for (const auto &acell :
5392 triangulation.active_cell_iterators_on_level(level))
5393 if (acell->refine_flag_set())
5394 ++flagged_cells;
5395
5396 // count number of used cells
5397 // on the next higher level
5398 const unsigned int used_cells =
5399 std::count(triangulation.levels[level + 1]->cells.used.begin(),
5400 triangulation.levels[level + 1]->cells.used.end(),
5401 true);
5402
5403 // reserve space for the used_cells cells already existing
5404 // on the next higher level as well as for the
5405 // 2*flagged_cells that will be created on that level
5406 reserve_space(*triangulation.levels[level + 1],
5408 flagged_cells,
5409 1,
5410 spacedim);
5411 // reserve space for 2*flagged_cells new lines on the next
5412 // higher level
5413 reserve_space(triangulation.levels[level + 1]->cells,
5415 flagged_cells,
5416 0);
5417
5418 needed_vertices += flagged_cells;
5419 }
5420
5421 // add to needed vertices how many
5422 // vertices are already in use
5423 needed_vertices += std::count(triangulation.vertices_used.begin(),
5424 triangulation.vertices_used.end(),
5425 true);
5426 // if we need more vertices: create them, if not: leave the
5427 // array as is, since shrinking is not really possible because
5428 // some of the vertices at the end may be in use
5429 if (needed_vertices > triangulation.vertices.size())
5430 {
5431 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
5432 triangulation.vertices_used.resize(needed_vertices, false);
5433 }
5434
5435
5436 // Do REFINEMENT on every level; exclude highest level as
5437 // above
5438
5439 // index of next unused vertex
5440 unsigned int next_unused_vertex = 0;
5441
5442 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5443 {
5445 next_unused_cell = triangulation.begin_raw(level + 1);
5446
5447 for (const auto &cell :
5448 triangulation.active_cell_iterators_on_level(level))
5449 if (cell->refine_flag_set())
5450 {
5451 // clear refinement flag
5452 cell->clear_refine_flag();
5453
5454 // search for next unused
5455 // vertex
5456 while (triangulation.vertices_used[next_unused_vertex] ==
5457 true)
5458 ++next_unused_vertex;
5459 Assert(
5460 next_unused_vertex < triangulation.vertices.size(),
5461 ExcMessage(
5462 "Internal error: During refinement, the triangulation "
5463 "wants to access an element of the 'vertices' array "
5464 "but it turns out that the array is not large enough."));
5465
5466 // Now we always ask the cell itself where to put
5467 // the new point. The cell in turn will query the
5468 // manifold object internally.
5469 triangulation.vertices[next_unused_vertex] =
5470 cell->center(true);
5471
5472 triangulation.vertices_used[next_unused_vertex] = true;
5473
5474 // search for next two unused cell (++ takes care of
5475 // the end of the vector)
5477 first_child,
5478 second_child;
5479 while (next_unused_cell->used() == true)
5480 ++next_unused_cell;
5481 first_child = next_unused_cell;
5482 first_child->set_used_flag();
5483 first_child->clear_user_data();
5484 ++next_unused_cell;
5485 AssertIsNotUsed(next_unused_cell);
5486 second_child = next_unused_cell;
5487 second_child->set_used_flag();
5488 second_child->clear_user_data();
5489
5490 types::subdomain_id subdomainid = cell->subdomain_id();
5491
5492 // insert first child
5493 cell->set_children(0, first_child->index());
5494 first_child->clear_children();
5495 first_child->set_bounding_object_indices(
5496 {cell->vertex_index(0), next_unused_vertex});
5497 first_child->set_material_id(cell->material_id());
5498 first_child->set_manifold_id(cell->manifold_id());
5499 first_child->set_subdomain_id(subdomainid);
5500 if (dim == spacedim - 1)
5501 first_child->set_direction_flag(cell->direction_flag());
5502
5503 first_child->set_parent(cell->index());
5504
5505 // Set manifold id of the right face. Only do this
5506 // on the first child.
5507 first_child->face(1)->set_manifold_id(cell->manifold_id());
5508
5509 // reset neighborship info (refer to
5510 // internal::TriangulationImplementation::TriaLevel<0> for
5511 // details)
5512 first_child->set_neighbor(1, second_child);
5513 if (cell->neighbor(0).state() != IteratorState::valid)
5514 first_child->set_neighbor(0, cell->neighbor(0));
5515 else if (cell->neighbor(0)->is_active())
5516 {
5517 // since the neighbors level is always <=level,
5518 // if the cell is active, then there are no
5519 // cells to the left which may want to know
5520 // about this new child cell.
5521 Assert(cell->neighbor(0)->level() <= cell->level(),
5523 first_child->set_neighbor(0, cell->neighbor(0));
5524 }
5525 else
5526 // left neighbor is refined
5527 {
5528 // set neighbor to cell on same level
5529 const unsigned int nbnb = cell->neighbor_of_neighbor(0);
5530 first_child->set_neighbor(0,
5531 cell->neighbor(0)->child(nbnb));
5532
5533 // reset neighbor info of all right descendant
5534 // of the left neighbor of cell
5536 left_neighbor = cell->neighbor(0);
5537 while (left_neighbor->has_children())
5538 {
5539 left_neighbor = left_neighbor->child(nbnb);
5540 left_neighbor->set_neighbor(nbnb, first_child);
5541 }
5542 }
5543
5544 // insert second child
5545 second_child->clear_children();
5546 second_child->set_bounding_object_indices(
5547 {next_unused_vertex, cell->vertex_index(1)});
5548 second_child->set_neighbor(0, first_child);
5549 second_child->set_material_id(cell->material_id());
5550 second_child->set_manifold_id(cell->manifold_id());
5551 second_child->set_subdomain_id(subdomainid);
5552 if (dim == spacedim - 1)
5553 second_child->set_direction_flag(cell->direction_flag());
5554
5555 if (cell->neighbor(1).state() != IteratorState::valid)
5556 second_child->set_neighbor(1, cell->neighbor(1));
5557 else if (cell->neighbor(1)->is_active())
5558 {
5559 Assert(cell->neighbor(1)->level() <= cell->level(),
5561 second_child->set_neighbor(1, cell->neighbor(1));
5562 }
5563 else
5564 // right neighbor is refined same as above
5565 {
5566 const unsigned int nbnb = cell->neighbor_of_neighbor(1);
5567 second_child->set_neighbor(
5568 1, cell->neighbor(1)->child(nbnb));
5569
5571 right_neighbor = cell->neighbor(1);
5572 while (right_neighbor->has_children())
5573 {
5574 right_neighbor = right_neighbor->child(nbnb);
5575 right_neighbor->set_neighbor(nbnb, second_child);
5576 }
5577 }
5578 // inform all listeners that cell refinement is done
5579 triangulation.signals.post_refinement_on_cell(cell);
5580 }
5581 }
5582
5583 // in 1d, we can not have distorted children unless the parent
5584 // was already distorted (that is because we don't use
5585 // boundary information for 1d triangulations). so return an
5586 // empty list
5588 }
5589
5590
5595 template <int spacedim>
5598 const bool check_for_distorted_cells)
5599 {
5600 const unsigned int dim = 2;
5601
5602 // First check whether we can get away with isotropic refinement, or
5603 // whether we need to run through the full anisotropic algorithm
5604 {
5605 bool do_isotropic_refinement = true;
5606 for (const auto &cell : triangulation.active_cell_iterators())
5607 if (cell->refine_flag_set() == RefinementCase<dim>::cut_x ||
5608 cell->refine_flag_set() == RefinementCase<dim>::cut_y)
5609 {
5610 do_isotropic_refinement = false;
5611 break;
5612 }
5613
5614 if (do_isotropic_refinement)
5615 return execute_refinement_isotropic(triangulation,
5616 check_for_distorted_cells);
5617 }
5618
5619 // If we get here, we are doing anisotropic refinement.
5620
5621 // Check whether a new level is needed. We have to check for
5622 // this on the highest level only
5623 for (const auto &cell : triangulation.active_cell_iterators_on_level(
5624 triangulation.levels.size() - 1))
5625 if (cell->refine_flag_set())
5626 {
5627 triangulation.levels.push_back(
5628 std::make_unique<
5630 break;
5631 }
5632
5633 // TODO[WB]: we clear user flags and pointers of lines; we're going
5634 // to use them to flag which lines need refinement
5637 line != triangulation.end_line();
5638 ++line)
5639 {
5640 line->clear_user_flag();
5641 line->clear_user_data();
5642 }
5643 // running over all cells and lines count the number
5644 // n_single_lines of lines which can be stored as single
5645 // lines, e.g. inner lines
5646 unsigned int n_single_lines = 0;
5647
5648 // New lines to be created: number lines which are stored in
5649 // pairs (the children of lines must be stored in pairs)
5650 unsigned int n_lines_in_pairs = 0;
5651
5652 // check how much space is needed on every level. We need not
5653 // check the highest level since either - on the highest level
5654 // no cells are flagged for refinement - there are, but
5655 // prepare_refinement added another empty level
5656 unsigned int needed_vertices = 0;
5657 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5658 {
5659 // count number of flagged cells on this level and compute
5660 // how many new vertices and new lines will be needed
5661 unsigned int needed_cells = 0;
5662
5663 for (const auto &cell :
5664 triangulation.active_cell_iterators_on_level(level))
5665 if (cell->refine_flag_set())
5666 {
5667 if (cell->refine_flag_set() == RefinementCase<dim>::cut_xy)
5668 {
5669 needed_cells += 4;
5670
5671 // new vertex at center of cell is needed in any
5672 // case
5673 ++needed_vertices;
5674
5675 // the four inner lines can be stored as singles
5676 n_single_lines += 4;
5677 }
5678 else // cut_x || cut_y
5679 {
5680 // set the flag showing that anisotropic
5681 // refinement is used for at least one cell
5682 triangulation.anisotropic_refinement = true;
5683
5684 needed_cells += 2;
5685 // no vertex at center
5686
5687 // the inner line can be stored as single
5688 n_single_lines += 1;
5689 }
5690
5691 // mark all faces (lines) for refinement; checking
5692 // locally whether the neighbor would also like to
5693 // refine them is rather difficult for lines so we
5694 // only flag them and after visiting all cells, we
5695 // decide which lines need refinement;
5696 for (const unsigned int line_no :
5698 {
5700 cell->refine_flag_set(), line_no) ==
5702 {
5704 line = cell->line(line_no);
5705 if (line->has_children() == false)
5706 line->set_user_flag();
5707 }
5708 }
5709 }
5710
5711
5712 // count number of used cells on the next higher level
5713 const unsigned int used_cells =
5714 std::count(triangulation.levels[level + 1]->cells.used.begin(),
5715 triangulation.levels[level + 1]->cells.used.end(),
5716 true);
5717
5718
5719 // reserve space for the used_cells cells already existing
5720 // on the next higher level as well as for the
5721 // needed_cells that will be created on that level
5722 reserve_space(*triangulation.levels[level + 1],
5723 used_cells + needed_cells,
5724 2,
5725 spacedim);
5726
5727 // reserve space for needed_cells new quads on the next
5728 // higher level
5729 reserve_space(triangulation.levels[level + 1]->cells,
5730 needed_cells,
5731 0);
5732 }
5733
5734 // now count the lines which were flagged for refinement
5737 line != triangulation.end_line();
5738 ++line)
5739 if (line->user_flag_set())
5740 {
5741 Assert(line->has_children() == false, ExcInternalError());
5742 n_lines_in_pairs += 2;
5743 needed_vertices += 1;
5744 }
5745 // reserve space for n_lines_in_pairs new lines. note, that
5746 // we can't reserve space for the single lines here as well,
5747 // as all the space reserved for lines in pairs would be
5748 // counted as unused and we would end up with too little space
5749 // to store all lines. memory reservation for n_single_lines
5750 // can only be done AFTER we refined the lines of the current
5751 // cells
5752 reserve_space(triangulation.faces->lines, n_lines_in_pairs, 0);
5753
5754 // add to needed vertices how many vertices are already in use
5755 needed_vertices += std::count(triangulation.vertices_used.begin(),
5756 triangulation.vertices_used.end(),
5757 true);
5758 // if we need more vertices: create them, if not: leave the
5759 // array as is, since shrinking is not really possible because
5760 // some of the vertices at the end may be in use
5761 if (needed_vertices > triangulation.vertices.size())
5762 {
5763 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
5764 triangulation.vertices_used.resize(needed_vertices, false);
5765 }
5766
5767
5768 // Do REFINEMENT on every level; exclude highest level as
5769 // above
5770
5771 // index of next unused vertex
5772 unsigned int next_unused_vertex = 0;
5773
5774 // first the refinement of lines. children are stored
5775 // pairwise
5776 {
5777 // only active objects can be refined further
5780 endl = triangulation.end_line();
5782 next_unused_line = triangulation.begin_raw_line();
5783
5784 for (; line != endl; ++line)
5785 if (line->user_flag_set())
5786 {
5787 // this line needs to be refined
5788
5789 // find the next unused vertex and set it
5790 // appropriately
5791 while (triangulation.vertices_used[next_unused_vertex] == true)
5792 ++next_unused_vertex;
5793 Assert(
5794 next_unused_vertex < triangulation.vertices.size(),
5795 ExcMessage(
5796 "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."));
5797 triangulation.vertices_used[next_unused_vertex] = true;
5798
5799 triangulation.vertices[next_unused_vertex] = line->center(true);
5800
5801 // now that we created the right point, make up the
5802 // two child lines. To this end, find a pair of
5803 // unused lines
5804 bool pair_found = false;
5805 (void)pair_found;
5806 for (; next_unused_line != endl; ++next_unused_line)
5807 if (!next_unused_line->used() &&
5808 !(++next_unused_line)->used())
5809 {
5810 // go back to the first of the two unused
5811 // lines
5812 --next_unused_line;
5813 pair_found = true;
5814 break;
5815 }
5816 Assert(pair_found, ExcInternalError());
5817
5818 // there are now two consecutive unused lines, such
5819 // that the children of a line will be consecutive.
5820 // then set the child pointer of the present line
5821 line->set_children(0, next_unused_line->index());
5822
5823 // set the two new lines
5825 children[2] = {next_unused_line, ++next_unused_line};
5826 // some tests; if any of the iterators should be
5827 // invalid, then already dereferencing will fail
5828 AssertIsNotUsed(children[0]);
5829 AssertIsNotUsed(children[1]);
5830
5831 children[0]->set_bounding_object_indices(
5832 {line->vertex_index(0), next_unused_vertex});
5833 children[1]->set_bounding_object_indices(
5834 {next_unused_vertex, line->vertex_index(1)});
5835
5836 children[0]->set_used_flag();
5837 children[1]->set_used_flag();
5838 children[0]->clear_children();
5839 children[1]->clear_children();
5840 children[0]->clear_user_data();
5841 children[1]->clear_user_data();
5842 children[0]->clear_user_flag();
5843 children[1]->clear_user_flag();
5844
5845
5846 children[0]->set_boundary_id_internal(line->boundary_id());
5847 children[1]->set_boundary_id_internal(line->boundary_id());
5848
5849 children[0]->set_manifold_id(line->manifold_id());
5850 children[1]->set_manifold_id(line->manifold_id());
5851
5852 // finally clear flag indicating the need for
5853 // refinement
5854 line->clear_user_flag();
5855 }
5856 }
5857
5858
5859 // Now set up the new cells
5860
5861 // reserve space for inner lines (can be stored as single
5862 // lines)
5863 reserve_space(triangulation.faces->lines, 0, n_single_lines);
5864
5866 cells_with_distorted_children;
5867
5868 // reset next_unused_line, as now also single empty places in
5869 // the vector can be used
5871 next_unused_line = triangulation.begin_raw_line();
5872
5873 for (int level = 0;
5874 level < static_cast<int>(triangulation.levels.size()) - 1;
5875 ++level)
5876 {
5878 next_unused_cell = triangulation.begin_raw(level + 1);
5879
5880 for (const auto &cell :
5881 triangulation.active_cell_iterators_on_level(level))
5882 if (cell->refine_flag_set())
5883 {
5884 // actually set up the children and update neighbor
5885 // information
5886 create_children(triangulation,
5887 next_unused_vertex,
5888 next_unused_line,
5889 next_unused_cell,
5890 cell);
5891
5892 if (check_for_distorted_cells &&
5893 has_distorted_children<dim, spacedim>(cell))
5894 cells_with_distorted_children.distorted_cells.push_back(
5895 cell);
5896 // inform all listeners that cell refinement is done
5897 triangulation.signals.post_refinement_on_cell(cell);
5898 }
5899 }
5900
5901 return cells_with_distorted_children;
5902 }
5903
5904
5905 template <int spacedim>
5908 const bool check_for_distorted_cells)
5909 {
5910 static const int dim = 3;
5911 static const unsigned int X = numbers::invalid_unsigned_int;
5912 using raw_line_iterator =
5914 using raw_quad_iterator =
5916
5917 Assert(spacedim == 3, ExcNotImplemented());
5918
5919 Assert(triangulation.vertices.size() ==
5920 triangulation.vertices_used.size(),
5922
5923 // Check whether a new level is needed. We have to check for
5924 // this on the highest level only
5925 for (const auto &cell : triangulation.active_cell_iterators_on_level(
5926 triangulation.levels.size() - 1))
5927 if (cell->refine_flag_set())
5928 {
5929 triangulation.levels.push_back(
5930 std::make_unique<
5932 break;
5933 }
5934
5935 // first clear user flags for quads and lines; we're going to
5936 // use them to flag which lines and quads need refinement
5937 triangulation.faces->quads.clear_user_data();
5938 triangulation.faces->lines.clear_user_flags();
5939 triangulation.faces->quads.clear_user_flags();
5940
5941 // check how much space is needed on every level. We need not
5942 // check the highest level since either
5943 // - on the highest level no cells are flagged for refinement
5944 // - there are, but prepare_refinement added another empty
5945 // level which then is the highest level
5946
5947 // variables to hold the number of newly to be created
5948 // vertices, lines and quads. as these are stored globally,
5949 // declare them outside the loop over al levels. we need lines
5950 // and quads in pairs for refinement of old ones and lines and
5951 // quads, that can be stored as single ones, as they are newly
5952 // created in the inside of an existing cell
5953 unsigned int needed_vertices = 0;
5954 unsigned int needed_lines_single = 0;
5955 unsigned int needed_quads_single = 0;
5956 unsigned int needed_lines_pair = 0;
5957 unsigned int needed_quads_pair = 0;
5958 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5959 {
5960 unsigned int new_cells = 0;
5961
5962 for (const auto &cell :
5963 triangulation.active_cell_iterators_on_level(level))
5964 if (cell->refine_flag_set())
5965 {
5966 // Only support isotropic refinement
5967 Assert(cell->refine_flag_set() ==
5970
5971 // Now count up how many new cells, faces, edges, and vertices
5972 // we will need to allocate to do this refinement.
5973 new_cells += cell->reference_cell().n_isotropic_children();
5974
5975 if (cell->reference_cell() == ReferenceCells::Hexahedron)
5976 {
5977 ++needed_vertices;
5978 needed_lines_single += 6;
5979 needed_quads_single += 12;
5980 }
5981 else if (cell->reference_cell() ==
5983 {
5984 needed_lines_single += 1;
5985 needed_quads_single += 8;
5986 }
5987 else
5988 {
5990 }
5991
5992 // Also check whether we have to refine any of the faces and
5993 // edges that bound this cell. They may of course already be
5994 // refined, so we only *mark* them for refinement by setting
5995 // the user flags
5996 for (const auto face : cell->face_indices())
5997 if (cell->face(face)->n_children() == 0)
5998 cell->face(face)->set_user_flag();
5999 else
6000 Assert(cell->face(face)->n_children() ==
6001 cell->reference_cell()
6002 .face_reference_cell(face)
6003 .n_isotropic_children(),
6005
6006 for (const auto line : cell->line_indices())
6007 if (cell->line(line)->has_children() == false)
6008 cell->line(line)->set_user_flag();
6009 else
6010 Assert(cell->line(line)->n_children() == 2,
6012 }
6013
6014 const unsigned int used_cells =
6015 std::count(triangulation.levels[level + 1]->cells.used.begin(),
6016 triangulation.levels[level + 1]->cells.used.end(),
6017 true);
6018
6019 reserve_space(*triangulation.levels[level + 1],
6020 used_cells + new_cells,
6021 3,
6022 spacedim);
6023
6024 reserve_space(triangulation.levels[level + 1]->cells, new_cells);
6025 }
6026
6027 // now count the quads and lines which were flagged for
6028 // refinement
6031 quad != triangulation.end_quad();
6032 ++quad)
6033 {
6034 if (quad->user_flag_set() == false)
6035 continue;
6036
6037 if (quad->reference_cell() == ReferenceCells::Quadrilateral)
6038 {
6039 needed_quads_pair += 4;
6040 needed_lines_pair += 4;
6041 needed_vertices += 1;
6042 }
6043 else if (quad->reference_cell() == ReferenceCells::Triangle)
6044 {
6045 needed_quads_pair += 4;
6046 needed_lines_single += 3;
6047 }
6048 else
6049 {
6051 }
6052 }
6053
6056 line != triangulation.end_line();
6057 ++line)
6058 {
6059 if (line->user_flag_set() == false)
6060 continue;
6061
6062 needed_lines_pair += 2;
6063 needed_vertices += 1;
6064 }
6065
6066 reserve_space(triangulation.faces->lines,
6067 needed_lines_pair,
6068 needed_lines_single);
6070 needed_quads_pair,
6071 needed_quads_single);
6072 reserve_space(triangulation.faces->quads,
6073 needed_quads_pair,
6074 needed_quads_single);
6075
6076
6077 // add to needed vertices how many vertices are already in use
6078 needed_vertices += std::count(triangulation.vertices_used.begin(),
6079 triangulation.vertices_used.end(),
6080 true);
6081
6082 if (needed_vertices > triangulation.vertices.size())
6083 {
6084 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
6085 triangulation.vertices_used.resize(needed_vertices, false);
6086 }
6087
6088 //-----------------------------------------
6089 // Before we start with the actual refinement, we do some
6090 // sanity checks if in debug mode. especially, we try to catch
6091 // the notorious problem with lines being twice refined,
6092 // i.e. there are cells adjacent at one line ("around the
6093 // edge", but not at a face), with two cells differing by more
6094 // than one refinement level
6095 //
6096 // this check is very simple to implement here, since we have
6097 // all lines flagged if they shall be refined
6098#ifdef DEBUG
6099 for (const auto &cell : triangulation.active_cell_iterators())
6100 if (!cell->refine_flag_set())
6101 for (unsigned int line_n = 0; line_n < cell->n_lines(); ++line_n)
6102 if (cell->line(line_n)->has_children())
6103 for (unsigned int c = 0; c < 2; ++c)
6104 Assert(cell->line(line_n)->child(c)->user_flag_set() == false,
6106#endif
6107
6108 unsigned int current_vertex = 0;
6109
6110 // helper function - find the next available vertex number and mark it
6111 // as used.
6112 auto get_next_unused_vertex = [](const unsigned int current_vertex,
6113 std::vector<bool> &vertices_used) {
6114 unsigned int next_vertex = current_vertex;
6115 while (next_vertex < vertices_used.size() &&
6116 vertices_used[next_vertex] == true)
6117 ++next_vertex;
6118 Assert(next_vertex < vertices_used.size(), ExcInternalError());
6119 vertices_used[next_vertex] = true;
6120
6121 return next_vertex;
6122 };
6123
6124 // LINES
6125 {
6128 endl = triangulation.end_line();
6129 raw_line_iterator next_unused_line = triangulation.begin_raw_line();
6130
6131 for (; line != endl; ++line)
6132 {
6133 if (line->user_flag_set() == false)
6134 continue;
6135
6136 next_unused_line =
6137 triangulation.faces->lines.template next_free_pair_object<1>(
6139 Assert(next_unused_line.state() == IteratorState::valid,
6141
6142 // now we found two consecutive unused lines, such
6143 // that the children of a line will be consecutive.
6144 // then set the child pointer of the present line
6145 line->set_children(0, next_unused_line->index());
6146
6147 const std::array<raw_line_iterator, 2> children{
6148 {next_unused_line, ++next_unused_line}};
6149
6150 AssertIsNotUsed(children[0]);
6151 AssertIsNotUsed(children[1]);
6152
6153 current_vertex =
6154 get_next_unused_vertex(current_vertex,
6155 triangulation.vertices_used);
6156 triangulation.vertices[current_vertex] = line->center(true);
6157
6158 children[0]->set_bounding_object_indices(
6159 {line->vertex_index(0), current_vertex});
6160 children[1]->set_bounding_object_indices(
6161 {current_vertex, line->vertex_index(1)});
6162
6163 const auto manifold_id = line->manifold_id();
6164 const auto boundary_id = line->boundary_id();
6165 for (const auto &child : children)
6166 {
6167 child->set_used_flag();
6168 child->clear_children();
6169 child->clear_user_data();
6170 child->clear_user_flag();
6171 child->set_boundary_id_internal(boundary_id);
6172 child->set_manifold_id(manifold_id);
6173 }
6174
6175 line->clear_user_flag();
6176 }
6177 }
6178
6179 // QUADS
6180 {
6182 quad = triangulation.begin_quad(),
6183 endq = triangulation.end_quad();
6184
6185 for (; quad != endq; ++quad)
6186 {
6187 if (quad->user_flag_set() == false)
6188 continue;
6189
6190 const auto reference_face_type = quad->reference_cell();
6191
6192 // 1) create new lines (property is set later)
6193 // maximum of 4 new lines (4 quadrilateral, 3 triangle)
6194 std::array<raw_line_iterator, 4> new_lines;
6195 if (reference_face_type == ReferenceCells::Quadrilateral)
6196 {
6197 for (unsigned int l = 0; l < 2; ++l)
6198 {
6199 auto next_unused_line =
6200 triangulation.faces->lines
6201 .template next_free_pair_object<1>(triangulation);
6202 new_lines[2 * l] = next_unused_line;
6203 new_lines[2 * l + 1] = ++next_unused_line;
6204 }
6205 }
6206 else if (reference_face_type == ReferenceCells::Triangle)
6207 {
6208 for (unsigned int l = 0; l < 3; ++l)
6209 new_lines[l] =
6210 triangulation.faces->lines
6211 .template next_free_single_object<1>(triangulation);
6212 }
6213 else
6214 {
6216 }
6217
6218 for (const unsigned int line : quad->line_indices())
6219 {
6220 AssertIsNotUsed(new_lines[line]);
6221 (void)line;
6222 }
6223
6224 // 2) create new quads (properties are set below). Both triangles
6225 // and quads are divided in four.
6226 std::array<raw_quad_iterator, 4> new_quads;
6227 for (unsigned int q = 0; q < 2; ++q)
6228 {
6229 auto next_unused_quad =
6230 triangulation.faces->quads
6231 .template next_free_pair_object<2>(triangulation);
6232
6233 new_quads[2 * q] = next_unused_quad;
6234 new_quads[2 * q + 1] = ++next_unused_quad;
6235
6236 quad->set_children(2 * q, new_quads[2 * q]->index());
6237 }
6238 quad->set_refinement_case(RefinementCase<2>::cut_xy);
6239
6240 for (const auto &quad : new_quads)
6241 {
6242 AssertIsNotUsed(quad);
6243 (void)quad;
6244 }
6245
6246 // 3) set vertex indices and set new vertex
6247
6248 // Maximum of 9 vertices per refined quad (9 for Quadrilateral, 6
6249 // for Triangle)
6250 std::array<unsigned int, 9> vertex_indices = {};
6251 unsigned int k = 0;
6252 for (const auto i : quad->vertex_indices())
6253 vertex_indices[k++] = quad->vertex_index(i);
6254
6255 for (const auto i : quad->line_indices())
6256 vertex_indices[k++] = quad->line(i)->child(0)->vertex_index(1);
6257
6258 if (reference_face_type == ReferenceCells::Quadrilateral)
6259 {
6260 current_vertex =
6261 get_next_unused_vertex(current_vertex,
6262 triangulation.vertices_used);
6263 vertex_indices[k++] = current_vertex;
6264
6265 triangulation.vertices[current_vertex] =
6266 quad->center(true, true);
6267 }
6268
6269 // 4) set new lines on quads and their properties
6270 std::array<raw_line_iterator, 12> lines;
6271 unsigned int n_lines = 0;
6272 for (unsigned int l = 0; l < quad->n_lines(); ++l)
6273 for (unsigned int c = 0; c < 2; ++c)
6274 {
6275 static constexpr ::ndarray<unsigned int, 2, 2> index =
6276 {{// child 0, line_orientation=false and true
6277 {{1, 0}},
6278 // child 1, line_orientation=false and true
6279 {{0, 1}}}};
6280
6281 lines[n_lines++] =
6282 quad->line(l)->child(index[c][quad->line_orientation(l)]);
6283 }
6284
6285 for (unsigned int l = 0; l < quad->n_lines(); ++l)
6286 lines[n_lines++] = new_lines[l];
6287
6288 std::array<int, 12> line_indices;
6289 for (unsigned int i = 0; i < n_lines; ++i)
6290 line_indices[i] = lines[i]->index();
6291
6292 static constexpr ::ndarray<unsigned int, 12, 2>
6293 line_vertices_quad{{{{0, 4}},
6294 {{4, 2}},
6295 {{1, 5}},
6296 {{5, 3}},
6297 {{0, 6}},
6298 {{6, 1}},
6299 {{2, 7}},
6300 {{7, 3}},
6301 {{6, 8}},
6302 {{8, 7}},
6303 {{4, 8}},
6304 {{8, 5}}}};
6305
6306 static constexpr ::ndarray<unsigned int, 4, 4>
6307 quad_lines_quad{{{{0, 8, 4, 10}},
6308 {{8, 2, 5, 11}},
6309 {{1, 9, 10, 6}},
6310 {{9, 3, 11, 7}}}};
6311
6312 static constexpr ::ndarray<unsigned int, 12, 2>
6313 line_vertices_tri{{{{0, 3}},
6314 {{3, 1}},
6315 {{1, 4}},
6316 {{4, 2}},
6317 {{2, 5}},
6318 {{5, 0}},
6319 {{3, 4}},
6320 {{4, 5}},
6321 {{3, 5}},
6322 {{X, X}},
6323 {{X, X}},
6324 {{X, X}}}};
6325
6326 static constexpr ::ndarray<unsigned int, 4, 4>
6327 quad_lines_tri{{{{0, 8, 5, X}},
6328 {{1, 2, 6, X}},
6329 {{7, 3, 4, X}},
6330 {{6, 7, 8, X}}}};
6331
6332 static constexpr ::ndarray<unsigned int, 4, 4, 2>
6333 quad_line_vertices_tri{
6334 {{{{{0, 3}}, {{3, 5}}, {{5, 0}}, {{X, X}}}},
6335 {{{{3, 1}}, {{1, 4}}, {{4, 3}}, {{X, X}}}},
6336 {{{{5, 4}}, {{4, 2}}, {{2, 5}}, {{X, X}}}},
6337 {{{{3, 4}}, {{4, 5}}, {{5, 3}}, {{X, X}}}}}};
6338
6339 const auto &line_vertices =
6340 (reference_face_type == ReferenceCells::Quadrilateral) ?
6341 line_vertices_quad :
6342 line_vertices_tri;
6343 const auto &quad_lines =
6344 (reference_face_type == ReferenceCells::Quadrilateral) ?
6345 quad_lines_quad :
6346 quad_lines_tri;
6347
6348 for (unsigned int i = 0, j = 2 * quad->n_lines();
6349 i < quad->n_lines();
6350 ++i, ++j)
6351 {
6352 auto &new_line = new_lines[i];
6353 new_line->set_bounding_object_indices(
6354 {vertex_indices[line_vertices[j][0]],
6355 vertex_indices[line_vertices[j][1]]});
6356 new_line->set_used_flag();
6357 new_line->clear_user_flag();
6358 new_line->clear_user_data();
6359 new_line->clear_children();
6360 new_line->set_boundary_id_internal(quad->boundary_id());
6361 new_line->set_manifold_id(quad->manifold_id());
6362 }
6363
6364 // 5) set properties of quads
6365 for (unsigned int i = 0; i < new_quads.size(); ++i)
6366 {
6367 auto &new_quad = new_quads[i];
6368
6369 // TODO: we assume here that all children have the same type
6370 // as the parent
6371 triangulation.faces->set_quad_type(new_quad->index(),
6372 reference_face_type);
6373
6374 if (reference_face_type == ReferenceCells::Triangle)
6375 new_quad->set_bounding_object_indices(
6376 {line_indices[quad_lines[i][0]],
6377 line_indices[quad_lines[i][1]],
6378 line_indices[quad_lines[i][2]]});
6379 else if (reference_face_type == ReferenceCells::Quadrilateral)
6380 new_quad->set_bounding_object_indices(
6381 {line_indices[quad_lines[i][0]],
6382 line_indices[quad_lines[i][1]],
6383 line_indices[quad_lines[i][2]],
6384 line_indices[quad_lines[i][3]]});
6385 else
6387
6388 new_quad->set_used_flag();
6389 new_quad->clear_user_flag();
6390 new_quad->clear_user_data();
6391 new_quad->clear_children();
6392 new_quad->set_boundary_id_internal(quad->boundary_id());
6393 new_quad->set_manifold_id(quad->manifold_id());
6394
6395#ifdef DEBUG
6396 std::set<unsigned int> s;
6397#endif
6398
6399 // ... and fix orientation of lines of face for triangles,
6400 // using an expensive algorithm, quadrilaterals are treated
6401 // a few lines below by a cheaper algorithm
6402 if (reference_face_type == ReferenceCells::Triangle)
6403 {
6404 for (const auto f : new_quad->line_indices())
6405 {
6406 const std::array<unsigned int, 2> vertices_0 = {
6407 {lines[quad_lines[i][f]]->vertex_index(0),
6408 lines[quad_lines[i][f]]->vertex_index(1)}};
6409
6410 const std::array<unsigned int, 2> vertices_1 = {
6411 {vertex_indices[quad_line_vertices_tri[i][f][0]],
6412 vertex_indices[quad_line_vertices_tri[i][f][1]]}};
6413
6414 const auto orientation =
6416 make_array_view(vertices_0),
6417 make_array_view(vertices_1));
6418
6419#ifdef DEBUG
6420 for (const auto i : vertices_0)
6421 s.insert(i);
6422 for (const auto i : vertices_1)
6423 s.insert(i);
6424#endif
6425
6426 new_quad->set_line_orientation(f, orientation);
6427 }
6428#ifdef DEBUG
6429 AssertDimension(s.size(), 3);
6430#endif
6431 }
6432 }
6433
6434 // fix orientation of lines of faces for quadrilaterals with
6435 // cheap algorithm
6436 if (reference_face_type == ReferenceCells::Quadrilateral)
6437 {
6438 static constexpr ::ndarray<unsigned int, 4, 2>
6439 quad_child_boundary_lines{
6440 {{{0, 2}}, {{1, 3}}, {{0, 1}}, {{2, 3}}}};
6441
6442 for (unsigned int i = 0; i < 4; ++i)
6443 for (unsigned int j = 0; j < 2; ++j)
6444 new_quads[quad_child_boundary_lines[i][j]]
6445 ->set_line_orientation(i, quad->line_orientation(i));
6446 }
6447
6448 quad->clear_user_flag();
6449 }
6450 }
6451
6453 cells_with_distorted_children;
6454
6457 for (unsigned int level = 0; level != triangulation.levels.size() - 1;
6458 ++level)
6459 {
6461 next_unused_hex = triangulation.begin_raw_hex(level + 1);
6462 Assert(hex == triangulation.end() ||
6463 hex->level() >= static_cast<int>(level),
6465
6466 for (; hex != triangulation.end() &&
6467 hex->level() == static_cast<int>(level);
6468 ++hex)
6469 {
6470 if (hex->refine_flag_set() ==
6472 continue;
6473
6474 const auto &reference_cell_type = hex->reference_cell();
6475
6476 const RefinementCase<dim> ref_case = hex->refine_flag_set();
6477 hex->clear_refine_flag();
6478 hex->set_refinement_case(ref_case);
6479
6480 unsigned int n_new_lines = 0;
6481 unsigned int n_new_quads = 0;
6482 unsigned int n_new_hexes = 0;
6483
6484 if (reference_cell_type == ReferenceCells::Hexahedron)
6485 {
6486 n_new_lines = 6;
6487 n_new_quads = 12;
6488 n_new_hexes = 8;
6489 }
6490 else if (reference_cell_type == ReferenceCells::Tetrahedron)
6491 {
6492 n_new_lines = 1;
6493 n_new_quads = 8;
6494 n_new_hexes = 8;
6495 }
6496 else
6498
6499 std::array<raw_line_iterator, 6> new_lines;
6500 for (unsigned int i = 0; i < n_new_lines; ++i)
6501 {
6502 new_lines[i] =
6503 triangulation.faces->lines
6504 .template next_free_single_object<1>(triangulation);
6505
6506 AssertIsNotUsed(new_lines[i]);
6507 new_lines[i]->set_used_flag();
6508 new_lines[i]->clear_user_flag();
6509 new_lines[i]->clear_user_data();
6510 new_lines[i]->clear_children();
6511 new_lines[i]->set_boundary_id_internal(
6513 new_lines[i]->set_manifold_id(hex->manifold_id());
6514 }
6515
6516 std::array<raw_quad_iterator, 12> new_quads;
6517 for (unsigned int i = 0; i < n_new_quads; ++i)
6518 {
6519 new_quads[i] =
6520 triangulation.faces->quads
6521 .template next_free_single_object<2>(triangulation);
6522
6523 auto &new_quad = new_quads[i];
6524
6525 // TODO: faces of children have the same type as the faces
6526 // of the parent
6527 triangulation.faces->set_quad_type(
6528 new_quad->index(),
6529 reference_cell_type.face_reference_cell(0));
6530
6531 AssertIsNotUsed(new_quad);
6532 new_quad->set_used_flag();
6533 new_quad->clear_user_flag();
6534 new_quad->clear_user_data();
6535 new_quad->clear_children();
6536 new_quad->set_boundary_id_internal(
6538 new_quad->set_manifold_id(hex->manifold_id());
6539 for (const auto j : new_quads[i]->line_indices())
6540 new_quad->set_line_orientation(j, true);
6541 }
6542
6543 // we always get 8 children per refined cell
6544 std::array<
6546 8>
6547 new_hexes;
6548 {
6549 for (unsigned int i = 0; i < n_new_hexes; ++i)
6550 {
6551 if (i % 2 == 0)
6552 next_unused_hex =
6553 triangulation.levels[level + 1]->cells.next_free_hex(
6554 triangulation, level + 1);
6555 else
6556 ++next_unused_hex;
6557
6558 new_hexes[i] = next_unused_hex;
6559
6560 auto &new_hex = new_hexes[i];
6561
6562 // children have the same type as the parent
6563 triangulation.levels[new_hex->level()]
6564 ->reference_cell[new_hex->index()] =
6565 reference_cell_type;
6566
6567 AssertIsNotUsed(new_hex);
6568 new_hex->set_used_flag();
6569 new_hex->clear_user_flag();
6570 new_hex->clear_user_data();
6571 new_hex->clear_children();
6572 new_hex->set_material_id(hex->material_id());
6573 new_hex->set_manifold_id(hex->manifold_id());
6574 new_hex->set_subdomain_id(hex->subdomain_id());
6575
6576 if (i % 2)
6577 new_hex->set_parent(hex->index());
6578
6579 // set the orientation flag to its default state for all
6580 // faces initially. later on go the other way round and
6581 // reset faces that are at the boundary of the mother cube
6582 for (const auto f : new_hex->face_indices())
6583 new_hex->set_combined_face_orientation(
6584 f,
6586 }
6587 for (unsigned int i = 0; i < n_new_hexes / 2; ++i)
6588 hex->set_children(2 * i, new_hexes[2 * i]->index());
6589 }
6590
6591 {
6592 // load vertex indices
6593 std::array<unsigned int, 27> vertex_indices = {};
6594
6595 {
6596 unsigned int k = 0;
6597
6598 // avoid a compiler warning by fixing the max number of
6599 // loop iterations to 8
6600 const unsigned int n_vertices =
6601 std::min(hex->n_vertices(), 8u);
6602 for (unsigned int i = 0; i < n_vertices; ++i)
6603 vertex_indices[k++] = hex->vertex_index(i);
6604
6605 const std::array<unsigned int, 12> line_indices =
6606 TriaAccessorImplementation::Implementation::
6607 get_line_indices_of_cell(*hex);
6608
6609 // For the tetrahedron the parent consists of the vertices
6610 // 0,1,2,3, the new vertices 4-9 are defined as the
6611 // midpoints of the edges: 4 -> (0,1), 5 -> (1,2), 6 ->
6612 // (2,0), 7 -> (0,3), 8 -> (1,3), 9 -> (2,3).
6613 // Order is defined by the reference cell, see
6614 // https://dealii.org/developer/doxygen/deal.II/group__simplex.html#simplex_reference_cells.
6615
6616 // Avoid a compiler warning by fixing the max number of loop
6617 // iterations to 12
6618 const unsigned int n_lines = std::min(hex->n_lines(), 12u);
6619 for (unsigned int l = 0; l < n_lines; ++l)
6620 {
6621 raw_line_iterator line(&triangulation,
6622 0,
6623 line_indices[l]);
6624 vertex_indices[k++] = line->child(0)->vertex_index(1);
6625 }
6626
6627 if (reference_cell_type == ReferenceCells::Hexahedron)
6628 {
6629 for (const unsigned int i : hex->face_indices())
6630 vertex_indices[k++] =
6631 hex->face(i)->child(0)->vertex_index(3);
6632
6633 // Set single new vertex in the center
6634 current_vertex =
6635 get_next_unused_vertex(current_vertex,
6636 triangulation.vertices_used);
6637 vertex_indices[k++] = current_vertex;
6638
6639 triangulation.vertices[current_vertex] =
6640 hex->center(true, true);
6641 }
6642 }
6643
6644 unsigned int chosen_line_tetrahedron = 0;
6645 // set up new lines
6646 if (reference_cell_type == ReferenceCells::Hexahedron)
6647 {
6648 static constexpr ::ndarray<unsigned int, 6, 2>
6649 new_line_vertices = {{{{22, 26}},
6650 {{26, 23}},
6651 {{20, 26}},
6652 {{26, 21}},
6653 {{24, 26}},
6654 {{26, 25}}}};
6655 for (unsigned int i = 0; i < n_new_lines; ++i)
6656 new_lines[i]->set_bounding_object_indices(
6657 {vertex_indices[new_line_vertices[i][0]],
6658 vertex_indices[new_line_vertices[i][1]]});
6659 }
6660 else if (reference_cell_type == ReferenceCells::Tetrahedron)
6661 {
6662 // in the tetrahedron case, we have the three
6663 // possibilities (6,8), (5,7), (4,9) -> pick the
6664 // shortest line to guarantee the best possible aspect
6665 // ratios
6666 static constexpr ::ndarray<unsigned int, 3, 2>
6667 new_line_vertices = {{{{6, 8}}, {{5, 7}}, {{4, 9}}}};
6668
6669 const auto &vertices = triangulation.get_vertices();
6670 double min_distance =
6671 std::numeric_limits<double>::infinity();
6672 for (unsigned int i = 0; i < new_line_vertices.size();
6673 ++i)
6674 {
6675 const double current_distance =
6676 vertices[vertex_indices[new_line_vertices[i][0]]]
6677 .distance(
6678 vertices
6679 [vertex_indices[new_line_vertices[i][1]]]);
6680 if (current_distance < min_distance)
6681 {
6682 chosen_line_tetrahedron = i;
6683 min_distance = current_distance;
6684 }
6685 }
6686
6687 new_lines[0]->set_bounding_object_indices(
6689 [new_line_vertices[chosen_line_tetrahedron][0]],
6691 [new_line_vertices[chosen_line_tetrahedron][1]]});
6692 }
6693
6694 // set up new quads
6695 {
6696 boost::container::small_vector<raw_line_iterator, 30>
6697 relevant_lines;
6698
6699 if (reference_cell_type == ReferenceCells::Hexahedron)
6700 {
6701 relevant_lines.resize(30);
6702 for (unsigned int f = 0, k = 0; f < 6; ++f)
6703 for (unsigned int c = 0; c < 4; ++c, ++k)
6704 {
6705 static constexpr ::
6706 ndarray<unsigned int, 4, 2>
6707 temp = {
6708 {{{0, 1}}, {{3, 0}}, {{0, 3}}, {{3, 2}}}};
6709
6710 relevant_lines[k] =
6711 hex->face(f)
6712 ->isotropic_child(
6714 standard_to_real_face_vertex(
6715 temp[c][0],
6716 hex->face_orientation(f),
6717 hex->face_flip(f),
6718 hex->face_rotation(f)))
6719 ->line(GeometryInfo<dim>::
6720 standard_to_real_face_line(
6721 temp[c][1],
6722 hex->face_orientation(f),
6723 hex->face_flip(f),
6724 hex->face_rotation(f)));
6725 }
6726
6727 for (unsigned int i = 0, k = 24; i < 6; ++i, ++k)
6728 relevant_lines[k] = new_lines[i];
6729 }
6730 else if (reference_cell_type == ReferenceCells::Tetrahedron)
6731 {
6732 // The order of the lines is defined by the ordering
6733 // of the faces of the reference cell and the ordering
6734 // of the lines within a face.
6735 // Each face is split into 4 child triangles, the
6736 // relevant lines are defined by the vertices of the
6737 // center triangles: 0 -> (4,5), 1 -> (5,6), 2 -> (4,6),
6738 // 3 -> (4,7), 4 -> (7,8), 5 -> (4,8), 6 -> (6,9), 7 ->
6739 // (9,7), 8 -> (6,7), 9 -> (5,8), 10 -> (8,9), 11 ->
6740 // (5,9), Line 12 is determined by
6741 // chosen_line_tetrahedron i.e. (6,8), (5,7) or (4,9)
6742
6743 relevant_lines.resize(13);
6744
6745 unsigned int k = 0;
6746 for (unsigned int f = 0; f < 4; ++f)
6747 for (unsigned int l = 0; l < 3; ++l, ++k)
6748 {
6749 // TODO: add comment
6750 static const std::
6751 array<std::array<unsigned int, 3>, 6>
6752 table = {{{{1, 0, 2}}, // 0
6753 {{0, 1, 2}},
6754 {{0, 2, 1}}, // 2
6755 {{1, 2, 0}},
6756 {{2, 1, 0}}, // 4
6757 {{2, 0, 1}}}};
6758
6759 relevant_lines[k] =
6760 hex->face(f)
6761 ->child(3 /*center triangle*/)
6762 ->line(
6763 table[triangulation.levels[hex->level()]
6764 ->face_orientations
6765 .get_combined_orientation(
6766 hex->index() * GeometryInfo<dim>::
6767 faces_per_cell +
6768 f)][l]);
6769 }
6770
6771 relevant_lines[k++] = new_lines[0];
6772 AssertDimension(k, 13);
6773 }
6774 else
6776
6777 boost::container::small_vector<unsigned int, 30>
6778 relevant_line_indices(relevant_lines.size());
6779 for (unsigned int i = 0; i < relevant_line_indices.size();
6780 ++i)
6781 relevant_line_indices[i] = relevant_lines[i]->index();
6782
6783 static constexpr ::ndarray<unsigned int, 12, 4>
6784 new_quad_lines_hex = {{{{10, 28, 16, 24}},
6785 {{28, 14, 17, 25}},
6786 {{11, 29, 24, 20}},
6787 {{29, 15, 25, 21}},
6788 {{18, 26, 0, 28}},
6789 {{26, 22, 1, 29}},
6790 {{19, 27, 28, 4}},
6791 {{27, 23, 29, 5}},
6792 {{2, 24, 8, 26}},
6793 {{24, 6, 9, 27}},
6794 {{3, 25, 26, 12}},
6795 {{25, 7, 27, 13}}}};
6796
6797 // It is easierst to start at table cell_vertices_tet,
6798 // there the vertices are listed which build up the
6799 // 8 child tets. To build the child tets, 8 new faces are
6800 // needed. The the vertices, which define the lines of these
6801 // new faces are listed in table_tet. Now only the
6802 // corresponding index of the lines and quads have to be
6803 // listed in new_quad_lines_tet and cell_quads_tet.
6804
6805 // The first 4 define the faces which cut off the
6806 // parent tetrahedron at the edges. the numbers are the
6807 // index of the relevant_lines defined above the last 4
6808 // faces cut apart the remaining octahedron, such that all
6809 // of these contain line number 12. the ordering of the
6810 // faces is arbitrary, the ordering within the faces has to
6811 // follow the righthand convention for triangles
6812 static constexpr ::ndarray<unsigned int, 3, 12, 4>
6813 new_quad_lines_tet = {{// new line is (6,8)
6814 {{{{2, 3, 8, X}},
6815 {{0, 9, 5, X}},
6816 {{1, 6, 11, X}},
6817 {{4, 10, 7, X}},
6818 {{2, 12, 5, X}},
6819 {{1, 9, 12, X}},
6820 {{4, 8, 12, X}},
6821 {{6, 12, 10, X}},
6822 {{X, X, X, X}},
6823 {{X, X, X, X}},
6824 {{X, X, X, X}},
6825 {{X, X, X, X}}}},
6826 // new line is (5,7)
6827 {{{{2, 3, 8, X}},
6828 {{0, 9, 5, X}},
6829 {{1, 6, 11, X}},
6830 {{4, 10, 7, X}},
6831 {{0, 3, 12, X}},
6832 {{1, 12, 8, X}},
6833 {{4, 12, 9, X}},
6834 {{7, 11, 12, X}},
6835 {{X, X, X, X}},
6836 {{X, X, X, X}},
6837 {{X, X, X, X}},
6838 {{X, X, X, X}}}},
6839 // new line is (4,9)
6840 {{{{2, 3, 8, X}},
6841 {{0, 9, 5, X}},
6842 {{1, 6, 11, X}},
6843 {{4, 10, 7, X}},
6844 {{0, 12, 11, X}},
6845 {{2, 6, 12, X}},
6846 {{3, 12, 7, X}},
6847 {{5, 10, 12, X}},
6848 {{X, X, X, X}},
6849 {{X, X, X, X}},
6850 {{X, X, X, X}},
6851 {{X, X, X, X}}}}}};
6852
6853 static constexpr ::ndarray<unsigned int, 12, 4, 2>
6854 table_hex = {
6855 {{{{{10, 22}}, {{24, 26}}, {{10, 24}}, {{22, 26}}}},
6856 {{{{24, 26}}, {{11, 23}}, {{24, 11}}, {{26, 23}}}},
6857 {{{{22, 14}}, {{26, 25}}, {{22, 26}}, {{14, 25}}}},
6858 {{{{26, 25}}, {{23, 15}}, {{26, 23}}, {{25, 15}}}},
6859 {{{{8, 24}}, {{20, 26}}, {{8, 20}}, {{24, 26}}}},
6860 {{{{20, 26}}, {{12, 25}}, {{20, 12}}, {{26, 25}}}},
6861 {{{{24, 9}}, {{26, 21}}, {{24, 26}}, {{9, 21}}}},
6862 {{{{26, 21}}, {{25, 13}}, {{26, 25}}, {{21, 13}}}},
6863 {{{{16, 20}}, {{22, 26}}, {{16, 22}}, {{20, 26}}}},
6864 {{{{22, 26}}, {{17, 21}}, {{22, 17}}, {{26, 21}}}},
6865 {{{{20, 18}}, {{26, 23}}, {{20, 26}}, {{18, 23}}}},
6866 {{{{26, 23}}, {{21, 19}}, {{26, 21}}, {{23, 19}}}}}};
6867
6868 // The table defines the vertices of the lines above
6869 // see relevant_lines for mapping between line indices and
6870 // vertex numbering
6871 static constexpr ::ndarray<unsigned int, 3, 12, 4, 2>
6872 table_tet = {
6873 {// new line is (6, 8)
6874 {{{{{{6, 4}}, {{4, 7}}, {{7, 6}}, {{X, X}}}},
6875 {{{{4, 5}}, {{5, 8}}, {{8, 4}}, {{X, X}}}},
6876 {{{{5, 6}}, {{6, 9}}, {{9, 5}}, {{X, X}}}},
6877 {{{{7, 8}}, {{8, 9}}, {{9, 7}}, {{X, X}}}},
6878 {{{{4, 6}}, {{6, 8}}, {{8, 4}}, {{X, X}}}},
6879 {{{{6, 5}}, {{5, 8}}, {{8, 6}}, {{X, X}}}},
6880 {{{{8, 7}}, {{7, 6}}, {{6, 8}}, {{X, X}}}},
6881 {{{{9, 6}}, {{6, 8}}, {{8, 9}}, {{X, X}}}},
6882 {{{{X, X}}, {{X, X}}, {{X, X}}, {{X, X}}}},
6883 {{{{X, X}}, {{X, X}}, {{X, X}}, {{X, X}}}},
6884 {{{{X, X}}, {{X, X}}, {{X, X}}, {{X, X}}}},
6885 {{{{X, X}}, {{X, X}}, {{X, X}}, {{X, X}}}}}},
6886 // new line is (5, 7)
6887 {{{{{{6, 4}}, {{4, 7}}, {{7, 6}}, {{X, X}}}},
6888 {{{{4, 5}}, {{5, 8}}, {{8, 4}}, {{X, X}}}},
6889 {{{{5, 6}}, {{6, 9}}, {{9, 5}}, {{X, X}}}},
6890 {{{{7, 8}}, {{8, 9}}, {{9, 7}}, {{X, X}}}},
6891 {{{{5, 4}}, {{4, 7}}, {{7, 5}}, {{X, X}}}},
6892 {{{{6, 5}}, {{5, 7}}, {{7, 6}}, {{X, X}}}},
6893 {{{{8, 7}}, {{7, 5}}, {{5, 8}}, {{X, X}}}},
6894 {{{{7, 9}}, {{9, 5}}, {{5, 7}}, {{X, X}}}},
6895 {{{{X, X}}, {{X, X}}, {{X, X}}, {{X, X}}}},
6896 {{{{X, X}}, {{X, X}}, {{X, X}}, {{X, X}}}},
6897 {{{{X, X}}, {{X, X}}, {{X, X}}, {{X, X}}}},
6898 {{{{X, X}}, {{X, X}}, {{X, X}}, {{X, X}}}}}},
6899 // new line is (4, 9)
6900 {{{{{{6, 4}}, {{4, 7}}, {{7, 6}}, {{X, X}}}},
6901 {{{{4, 5}}, {{5, 8}}, {{8, 4}}, {{X, X}}}},
6902 {{{{5, 6}}, {{6, 9}}, {{9, 5}}, {{X, X}}}},
6903 {{{{7, 8}}, {{8, 9}}, {{9, 7}}, {{X, X}}}},
6904 {{{{5, 4}}, {{4, 9}}, {{9, 5}}, {{X, X}}}},
6905 {{{{4, 6}}, {{6, 9}}, {{9, 4}}, {{X, X}}}},
6906 {{{{7, 4}}, {{4, 9}}, {{9, 7}}, {{X, X}}}},
6907 {{{{4, 8}}, {{8, 9}}, {{9, 4}}, {{X, X}}}},
6908 {{{{X, X}}, {{X, X}}, {{X, X}}, {{X, X}}}},
6909 {{{{X, X}}, {{X, X}}, {{X, X}}, {{X, X}}}},
6910 {{{{X, X}}, {{X, X}}, {{X, X}}, {{X, X}}}},
6911 {{{{X, X}}, {{X, X}}, {{X, X}}, {{X, X}}}}}}}};
6912
6913 const auto &new_quad_lines =
6914 (reference_cell_type == ReferenceCells::Hexahedron) ?
6915 new_quad_lines_hex :
6916 new_quad_lines_tet[chosen_line_tetrahedron];
6917
6918 const auto &table =
6919 (reference_cell_type == ReferenceCells::Hexahedron) ?
6920 table_hex :
6921 table_tet[chosen_line_tetrahedron];
6922
6923 static constexpr ::ndarray<unsigned int, 4, 2>
6924 representative_lines{
6925 {{{0, 2}}, {{2, 0}}, {{3, 3}}, {{1, 1}}}};
6926
6927 for (unsigned int q = 0; q < n_new_quads; ++q)
6928 {
6929 auto &new_quad = new_quads[q];
6930
6931 if (new_quad->n_lines() == 3)
6932 new_quad->set_bounding_object_indices(
6933 {relevant_line_indices[new_quad_lines[q][0]],
6934 relevant_line_indices[new_quad_lines[q][1]],
6935 relevant_line_indices[new_quad_lines[q][2]]});
6936 else if (new_quad->n_lines() == 4)
6937 new_quad->set_bounding_object_indices(
6938 {relevant_line_indices[new_quad_lines[q][0]],
6939 relevant_line_indices[new_quad_lines[q][1]],
6940 relevant_line_indices[new_quad_lines[q][2]],
6941 relevant_line_indices[new_quad_lines[q][3]]});
6942 else
6944
6945 // On hexes, we must only determine a single line
6946 // according to the representative_lines array above
6947 // (this saves expensive operations), for tets we do
6948 // all lines manually
6949 const unsigned int n_compute_lines =
6950 reference_cell_type == ReferenceCells::Hexahedron ?
6951 1 :
6952 new_quad->n_lines();
6953 for (unsigned int line = 0; line < n_compute_lines;
6954 ++line)
6955 {
6956 const unsigned int l =
6957 (reference_cell_type ==
6959 representative_lines[q % 4][0] :
6960 line;
6961
6962 const std::array<unsigned int, 2> vertices_0 = {
6963 {relevant_lines[new_quad_lines[q][l]]
6964 ->vertex_index(0),
6965 relevant_lines[new_quad_lines[q][l]]
6966 ->vertex_index(1)}};
6967
6968 const std::array<unsigned int, 2> vertices_1 = {
6969 {vertex_indices[table[q][l][0]],
6970 vertex_indices[table[q][l][1]]}};
6971
6972 const auto orientation =
6974 make_array_view(vertices_0),
6975 make_array_view(vertices_1));
6976
6977 new_quad->set_line_orientation(l, orientation);
6978
6979 // on a hex, inject the status of the current line
6980 // also to the line on the other quad along the
6981 // same direction
6982 if (reference_cell_type ==
6984 new_quads[representative_lines[q % 4][1] + q -
6985 (q % 4)]
6986 ->set_line_orientation(l, orientation);
6987 }
6988 }
6989 }
6990
6991 // set up new hex
6992 {
6993 std::array<int, 36> quad_indices;
6994
6995 if (reference_cell_type == ReferenceCells::Hexahedron)
6996 {
6997 for (unsigned int i = 0; i < n_new_quads; ++i)
6998 quad_indices[i] = new_quads[i]->index();
6999
7000 for (unsigned int f = 0, k = n_new_quads; f < 6; ++f)
7001 for (unsigned int c = 0; c < 4; ++c, ++k)
7002 quad_indices[k] =
7003 hex->face(f)->isotropic_child_index(
7005 c,
7006 hex->face_orientation(f),
7007 hex->face_flip(f),
7008 hex->face_rotation(f)));
7009 }
7010 else if (reference_cell_type == ReferenceCells::Tetrahedron)
7011 {
7012 // list of the indices of the surfaces which define the
7013 // 8 new tets. the indices 0-7 are the new quads defined
7014 // above (so 0-3 cut off the corners and 4-7 separate
7015 // the remaining octahedral), the indices between 8-11
7016 // are the children of the first face, from 12-15 of the
7017 // second, etc.
7018 for (unsigned int i = 0; i < n_new_quads; ++i)
7019 quad_indices[i] = new_quads[i]->index();
7020
7021 for (unsigned int f = 0, k = n_new_quads; f < 4; ++f)
7022 for (unsigned int c = 0; c < 4; ++c, ++k)
7023 {
7024 quad_indices[k] = hex->face(f)->child_index(
7025 (c == 3) ?
7026 3 :
7027 reference_cell_type
7028 .standard_to_real_face_vertex(
7029 c,
7030 f,
7031 triangulation.levels[hex->level()]
7032 ->face_orientations
7033 .get_combined_orientation(
7034 hex->index() *
7036 f)));
7037 }
7038 }
7039 else
7040 {
7042 }
7043
7044 static constexpr ::ndarray<unsigned int, 8, 6>
7045 cell_quads_hex = {{
7046 {{12, 0, 20, 4, 28, 8}}, // bottom children
7047 {{0, 16, 22, 6, 29, 9}}, //
7048 {{13, 1, 4, 24, 30, 10}}, //
7049 {{1, 17, 6, 26, 31, 11}}, //
7050 {{14, 2, 21, 5, 8, 32}}, // top children
7051 {{2, 18, 23, 7, 9, 33}}, //
7052 {{15, 3, 5, 25, 10, 34}}, //
7053 {{3, 19, 7, 27, 11, 35}} //
7054 }};
7055
7056 // indices of the faces which define the new tets
7057 // the ordering of the tets is arbitrary
7058 // the first 4 determine the tets cutting of the corners
7059 // the last 4 are ordered after their appearance in the
7060 // faces.
7061 // the ordering within the faces is determined by
7062 // convention for the tetrahedron unit cell, see
7063 // cell_vertices_tet below
7064 static constexpr ::ndarray<unsigned int, 3, 8, 6>
7065 cell_quads_tet = {{// new line is (6, 8)
7066 {{{{8, 13, 16, 0, X, X}},
7067 {{9, 12, 1, 21, X, X}},
7068 {{10, 2, 17, 20, X, X}},
7069 {{3, 14, 18, 22, X, X}},
7070 {{11, 1, 4, 5, X, X}},
7071 {{15, 0, 4, 6, X, X}},
7072 {{19, 7, 6, 3, X, X}},
7073 {{23, 5, 2, 7, X, X}}}},
7074 // new line is (5, 7)
7075 {{
7076 {{8, 13, 16, 0, X, X}},
7077 {{9, 12, 1, 21, X, X}},
7078 {{10, 2, 17, 20, X, X}},
7079 {{3, 14, 18, 22, X, X}},
7080 {{11, 4, 0, 5, X, X}},
7081 {{15, 4, 1, 6, X, X}},
7082 {{19, 2, 5, 7, X, X}},
7083 {{23, 6, 7, 3, X, X}},
7084 }},
7085 // new line is (4, 9)
7086 {{
7087 {{8, 13, 16, 0, X, X}},
7088 {{9, 12, 1, 21, X, X}},
7089 {{10, 2, 17, 20, X, X}},
7090 {{3, 14, 18, 22, X, X}},
7091 {{11, 4, 5, 2, X, X}},
7092 {{15, 6, 7, 3, X, X}},
7093 {{19, 5, 0, 6, X, X}},
7094 {{23, 1, 4, 7, X, X}},
7095 }}}};
7096
7097 // the 4 faces of the reference tet are defined by 3
7098 // vertices each and follow the order of the unit cell
7099 static constexpr ::ndarray<unsigned int, 4, 3>
7100 reference_cell_face_vertices = {
7101 {{{0, 1, 2}}, {{1, 0, 3}}, {{0, 2, 3}}, {{2, 1, 3}}}};
7102
7103 // the 8 child tets are each defined by 4 vertices
7104 // the ordering of the tets has to be consistent with above
7105 // the ordering within the tets is given by the reference
7106 // tet i.e. looking at the fifth line the first 3 vertices
7107 // are given by face 11, the last vertex is the remaining of
7108 // the tet
7109 static constexpr ::ndarray<unsigned int, 3, 8, 4>
7110 cell_vertices_tet = {{// new line is (6,8)
7111 {{{{0, 4, 6, 7}},
7112 {{4, 1, 5, 8}},
7113 {{6, 5, 2, 9}},
7114 {{7, 8, 9, 3}},
7115 {{4, 5, 6, 8}},
7116 {{4, 7, 8, 6}},
7117 {{6, 9, 7, 8}},
7118 {{5, 8, 9, 6}}}},
7119 // new line is (5,7)
7120 {{{{0, 4, 6, 7}},
7121 {{4, 1, 5, 8}},
7122 {{6, 5, 2, 9}},
7123 {{7, 8, 9, 3}},
7124 {{4, 5, 6, 7}},
7125 {{4, 7, 8, 5}},
7126 {{6, 9, 7, 5}},
7127 {{5, 8, 9, 7}}}},
7128 // new line is (4,9)
7129 {{{{0, 4, 6, 7}},
7130 {{4, 1, 5, 8}},
7131 {{6, 5, 2, 9}},
7132 {{7, 8, 9, 3}},
7133 {{4, 5, 6, 9}},
7134 {{4, 7, 8, 9}},
7135 {{6, 9, 7, 4}},
7136 {{5, 8, 9, 4}}}}}};
7137
7138
7139 const auto &cell_quads =
7140 (reference_cell_type == ReferenceCells::Hexahedron) ?
7141 cell_quads_hex :
7142 cell_quads_tet[chosen_line_tetrahedron];
7143
7144 for (unsigned int c = 0;
7145 c < GeometryInfo<dim>::max_children_per_cell;
7146 ++c)
7147 {
7148 auto &new_hex = new_hexes[c];
7149
7150 if (new_hex->n_faces() == 4)
7151 {
7152 new_hex->set_bounding_object_indices(
7153 {quad_indices[cell_quads[c][0]],
7154 quad_indices[cell_quads[c][1]],
7155 quad_indices[cell_quads[c][2]],
7156 quad_indices[cell_quads[c][3]]});
7157
7158
7159 // for tets, we need to go through the faces and
7160 // figure the orientation out the hard way
7161 for (const auto f : new_hex->face_indices())
7162 {
7163 const auto &face = new_hex->face(f);
7164
7165 Assert(face->n_vertices() == 3,
7167
7168 const std::array<unsigned int, 3> vertices_0 = {
7169 {face->vertex_index(0),
7170 face->vertex_index(1),
7171 face->vertex_index(2)}};
7172
7173 const auto &new_hex_vertices =
7174 cell_vertices_tet[chosen_line_tetrahedron][c];
7175 const auto face_f_vertices =
7176 reference_cell_face_vertices[f];
7177
7178 const std::array<unsigned int, 3> vertices_1 = {
7179 {
7181 [new_hex_vertices[face_f_vertices[0]]],
7183 [new_hex_vertices[face_f_vertices[1]]],
7185 [new_hex_vertices[face_f_vertices[2]]],
7186 }};
7187
7188 new_hex->set_combined_face_orientation(
7189 f,
7190 face->reference_cell()
7191 .get_combined_orientation(
7192 make_array_view(vertices_1),
7193 make_array_view(vertices_0)));
7194 }
7195 }
7196 else if (new_hex->n_faces() == 6)
7197 new_hex->set_bounding_object_indices(
7198 {quad_indices[cell_quads[c][0]],
7199 quad_indices[cell_quads[c][1]],
7200 quad_indices[cell_quads[c][2]],
7201 quad_indices[cell_quads[c][3]],
7202 quad_indices[cell_quads[c][4]],
7203 quad_indices[cell_quads[c][5]]});
7204 else
7206 }
7207
7208 // for hexes, we can simply inherit the orientation values
7209 // from the parent on the outer faces; the inner faces can
7210 // be skipped as their orientation is always the default
7211 // one set above
7212 static constexpr ::ndarray<unsigned int, 6, 4>
7213 face_to_child_indices_hex{{{{0, 2, 4, 6}},
7214 {{1, 3, 5, 7}},
7215 {{0, 1, 4, 5}},
7216 {{2, 3, 6, 7}},
7217 {{0, 1, 2, 3}},
7218 {{4, 5, 6, 7}}}};
7219 if (hex->n_faces() == 6)
7220 for (const auto f : hex->face_indices())
7221 {
7222 const unsigned char combined_orientation =
7223 hex->combined_face_orientation(f);
7224 for (unsigned int c = 0; c < 4; ++c)
7225 new_hexes[face_to_child_indices_hex[f][c]]
7226 ->set_combined_face_orientation(
7227 f, combined_orientation);
7228 }
7229 }
7230 }
7231
7232 if (check_for_distorted_cells &&
7233 has_distorted_children<dim, spacedim>(hex))
7234 cells_with_distorted_children.distorted_cells.push_back(hex);
7235
7236 triangulation.signals.post_refinement_on_cell(hex);
7237 }
7238 }
7239
7240 triangulation.faces->quads.clear_user_data();
7241
7242 return cells_with_distorted_children;
7243 }
7244
7249 template <int spacedim>
7252 const bool check_for_distorted_cells)
7253 {
7254 const unsigned int dim = 3;
7255
7256 {
7257 bool flag_isotropic_mesh = true;
7259 cell = triangulation.begin(),
7260 endc = triangulation.end();
7261 for (; cell != endc; ++cell)
7262 if (cell->used())
7263 if (triangulation.get_anisotropic_refinement_flag() ||
7264 cell->refine_flag_set() == RefinementCase<dim>::cut_x ||
7265 cell->refine_flag_set() == RefinementCase<dim>::cut_y ||
7266 cell->refine_flag_set() == RefinementCase<dim>::cut_z ||
7267 cell->refine_flag_set() == RefinementCase<dim>::cut_xy ||
7268 cell->refine_flag_set() == RefinementCase<dim>::cut_xz ||
7269 cell->refine_flag_set() == RefinementCase<dim>::cut_yz)
7270 {
7271 flag_isotropic_mesh = false;
7272 break;
7273 }
7274
7275 if (flag_isotropic_mesh)
7276 return execute_refinement_isotropic(triangulation,
7277 check_for_distorted_cells);
7278 }
7279
7280 // this function probably also works for spacedim>3 but it
7281 // isn't tested. it will probably be necessary to pull new
7282 // vertices onto the manifold just as we do for the other
7283 // functions above.
7284 Assert(spacedim == 3, ExcNotImplemented());
7285
7286 // Check whether a new level is needed. We have to check for
7287 // this on the highest level only
7288 for (const auto &cell : triangulation.active_cell_iterators_on_level(
7289 triangulation.levels.size() - 1))
7290 if (cell->refine_flag_set())
7291 {
7292 triangulation.levels.push_back(
7293 std::make_unique<
7295 break;
7296 }
7297
7298
7299 // first clear user flags for quads and lines; we're going to
7300 // use them to flag which lines and quads need refinement
7301 triangulation.faces->quads.clear_user_data();
7302
7305 line != triangulation.end_line();
7306 ++line)
7307 line->clear_user_flag();
7310 quad != triangulation.end_quad();
7311 ++quad)
7312 quad->clear_user_flag();
7313
7314 // create an array of face refine cases. User indices of faces
7315 // will be set to values corresponding with indices in this
7316 // array.
7317 const RefinementCase<dim - 1> face_refinement_cases[4] = {
7318 RefinementCase<dim - 1>::no_refinement,
7319 RefinementCase<dim - 1>::cut_x,
7320 RefinementCase<dim - 1>::cut_y,
7321 RefinementCase<dim - 1>::cut_xy};
7322
7323 // check how much space is needed on every level. We need not
7324 // check the highest level since either
7325 // - on the highest level no cells are flagged for refinement
7326 // - there are, but prepare_refinement added another empty
7327 // level which then is the highest level
7328
7329 // variables to hold the number of newly to be created
7330 // vertices, lines and quads. as these are stored globally,
7331 // declare them outside the loop over al levels. we need lines
7332 // and quads in pairs for refinement of old ones and lines and
7333 // quads, that can be stored as single ones, as they are newly
7334 // created in the inside of an existing cell
7335 unsigned int needed_vertices = 0;
7336 unsigned int needed_lines_single = 0;
7337 unsigned int needed_quads_single = 0;
7338 unsigned int needed_lines_pair = 0;
7339 unsigned int needed_quads_pair = 0;
7340 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
7341 {
7342 // count number of flagged cells on this level and compute
7343 // how many new vertices and new lines will be needed
7344 unsigned int new_cells = 0;
7345
7346 for (const auto &acell :
7347 triangulation.active_cell_iterators_on_level(level))
7348 if (acell->refine_flag_set())
7349 {
7350 RefinementCase<dim> ref_case = acell->refine_flag_set();
7351
7352 // now for interior vertices, lines and quads, which
7353 // are needed in any case
7354 if (ref_case == RefinementCase<dim>::cut_x ||
7355 ref_case == RefinementCase<dim>::cut_y ||
7356 ref_case == RefinementCase<dim>::cut_z)
7357 {
7358 ++needed_quads_single;
7359 new_cells += 2;
7360 triangulation.anisotropic_refinement = true;
7361 }
7362 else if (ref_case == RefinementCase<dim>::cut_xy ||
7363 ref_case == RefinementCase<dim>::cut_xz ||
7364 ref_case == RefinementCase<dim>::cut_yz)
7365 {
7366 ++needed_lines_single;
7367 needed_quads_single += 4;
7368 new_cells += 4;
7369 triangulation.anisotropic_refinement = true;
7370 }
7371 else if (ref_case == RefinementCase<dim>::cut_xyz)
7372 {
7373 ++needed_vertices;
7374 needed_lines_single += 6;
7375 needed_quads_single += 12;
7376 new_cells += 8;
7377 }
7378 else
7379 {
7380 // we should never get here
7382 }
7383
7384 // mark all faces for refinement; checking locally
7385 // if and how the neighbor would like to refine
7386 // these is difficult so we only flag them and after
7387 // visiting all cells, we decide which faces need
7388 // which refinement;
7389 for (const unsigned int face :
7391 {
7393 aface = acell->face(face);
7394 // get the RefineCase this faces has for the
7395 // given RefineCase of the cell
7396 RefinementCase<dim - 1> face_ref_case =
7398 ref_case,
7399 face,
7400 acell->face_orientation(face),
7401 acell->face_flip(face),
7402 acell->face_rotation(face));
7403 // only do something, if this face has to be
7404 // refined
7405 if (face_ref_case)
7406 {
7407 if (face_ref_case ==
7409 {
7410 if (aface->n_active_descendants() < 4)
7411 // we use user_flags to denote needed
7412 // isotropic refinement
7413 aface->set_user_flag();
7414 }
7415 else if (aface->refinement_case() != face_ref_case)
7416 // we use user_indices to denote needed
7417 // anisotropic refinement. note, that we
7418 // can have at most one anisotropic
7419 // refinement case for this face, as
7420 // otherwise prepare_refinement() would
7421 // have changed one of the cells to yield
7422 // isotropic refinement at this
7423 // face. therefore we set the user_index
7424 // uniquely
7425 {
7426 Assert(aface->refinement_case() ==
7428 dim - 1>::isotropic_refinement ||
7429 aface->refinement_case() ==
7432 aface->set_user_index(face_ref_case);
7433 }
7434 }
7435 } // for all faces
7436
7437 // flag all lines, that have to be refined
7438 for (unsigned int line = 0;
7439 line < GeometryInfo<dim>::lines_per_cell;
7440 ++line)
7442 line) &&
7443 !acell->line(line)->has_children())
7444 acell->line(line)->set_user_flag();
7445
7446 } // if refine_flag set and for all cells on this level
7447
7448
7449 // count number of used cells on the next higher level
7450 const unsigned int used_cells =
7451 std::count(triangulation.levels[level + 1]->cells.used.begin(),
7452 triangulation.levels[level + 1]->cells.used.end(),
7453 true);
7454
7455
7456 // reserve space for the used_cells cells already existing
7457 // on the next higher level as well as for the
7458 // 8*flagged_cells that will be created on that level
7459 reserve_space(*triangulation.levels[level + 1],
7460 used_cells + new_cells,
7461 3,
7462 spacedim);
7463 // reserve space for 8*flagged_cells new hexes on the next
7464 // higher level
7465 reserve_space(triangulation.levels[level + 1]->cells, new_cells);
7466 } // for all levels
7467 // now count the quads and lines which were flagged for
7468 // refinement
7471 quad != triangulation.end_quad();
7472 ++quad)
7473 {
7474 if (quad->user_flag_set())
7475 {
7476 // isotropic refinement: 1 interior vertex, 4 quads
7477 // and 4 interior lines. we store the interior lines
7478 // in pairs in case the face is already or will be
7479 // refined anisotropically
7480 needed_quads_pair += 4;
7481 needed_lines_pair += 4;
7482 needed_vertices += 1;
7483 }
7484 if (quad->user_index())
7485 {
7486 // anisotropic refinement: 1 interior
7487 // line and two quads
7488 needed_quads_pair += 2;
7489 needed_lines_single += 1;
7490 // there is a kind of complicated situation here which
7491 // requires our attention. if the quad is refined
7492 // isotropcally, two of the interior lines will get a
7493 // new mother line - the interior line of our
7494 // anisotropically refined quad. if those two lines
7495 // are not consecutive, we cannot do so and have to
7496 // replace them by two lines that are consecutive. we
7497 // try to avoid that situation, but it may happen
7498 // nevertheless through repeated refinement and
7499 // coarsening. thus we have to check here, as we will
7500 // need some additional space to store those new lines
7501 // in case we need them...
7502 if (quad->has_children())
7503 {
7504 Assert(quad->refinement_case() ==
7507 if ((face_refinement_cases[quad->user_index()] ==
7509 (quad->child(0)->line_index(1) + 1 !=
7510 quad->child(2)->line_index(1))) ||
7511 (face_refinement_cases[quad->user_index()] ==
7513 (quad->child(0)->line_index(3) + 1 !=
7514 quad->child(1)->line_index(3))))
7515 needed_lines_pair += 2;
7516 }
7517 }
7518 }
7519
7522 line != triangulation.end_line();
7523 ++line)
7524 if (line->user_flag_set())
7525 {
7526 needed_lines_pair += 2;
7527 needed_vertices += 1;
7528 }
7529
7530 // reserve space for needed_lines new lines stored in pairs
7531 reserve_space(triangulation.faces->lines,
7532 needed_lines_pair,
7533 needed_lines_single);
7534 // reserve space for needed_quads new quads stored in pairs
7536 needed_quads_pair,
7537 needed_quads_single);
7538 reserve_space(triangulation.faces->quads,
7539 needed_quads_pair,
7540 needed_quads_single);
7541
7542
7543 // add to needed vertices how many vertices are already in use
7544 needed_vertices += std::count(triangulation.vertices_used.begin(),
7545 triangulation.vertices_used.end(),
7546 true);
7547 // if we need more vertices: create them, if not: leave the
7548 // array as is, since shrinking is not really possible because
7549 // some of the vertices at the end may be in use
7550 if (needed_vertices > triangulation.vertices.size())
7551 {
7552 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
7553 triangulation.vertices_used.resize(needed_vertices, false);
7554 }
7555
7556
7557 //-----------------------------------------
7558 // Before we start with the actual refinement, we do some
7559 // sanity checks if in debug mode. especially, we try to catch
7560 // the notorious problem with lines being twice refined,
7561 // i.e. there are cells adjacent at one line ("around the
7562 // edge", but not at a face), with two cells differing by more
7563 // than one refinement level
7564 //
7565 // this check is very simple to implement here, since we have
7566 // all lines flagged if they shall be refined
7567#ifdef DEBUG
7568 for (const auto &cell : triangulation.active_cell_iterators())
7569 if (!cell->refine_flag_set())
7570 for (unsigned int line = 0;
7571 line < GeometryInfo<dim>::lines_per_cell;
7572 ++line)
7573 if (cell->line(line)->has_children())
7574 for (unsigned int c = 0; c < 2; ++c)
7575 Assert(cell->line(line)->child(c)->user_flag_set() == false,
7577#endif
7578
7579 //-----------------------------------------
7580 // Do refinement on every level
7581 //
7582 // To make life a bit easier, we first refine those lines and
7583 // quads that were flagged for refinement and then compose the
7584 // newly to be created cells.
7585 //
7586 // index of next unused vertex
7587 unsigned int next_unused_vertex = 0;
7588
7589 // first for lines
7590 {
7591 // only active objects can be refined further
7594 endl = triangulation.end_line();
7596 next_unused_line = triangulation.begin_raw_line();
7597
7598 for (; line != endl; ++line)
7599 if (line->user_flag_set())
7600 {
7601 // this line needs to be refined
7602
7603 // find the next unused vertex and set it
7604 // appropriately
7605 while (triangulation.vertices_used[next_unused_vertex] == true)
7606 ++next_unused_vertex;
7607 Assert(
7608 next_unused_vertex < triangulation.vertices.size(),
7609 ExcMessage(
7610 "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."));
7611 triangulation.vertices_used[next_unused_vertex] = true;
7612
7613 triangulation.vertices[next_unused_vertex] = line->center(true);
7614
7615 // now that we created the right point, make up the
7616 // two child lines (++ takes care of the end of the
7617 // vector)
7618 next_unused_line =
7619 triangulation.faces->lines.template next_free_pair_object<1>(
7621 Assert(next_unused_line.state() == IteratorState::valid,
7623
7624 // now we found two consecutive unused lines, such
7625 // that the children of a line will be consecutive.
7626 // then set the child pointer of the present line
7627 line->set_children(0, next_unused_line->index());
7628
7629 // set the two new lines
7631 children[2] = {next_unused_line, ++next_unused_line};
7632
7633 // some tests; if any of the iterators should be
7634 // invalid, then already dereferencing will fail
7635 AssertIsNotUsed(children[0]);
7636 AssertIsNotUsed(children[1]);
7637
7638 children[0]->set_bounding_object_indices(
7639 {line->vertex_index(0), next_unused_vertex});
7640 children[1]->set_bounding_object_indices(
7641 {next_unused_vertex, line->vertex_index(1)});
7642
7643 children[0]->set_used_flag();
7644 children[1]->set_used_flag();
7645 children[0]->clear_children();
7646 children[1]->clear_children();
7647 children[0]->clear_user_data();
7648 children[1]->clear_user_data();
7649 children[0]->clear_user_flag();
7650 children[1]->clear_user_flag();
7651
7652 children[0]->set_boundary_id_internal(line->boundary_id());
7653 children[1]->set_boundary_id_internal(line->boundary_id());
7654
7655 children[0]->set_manifold_id(line->manifold_id());
7656 children[1]->set_manifold_id(line->manifold_id());
7657
7658 // finally clear flag
7659 // indicating the need
7660 // for refinement
7661 line->clear_user_flag();
7662 }
7663 }
7664
7665
7666 //-------------------------------------
7667 // now refine marked quads
7668 //-------------------------------------
7669
7670 // here we encounter several cases:
7671
7672 // a) the quad is unrefined and shall be refined isotropically
7673
7674 // b) the quad is unrefined and shall be refined
7675 // anisotropically
7676
7677 // c) the quad is unrefined and shall be refined both
7678 // anisotropically and isotropically (this is reduced to case
7679 // b) and then case b) for the children again)
7680
7681 // d) the quad is refined anisotropically and shall be refined
7682 // isotropically (this is reduced to case b) for the
7683 // anisotropic children)
7684
7685 // e) the quad is refined isotropically and shall be refined
7686 // anisotropically (this is transformed to case c), however we
7687 // might have to renumber/rename children...)
7688
7689 // we need a loop in cases c) and d), as the anisotropic
7690 // children might have a lower index than the mother quad
7691 for (unsigned int loop = 0; loop < 2; ++loop)
7692 {
7693 // usually, only active objects can be refined
7694 // further. however, in cases d) and e) that is not true,
7695 // so we have to use 'normal' iterators here
7697 quad = triangulation.begin_quad(),
7698 endq = triangulation.end_quad();
7700 next_unused_line = triangulation.begin_raw_line();
7702 next_unused_quad = triangulation.begin_raw_quad();
7703
7704 for (; quad != endq; ++quad)
7705 {
7706 if (quad->user_index())
7707 {
7708 RefinementCase<dim - 1> aniso_quad_ref_case =
7709 face_refinement_cases[quad->user_index()];
7710 // there is one unlikely event here, where we
7711 // already have refind the face: if the face was
7712 // refined anisotropically and we want to refine
7713 // it isotropically, both children are flagged for
7714 // anisotropic refinement. however, if those
7715 // children were already flagged for anisotropic
7716 // refinement, they might already be processed and
7717 // refined.
7718 if (aniso_quad_ref_case == quad->refinement_case())
7719 continue;
7720
7721 Assert(quad->refinement_case() ==
7723 quad->refinement_case() ==
7726
7727 // this quad needs to be refined anisotropically
7728 Assert(quad->user_index() ==
7730 quad->user_index() ==
7733
7734 // make the new line interior to the quad
7736 new_line;
7737
7738 new_line =
7739 triangulation.faces->lines
7740 .template next_free_single_object<1>(triangulation);
7741 AssertIsNotUsed(new_line);
7742
7743 // first collect the
7744 // indices of the vertices:
7745 // *--1--*
7746 // | | |
7747 // | | | cut_x
7748 // | | |
7749 // *--0--*
7750 //
7751 // *-----*
7752 // | |
7753 // 0-----1 cut_y
7754 // | |
7755 // *-----*
7756 unsigned int vertex_indices[2];
7757 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
7758 {
7759 vertex_indices[0] =
7760 quad->line(2)->child(0)->vertex_index(1);
7761 vertex_indices[1] =
7762 quad->line(3)->child(0)->vertex_index(1);
7763 }
7764 else
7765 {
7766 vertex_indices[0] =
7767 quad->line(0)->child(0)->vertex_index(1);
7768 vertex_indices[1] =
7769 quad->line(1)->child(0)->vertex_index(1);
7770 }
7771
7772 new_line->set_bounding_object_indices(
7774 new_line->set_used_flag();
7775 new_line->clear_user_flag();
7776 new_line->clear_user_data();
7777 new_line->clear_children();
7778 new_line->set_boundary_id_internal(quad->boundary_id());
7779 new_line->set_manifold_id(quad->manifold_id());
7780
7781 // child 0 and 1 of a line are switched if the
7782 // line orientation is false. set up a miniature
7783 // table, indicating which child to take for line
7784 // orientations false and true. first index: child
7785 // index in standard orientation, second index:
7786 // line orientation
7787 const unsigned int index[2][2] = {
7788 {1, 0}, // child 0, line_orientation=false and true
7789 {0, 1}}; // child 1, line_orientation=false and true
7790
7791 // find some space (consecutive) for the two newly
7792 // to be created quads.
7794 new_quads[2];
7795
7796 next_unused_quad =
7797 triangulation.faces->quads
7798 .template next_free_pair_object<2>(triangulation);
7799 new_quads[0] = next_unused_quad;
7800 AssertIsNotUsed(new_quads[0]);
7801
7802 ++next_unused_quad;
7803 new_quads[1] = next_unused_quad;
7804 AssertIsNotUsed(new_quads[1]);
7805
7806 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
7807 {
7808 new_quads[0]->set_bounding_object_indices(
7809 {static_cast<int>(quad->line_index(0)),
7810 new_line->index(),
7811 quad->line(2)
7812 ->child(index[0][quad->line_orientation(2)])
7813 ->index(),
7814 quad->line(3)
7815 ->child(index[0][quad->line_orientation(3)])
7816 ->index()});
7817 new_quads[1]->set_bounding_object_indices(
7818 {new_line->index(),
7819 static_cast<int>(quad->line_index(1)),
7820 quad->line(2)
7821 ->child(index[1][quad->line_orientation(2)])
7822 ->index(),
7823 quad->line(3)
7824 ->child(index[1][quad->line_orientation(3)])
7825 ->index()});
7826 }
7827 else
7828 {
7829 new_quads[0]->set_bounding_object_indices(
7830 {quad->line(0)
7831 ->child(index[0][quad->line_orientation(0)])
7832 ->index(),
7833 quad->line(1)
7834 ->child(index[0][quad->line_orientation(1)])
7835 ->index(),
7836 static_cast<int>(quad->line_index(2)),
7837 new_line->index()});
7838 new_quads[1]->set_bounding_object_indices(
7839 {quad->line(0)
7840 ->child(index[1][quad->line_orientation(0)])
7841 ->index(),
7842 quad->line(1)
7843 ->child(index[1][quad->line_orientation(1)])
7844 ->index(),
7845 new_line->index(),
7846 static_cast<int>(quad->line_index(3))});
7847 }
7848
7849 for (const auto &new_quad : new_quads)
7850 {
7851 new_quad->set_used_flag();
7852 new_quad->clear_user_flag();
7853 new_quad->clear_user_data();
7854 new_quad->clear_children();
7855 new_quad->set_boundary_id_internal(quad->boundary_id());
7856 new_quad->set_manifold_id(quad->manifold_id());
7857 // set all line orientations to true, change
7858 // this after the loop, as we have to consider
7859 // different lines for each child
7860 for (unsigned int j = 0;
7861 j < GeometryInfo<dim>::lines_per_face;
7862 ++j)
7863 new_quad->set_line_orientation(j, true);
7864 }
7865 // now set the line orientation of children of
7866 // outer lines correctly, the lines in the
7867 // interior of the refined quad are automatically
7868 // oriented conforming to the standard
7869 new_quads[0]->set_line_orientation(
7870 0, quad->line_orientation(0));
7871 new_quads[0]->set_line_orientation(
7872 2, quad->line_orientation(2));
7873 new_quads[1]->set_line_orientation(
7874 1, quad->line_orientation(1));
7875 new_quads[1]->set_line_orientation(
7876 3, quad->line_orientation(3));
7877 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
7878 {
7879 new_quads[0]->set_line_orientation(
7880 3, quad->line_orientation(3));
7881 new_quads[1]->set_line_orientation(
7882 2, quad->line_orientation(2));
7883 }
7884 else
7885 {
7886 new_quads[0]->set_line_orientation(
7887 1, quad->line_orientation(1));
7888 new_quads[1]->set_line_orientation(
7889 0, quad->line_orientation(0));
7890 }
7891
7892 // test, whether this face is refined
7893 // isotropically already. if so, set the correct
7894 // children pointers.
7895 if (quad->refinement_case() ==
7896 RefinementCase<dim - 1>::cut_xy)
7897 {
7898 // we will put a new refinemnt level of
7899 // anisotropic refinement between the
7900 // unrefined and isotropically refined quad
7901 // ending up with the same fine quads but
7902 // introducing anisotropically refined ones as
7903 // children of the unrefined quad and mother
7904 // cells of the original fine ones.
7905
7906 // this process includes the creation of a new
7907 // middle line which we will assign as the
7908 // mother line of two of the existing inner
7909 // lines. If those inner lines are not
7910 // consecutive in memory, we won't find them
7911 // later on, so we have to create new ones
7912 // instead and replace all occurrences of the
7913 // old ones with those new ones. As this is
7914 // kind of ugly, we hope we don't have to do
7915 // it often...
7917 old_child[2];
7918 if (aniso_quad_ref_case ==
7920 {
7921 old_child[0] = quad->child(0)->line(1);
7922 old_child[1] = quad->child(2)->line(1);
7923 }
7924 else
7925 {
7926 Assert(aniso_quad_ref_case ==
7929
7930 old_child[0] = quad->child(0)->line(3);
7931 old_child[1] = quad->child(1)->line(3);
7932 }
7933
7934 if (old_child[0]->index() + 1 != old_child[1]->index())
7935 {
7936 // this is exactly the ugly case we taked
7937 // about. so, no coimplaining, lets get
7938 // two new lines and copy all info
7939 typename Triangulation<dim,
7940 spacedim>::raw_line_iterator
7941 new_child[2];
7942
7943 new_child[0] = new_child[1] =
7944 triangulation.faces->lines
7945 .template next_free_pair_object<1>(
7947 ++new_child[1];
7948
7949 new_child[0]->set_used_flag();
7950 new_child[1]->set_used_flag();
7951
7952 const int old_index_0 = old_child[0]->index(),
7953 old_index_1 = old_child[1]->index(),
7954 new_index_0 = new_child[0]->index(),
7955 new_index_1 = new_child[1]->index();
7956
7957 // loop over all quads and replace the old
7958 // lines
7959 for (unsigned int q = 0;
7960 q < triangulation.faces->quads.n_objects();
7961 ++q)
7962 for (unsigned int l = 0;
7963 l < GeometryInfo<dim>::lines_per_face;
7964 ++l)
7965 {
7966 const int this_index =
7967 triangulation.faces->quads
7968 .get_bounding_object_indices(q)[l];
7969 if (this_index == old_index_0)
7970 triangulation.faces->quads
7971 .get_bounding_object_indices(q)[l] =
7972 new_index_0;
7973 else if (this_index == old_index_1)
7974 triangulation.faces->quads
7975 .get_bounding_object_indices(q)[l] =
7976 new_index_1;
7977 }
7978 // now we have to copy all information of
7979 // the two lines
7980 for (unsigned int i = 0; i < 2; ++i)
7981 {
7982 Assert(!old_child[i]->has_children(),
7984
7985 new_child[i]->set_bounding_object_indices(
7986 {old_child[i]->vertex_index(0),
7987 old_child[i]->vertex_index(1)});
7988 new_child[i]->set_boundary_id_internal(
7989 old_child[i]->boundary_id());
7990 new_child[i]->set_manifold_id(
7991 old_child[i]->manifold_id());
7992 new_child[i]->set_user_index(
7993 old_child[i]->user_index());
7994 if (old_child[i]->user_flag_set())
7995 new_child[i]->set_user_flag();
7996 else
7997 new_child[i]->clear_user_flag();
7998
7999 new_child[i]->clear_children();
8000
8001 old_child[i]->clear_user_flag();
8002 old_child[i]->clear_user_index();
8003 old_child[i]->clear_used_flag();
8004 }
8005 }
8006 // now that we cared about the lines, go on
8007 // with the quads themselves, where we might
8008 // encounter similar situations...
8009 if (aniso_quad_ref_case ==
8011 {
8012 new_line->set_children(
8013 0, quad->child(0)->line_index(1));
8014 Assert(new_line->child(1) ==
8015 quad->child(2)->line(1),
8017 // now evereything is quite
8018 // complicated. we have the children
8019 // numbered according to
8020 //
8021 // *---*---*
8022 // |n+2|n+3|
8023 // *---*---*
8024 // | n |n+1|
8025 // *---*---*
8026 //
8027 // from the original isotropic
8028 // refinement. we have to reorder them as
8029 //
8030 // *---*---*
8031 // |n+1|n+3|
8032 // *---*---*
8033 // | n |n+2|
8034 // *---*---*
8035 //
8036 // such that n and n+1 are consecutive
8037 // children of m and n+2 and n+3 are
8038 // consecutive children of m+1, where m
8039 // and m+1 are given as in
8040 //
8041 // *---*---*
8042 // | | |
8043 // | m |m+1|
8044 // | | |
8045 // *---*---*
8046 //
8047 // this is a bit ugly, of course: loop
8048 // over all cells on all levels and look
8049 // for faces n+1 (switch_1) and n+2
8050 // (switch_2).
8051 const typename Triangulation<dim, spacedim>::
8052 quad_iterator switch_1 = quad->child(1),
8053 switch_2 = quad->child(2);
8054 const int switch_1_index = switch_1->index();
8055 const int switch_2_index = switch_2->index();
8056 for (unsigned int l = 0;
8057 l < triangulation.levels.size();
8058 ++l)
8059 for (unsigned int h = 0;
8060 h <
8061 triangulation.levels[l]->cells.n_objects();
8062 ++h)
8063 for (const unsigned int q :
8065 {
8066 const int face_index =
8068 ->cells.get_bounding_object_indices(
8069 h)[q];
8070 if (face_index == switch_1_index)
8071 triangulation.levels[l]
8072 ->cells.get_bounding_object_indices(
8073 h)[q] = switch_2_index;
8074 else if (face_index == switch_2_index)
8075 triangulation.levels[l]
8076 ->cells.get_bounding_object_indices(
8077 h)[q] = switch_1_index;
8078 }
8079 // now we have to copy all information of
8080 // the two quads
8081 const unsigned int switch_1_lines[4] = {
8082 switch_1->line_index(0),
8083 switch_1->line_index(1),
8084 switch_1->line_index(2),
8085 switch_1->line_index(3)};
8086 const bool switch_1_line_orientations[4] = {
8087 switch_1->line_orientation(0),
8088 switch_1->line_orientation(1),
8089 switch_1->line_orientation(2),
8090 switch_1->line_orientation(3)};
8091 const types::boundary_id switch_1_boundary_id =
8092 switch_1->boundary_id();
8093 const unsigned int switch_1_user_index =
8094 switch_1->user_index();
8095 const bool switch_1_user_flag =
8096 switch_1->user_flag_set();
8097 const RefinementCase<dim - 1>
8098 switch_1_refinement_case =
8099 switch_1->refinement_case();
8100 const int switch_1_first_child_pair =
8101 (switch_1_refinement_case ?
8102 switch_1->child_index(0) :
8103 -1);
8104 const int switch_1_second_child_pair =
8105 (switch_1_refinement_case ==
8106 RefinementCase<dim - 1>::cut_xy ?
8107 switch_1->child_index(2) :
8108 -1);
8109
8110 switch_1->set_bounding_object_indices(
8111 {switch_2->line_index(0),
8112 switch_2->line_index(1),
8113 switch_2->line_index(2),
8114 switch_2->line_index(3)});
8115 switch_1->set_line_orientation(
8116 0, switch_2->line_orientation(0));
8117 switch_1->set_line_orientation(
8118 1, switch_2->line_orientation(1));
8119 switch_1->set_line_orientation(
8120 2, switch_2->line_orientation(2));
8121 switch_1->set_line_orientation(
8122 3, switch_2->line_orientation(3));
8123 switch_1->set_boundary_id_internal(
8124 switch_2->boundary_id());
8125 switch_1->set_manifold_id(switch_2->manifold_id());
8126 switch_1->set_user_index(switch_2->user_index());
8127 if (switch_2->user_flag_set())
8128 switch_1->set_user_flag();
8129 else
8130 switch_1->clear_user_flag();
8131 switch_1->clear_refinement_case();
8132 switch_1->set_refinement_case(
8133 switch_2->refinement_case());
8134 switch_1->clear_children();
8135 if (switch_2->refinement_case())
8136 switch_1->set_children(0,
8137 switch_2->child_index(0));
8138 if (switch_2->refinement_case() ==
8139 RefinementCase<dim - 1>::cut_xy)
8140 switch_1->set_children(2,
8141 switch_2->child_index(2));
8142
8143 switch_2->set_bounding_object_indices(
8144 {switch_1_lines[0],
8145 switch_1_lines[1],
8146 switch_1_lines[2],
8147 switch_1_lines[3]});
8148 switch_2->set_line_orientation(
8149 0, switch_1_line_orientations[0]);
8150 switch_2->set_line_orientation(
8151 1, switch_1_line_orientations[1]);
8152 switch_2->set_line_orientation(
8153 2, switch_1_line_orientations[2]);
8154 switch_2->set_line_orientation(
8155 3, switch_1_line_orientations[3]);
8156 switch_2->set_boundary_id_internal(
8157 switch_1_boundary_id);
8158 switch_2->set_manifold_id(switch_1->manifold_id());
8159 switch_2->set_user_index(switch_1_user_index);
8160 if (switch_1_user_flag)
8161 switch_2->set_user_flag();
8162 else
8163 switch_2->clear_user_flag();
8164 switch_2->clear_refinement_case();
8165 switch_2->set_refinement_case(
8166 switch_1_refinement_case);
8167 switch_2->clear_children();
8168 switch_2->set_children(0,
8169 switch_1_first_child_pair);
8170 switch_2->set_children(2,
8171 switch_1_second_child_pair);
8172
8173 new_quads[0]->set_refinement_case(
8175 new_quads[0]->set_children(0, quad->child_index(0));
8176 new_quads[1]->set_refinement_case(
8178 new_quads[1]->set_children(0, quad->child_index(2));
8179 }
8180 else
8181 {
8182 new_quads[0]->set_refinement_case(
8184 new_quads[0]->set_children(0, quad->child_index(0));
8185 new_quads[1]->set_refinement_case(
8187 new_quads[1]->set_children(0, quad->child_index(2));
8188 new_line->set_children(
8189 0, quad->child(0)->line_index(3));
8190 Assert(new_line->child(1) ==
8191 quad->child(1)->line(3),
8193 }
8194 quad->clear_children();
8195 }
8196
8197 // note these quads as children to the present one
8198 quad->set_children(0, new_quads[0]->index());
8199
8200 quad->set_refinement_case(aniso_quad_ref_case);
8201
8202 // finally clear flag indicating the need for
8203 // refinement
8204 quad->clear_user_data();
8205 } // if (anisotropic refinement)
8206
8207 if (quad->user_flag_set())
8208 {
8209 // this quad needs to be refined isotropically
8210
8211 // first of all: we only get here in the first run
8212 // of the loop
8213 Assert(loop == 0, ExcInternalError());
8214
8215 // find the next unused vertex. we'll need this in
8216 // any case
8217 while (triangulation.vertices_used[next_unused_vertex] ==
8218 true)
8219 ++next_unused_vertex;
8220 Assert(
8221 next_unused_vertex < triangulation.vertices.size(),
8222 ExcMessage(
8223 "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."));
8224
8225 // now: if the quad is refined anisotropically
8226 // already, set the anisotropic refinement flag
8227 // for both children. Additionally, we have to
8228 // refine the inner line, as it is an outer line
8229 // of the two (anisotropic) children
8230 const RefinementCase<dim - 1> quad_ref_case =
8231 quad->refinement_case();
8232
8233 if (quad_ref_case == RefinementCase<dim - 1>::cut_x ||
8234 quad_ref_case == RefinementCase<dim - 1>::cut_y)
8235 {
8236 // set the 'opposite' refine case for children
8237 quad->child(0)->set_user_index(
8238 RefinementCase<dim - 1>::cut_xy - quad_ref_case);
8239 quad->child(1)->set_user_index(
8240 RefinementCase<dim - 1>::cut_xy - quad_ref_case);
8241 // refine the inner line
8243 middle_line;
8244 if (quad_ref_case == RefinementCase<dim - 1>::cut_x)
8245 middle_line = quad->child(0)->line(1);
8246 else
8247 middle_line = quad->child(0)->line(3);
8248
8249 // if the face has been refined
8250 // anisotropically in the last refinement step
8251 // it might be, that it is flagged already and
8252 // that the middle line is thus refined
8253 // already. if not create children.
8254 if (!middle_line->has_children())
8255 {
8256 // set the middle vertex
8257 // appropriately. double refinement of
8258 // quads can only happen in the interior
8259 // of the domain, so we need not care
8260 // about boundary quads here
8261 triangulation.vertices[next_unused_vertex] =
8262 middle_line->center(true);
8263 triangulation.vertices_used[next_unused_vertex] =
8264 true;
8265
8266 // now search a slot for the two
8267 // child lines
8268 next_unused_line =
8269 triangulation.faces->lines
8270 .template next_free_pair_object<1>(
8272
8273 // set the child pointer of the present
8274 // line
8275 middle_line->set_children(
8276 0, next_unused_line->index());
8277
8278 // set the two new lines
8279 const typename Triangulation<dim, spacedim>::
8280 raw_line_iterator children[2] = {
8281 next_unused_line, ++next_unused_line};
8282
8283 // some tests; if any of the iterators
8284 // should be invalid, then already
8285 // dereferencing will fail
8286 AssertIsNotUsed(children[0]);
8287 AssertIsNotUsed(children[1]);
8288
8289 children[0]->set_bounding_object_indices(
8290 {middle_line->vertex_index(0),
8291 next_unused_vertex});
8292 children[1]->set_bounding_object_indices(
8293 {next_unused_vertex,
8294 middle_line->vertex_index(1)});
8295
8296 children[0]->set_used_flag();
8297 children[1]->set_used_flag();
8298 children[0]->clear_children();
8299 children[1]->clear_children();
8300 children[0]->clear_user_data();
8301 children[1]->clear_user_data();
8302 children[0]->clear_user_flag();
8303 children[1]->clear_user_flag();
8304
8305 children[0]->set_boundary_id_internal(
8306 middle_line->boundary_id());
8307 children[1]->set_boundary_id_internal(
8308 middle_line->boundary_id());
8309
8310 children[0]->set_manifold_id(
8311 middle_line->manifold_id());
8312 children[1]->set_manifold_id(
8313 middle_line->manifold_id());
8314 }
8315 // now remove the flag from the quad and go to
8316 // the next quad, the actual refinement of the
8317 // quad takes place later on in this pass of
8318 // the loop or in the next one
8319 quad->clear_user_flag();
8320 continue;
8321 } // if (several refinement cases)
8322
8323 // if we got here, we have an unrefined quad and
8324 // have to do the usual work like in an purely
8325 // isotropic refinement
8326 Assert(quad_ref_case ==
8329
8330 // set the middle vertex appropriately: it might be that
8331 // the quad itself is not at the boundary, but that one of
8332 // its lines actually is. in this case, the newly created
8333 // vertices at the centers of the lines are not
8334 // necessarily the mean values of the adjacent vertices,
8335 // so do not compute the new vertex as the mean value of
8336 // the 4 vertices of the face, but rather as a weighted
8337 // mean value of the 8 vertices which we already have (the
8338 // four old ones, and the four ones inserted as middle
8339 // points for the four lines). summing up some more points
8340 // is generally cheaper than first asking whether one of
8341 // the lines is at the boundary
8342 //
8343 // note that the exact weights are chosen such as to
8344 // minimize the distortion of the four new quads from the
8345 // optimal shape. their description uses the formulas
8346 // underlying the TransfiniteInterpolationManifold
8347 // implementation
8348 triangulation.vertices[next_unused_vertex] =
8349 quad->center(true, true);
8350 triangulation.vertices_used[next_unused_vertex] = true;
8351
8352 // now that we created the right point, make up
8353 // the four lines interior to the quad (++ takes
8354 // care of the end of the vector)
8356 new_lines[4];
8357
8358 for (unsigned int i = 0; i < 4; ++i)
8359 {
8360 if (i % 2 == 0)
8361 // search a free pair of lines for 0. and
8362 // 2. line, so that two of them end up
8363 // together, which is necessary if later on
8364 // we want to refine the quad
8365 // anisotropically and the two lines end up
8366 // as children of new line
8367 next_unused_line =
8368 triangulation.faces->lines
8369 .template next_free_pair_object<1>(triangulation);
8370
8371 new_lines[i] = next_unused_line;
8372 ++next_unused_line;
8373
8374 AssertIsNotUsed(new_lines[i]);
8375 }
8376
8377 // set the data of the four lines. first collect
8378 // the indices of the five vertices:
8379 //
8380 // *--3--*
8381 // | | |
8382 // 0--4--1
8383 // | | |
8384 // *--2--*
8385 //
8386 // the lines are numbered as follows:
8387 //
8388 // *--*--*
8389 // | 1 |
8390 // *2-*-3*
8391 // | 0 |
8392 // *--*--*
8393
8394 const unsigned int vertex_indices[5] = {
8395 quad->line(0)->child(0)->vertex_index(1),
8396 quad->line(1)->child(0)->vertex_index(1),
8397 quad->line(2)->child(0)->vertex_index(1),
8398 quad->line(3)->child(0)->vertex_index(1),
8399 next_unused_vertex};
8400
8401 new_lines[0]->set_bounding_object_indices(
8403 new_lines[1]->set_bounding_object_indices(
8405 new_lines[2]->set_bounding_object_indices(
8407 new_lines[3]->set_bounding_object_indices(
8409
8410 for (const auto &new_line : new_lines)
8411 {
8412 new_line->set_used_flag();
8413 new_line->clear_user_flag();
8414 new_line->clear_user_data();
8415 new_line->clear_children();
8416 new_line->set_boundary_id_internal(quad->boundary_id());
8417 new_line->set_manifold_id(quad->manifold_id());
8418 }
8419
8420 // now for the quads. again, first collect some
8421 // data about the indices of the lines, with the
8422 // following numbering:
8423 //
8424 // .-6-.-7-.
8425 // 1 9 3
8426 // .-10.11-.
8427 // 0 8 2
8428 // .-4-.-5-.
8429
8430 // child 0 and 1 of a line are switched if the
8431 // line orientation is false. set up a miniature
8432 // table, indicating which child to take for line
8433 // orientations false and true. first index: child
8434 // index in standard orientation, second index:
8435 // line orientation
8436 const unsigned int index[2][2] = {
8437 {1, 0}, // child 0, line_orientation=false and true
8438 {0, 1}}; // child 1, line_orientation=false and true
8439
8440 const int line_indices[12] = {
8441 quad->line(0)
8442 ->child(index[0][quad->line_orientation(0)])
8443 ->index(),
8444 quad->line(0)
8445 ->child(index[1][quad->line_orientation(0)])
8446 ->index(),
8447 quad->line(1)
8448 ->child(index[0][quad->line_orientation(1)])
8449 ->index(),
8450 quad->line(1)
8451 ->child(index[1][quad->line_orientation(1)])
8452 ->index(),
8453 quad->line(2)
8454 ->child(index[0][quad->line_orientation(2)])
8455 ->index(),
8456 quad->line(2)
8457 ->child(index[1][quad->line_orientation(2)])
8458 ->index(),
8459 quad->line(3)
8460 ->child(index[0][quad->line_orientation(3)])
8461 ->index(),
8462 quad->line(3)
8463 ->child(index[1][quad->line_orientation(3)])
8464 ->index(),
8465 new_lines[0]->index(),
8466 new_lines[1]->index(),
8467 new_lines[2]->index(),
8468 new_lines[3]->index()};
8469
8470 // find some space (consecutive)
8471 // for the first two newly to be
8472 // created quads.
8474 new_quads[4];
8475
8476 next_unused_quad =
8477 triangulation.faces->quads
8478 .template next_free_pair_object<2>(triangulation);
8479
8480 new_quads[0] = next_unused_quad;
8481 AssertIsNotUsed(new_quads[0]);
8482
8483 ++next_unused_quad;
8484 new_quads[1] = next_unused_quad;
8485 AssertIsNotUsed(new_quads[1]);
8486
8487 next_unused_quad =
8488 triangulation.faces->quads
8489 .template next_free_pair_object<2>(triangulation);
8490 new_quads[2] = next_unused_quad;
8491 AssertIsNotUsed(new_quads[2]);
8492
8493 ++next_unused_quad;
8494 new_quads[3] = next_unused_quad;
8495 AssertIsNotUsed(new_quads[3]);
8496
8497 // note these quads as children to the present one
8498 quad->set_children(0, new_quads[0]->index());
8499 quad->set_children(2, new_quads[2]->index());
8500 quad->set_refinement_case(RefinementCase<2>::cut_xy);
8501
8502 new_quads[0]->set_bounding_object_indices(
8503 {line_indices[0],
8504 line_indices[8],
8505 line_indices[4],
8506 line_indices[10]});
8507 new_quads[1]->set_bounding_object_indices(
8508 {line_indices[8],
8509 line_indices[2],
8510 line_indices[5],
8511 line_indices[11]});
8512 new_quads[2]->set_bounding_object_indices(
8513 {line_indices[1],
8514 line_indices[9],
8515 line_indices[10],
8516 line_indices[6]});
8517 new_quads[3]->set_bounding_object_indices(
8518 {line_indices[9],
8519 line_indices[3],
8520 line_indices[11],
8521 line_indices[7]});
8522 for (const auto &new_quad : new_quads)
8523 {
8524 new_quad->set_used_flag();
8525 new_quad->clear_user_flag();
8526 new_quad->clear_user_data();
8527 new_quad->clear_children();
8528 new_quad->set_boundary_id_internal(quad->boundary_id());
8529 new_quad->set_manifold_id(quad->manifold_id());
8530 // set all line orientations to true, change
8531 // this after the loop, as we have to consider
8532 // different lines for each child
8533 for (unsigned int j = 0;
8534 j < GeometryInfo<dim>::lines_per_face;
8535 ++j)
8536 new_quad->set_line_orientation(j, true);
8537 }
8538 // now set the line orientation of children of
8539 // outer lines correctly, the lines in the
8540 // interior of the refined quad are automatically
8541 // oriented conforming to the standard
8542 new_quads[0]->set_line_orientation(
8543 0, quad->line_orientation(0));
8544 new_quads[0]->set_line_orientation(
8545 2, quad->line_orientation(2));
8546 new_quads[1]->set_line_orientation(
8547 1, quad->line_orientation(1));
8548 new_quads[1]->set_line_orientation(
8549 2, quad->line_orientation(2));
8550 new_quads[2]->set_line_orientation(
8551 0, quad->line_orientation(0));
8552 new_quads[2]->set_line_orientation(
8553 3, quad->line_orientation(3));
8554 new_quads[3]->set_line_orientation(
8555 1, quad->line_orientation(1));
8556 new_quads[3]->set_line_orientation(
8557 3, quad->line_orientation(3));
8558
8559 // finally clear flag indicating the need for
8560 // refinement
8561 quad->clear_user_flag();
8562 } // if (isotropic refinement)
8563 } // for all quads
8564 } // looped two times over all quads, all quads refined now
8565
8566 //---------------------------------
8567 // Now, finally, set up the new
8568 // cells
8569 //---------------------------------
8570
8572 cells_with_distorted_children;
8573
8574 for (unsigned int level = 0; level != triangulation.levels.size() - 1;
8575 ++level)
8576 {
8577 // only active objects can be refined further; remember
8578 // that we won't operate on the finest level, so
8579 // triangulation.begin_*(level+1) is allowed
8582 endh = triangulation.begin_active_hex(level + 1);
8584 next_unused_hex = triangulation.begin_raw_hex(level + 1);
8585
8586 for (; hex != endh; ++hex)
8587 if (hex->refine_flag_set())
8588 {
8589 // this hex needs to be refined
8590
8591 // clear flag indicating the need for refinement. do
8592 // it here already, since we can't do it anymore
8593 // once the cell has children
8594 const RefinementCase<dim> ref_case = hex->refine_flag_set();
8595 hex->clear_refine_flag();
8596 hex->set_refinement_case(ref_case);
8597
8598 // depending on the refine case we might have to
8599 // create additional vertices, lines and quads
8600 // interior of the hex before the actual children
8601 // can be set up.
8602
8603 // in a first step: reserve the needed space for
8604 // lines, quads and hexes and initialize them
8605 // correctly
8606
8607 unsigned int n_new_lines = 0;
8608 unsigned int n_new_quads = 0;
8609 unsigned int n_new_hexes = 0;
8610 switch (ref_case)
8611 {
8615 n_new_lines = 0;
8616 n_new_quads = 1;
8617 n_new_hexes = 2;
8618 break;
8622 n_new_lines = 1;
8623 n_new_quads = 4;
8624 n_new_hexes = 4;
8625 break;
8627 n_new_lines = 6;
8628 n_new_quads = 12;
8629 n_new_hexes = 8;
8630 break;
8631 default:
8633 break;
8634 }
8635
8636 // find some space for the newly to be created
8637 // interior lines and initialize them.
8638 std::vector<
8640 new_lines(n_new_lines);
8641 for (unsigned int i = 0; i < n_new_lines; ++i)
8642 {
8643 new_lines[i] =
8644 triangulation.faces->lines
8645 .template next_free_single_object<1>(triangulation);
8646
8647 AssertIsNotUsed(new_lines[i]);
8648 new_lines[i]->set_used_flag();
8649 new_lines[i]->clear_user_flag();
8650 new_lines[i]->clear_user_data();
8651 new_lines[i]->clear_children();
8652 // interior line
8653 new_lines[i]->set_boundary_id_internal(
8655 // they inherit geometry description of the hex they
8656 // belong to
8657 new_lines[i]->set_manifold_id(hex->manifold_id());
8658 }
8659
8660 // find some space for the newly to be created
8661 // interior quads and initialize them.
8662 std::vector<
8664 new_quads(n_new_quads);
8665 for (unsigned int i = 0; i < n_new_quads; ++i)
8666 {
8667 new_quads[i] =
8668 triangulation.faces->quads
8669 .template next_free_single_object<2>(triangulation);
8670
8671 AssertIsNotUsed(new_quads[i]);
8672 new_quads[i]->set_used_flag();
8673 new_quads[i]->clear_user_flag();
8674 new_quads[i]->clear_user_data();
8675 new_quads[i]->clear_children();
8676 // interior quad
8677 new_quads[i]->set_boundary_id_internal(
8679 // they inherit geometry description of the hex they
8680 // belong to
8681 new_quads[i]->set_manifold_id(hex->manifold_id());
8682 // set all line orientation flags to true by
8683 // default, change this afterwards, if necessary
8684 for (unsigned int j = 0;
8685 j < GeometryInfo<dim>::lines_per_face;
8686 ++j)
8687 new_quads[i]->set_line_orientation(j, true);
8688 }
8689
8690 types::subdomain_id subdomainid = hex->subdomain_id();
8691
8692 // find some space for the newly to be created hexes
8693 // and initialize them.
8694 std::vector<
8696 new_hexes(n_new_hexes);
8697 for (unsigned int i = 0; i < n_new_hexes; ++i)
8698 {
8699 if (i % 2 == 0)
8700 next_unused_hex =
8701 triangulation.levels[level + 1]->cells.next_free_hex(
8702 triangulation, level + 1);
8703 else
8704 ++next_unused_hex;
8705
8706 new_hexes[i] = next_unused_hex;
8707
8708 AssertIsNotUsed(new_hexes[i]);
8709 new_hexes[i]->set_used_flag();
8710 new_hexes[i]->clear_user_flag();
8711 new_hexes[i]->clear_user_data();
8712 new_hexes[i]->clear_children();
8713 // inherit material
8714 // properties
8715 new_hexes[i]->set_material_id(hex->material_id());
8716 new_hexes[i]->set_manifold_id(hex->manifold_id());
8717 new_hexes[i]->set_subdomain_id(subdomainid);
8718
8719 if (i % 2)
8720 new_hexes[i]->set_parent(hex->index());
8721 // set the face_orientation flag to true for all
8722 // faces initially, as this is the default value
8723 // which is true for all faces interior to the
8724 // hex. later on go the other way round and
8725 // reset faces that are at the boundary of the
8726 // mother cube
8727 //
8728 // the same is true for the face_flip and
8729 // face_rotation flags. however, the latter two
8730 // are set to false by default as this is the
8731 // standard value
8732 for (const unsigned int f :
8734 new_hexes[i]->set_combined_face_orientation(
8735 f,
8737 }
8738 // note these hexes as children to the present cell
8739 for (unsigned int i = 0; i < n_new_hexes / 2; ++i)
8740 hex->set_children(2 * i, new_hexes[2 * i]->index());
8741
8742 // we have to take into account whether the
8743 // different faces are oriented correctly or in the
8744 // opposite direction, so store that up front
8745
8746 // face_orientation
8747 const bool f_or[6] = {hex->face_orientation(0),
8748 hex->face_orientation(1),
8749 hex->face_orientation(2),
8750 hex->face_orientation(3),
8751 hex->face_orientation(4),
8752 hex->face_orientation(5)};
8753
8754 // face_flip
8755 const bool f_fl[6] = {hex->face_flip(0),
8756 hex->face_flip(1),
8757 hex->face_flip(2),
8758 hex->face_flip(3),
8759 hex->face_flip(4),
8760 hex->face_flip(5)};
8761
8762 // face_rotation
8763 const bool f_ro[6] = {hex->face_rotation(0),
8764 hex->face_rotation(1),
8765 hex->face_rotation(2),
8766 hex->face_rotation(3),
8767 hex->face_rotation(4),
8768 hex->face_rotation(5)};
8769
8770 // combined orientation
8771 const unsigned char f_co[6] = {
8772 hex->combined_face_orientation(0),
8773 hex->combined_face_orientation(1),
8774 hex->combined_face_orientation(2),
8775 hex->combined_face_orientation(3),
8776 hex->combined_face_orientation(4),
8777 hex->combined_face_orientation(5)};
8778
8779 // little helper table, indicating, whether the
8780 // child with index 0 or with index 1 can be found
8781 // at the standard origin of an anisotropically
8782 // refined quads in real orientation index 1:
8783 // (RefineCase - 1) index 2: face_flip
8784
8785 // index 3: face rotation
8786 // note: face orientation has no influence
8787 const unsigned int child_at_origin[2][2][2] = {
8788 {{0, 0}, // RefinementCase<dim>::cut_x, face_flip=false,
8789 // face_rotation=false and true
8790 {1, 1}}, // RefinementCase<dim>::cut_x, face_flip=true,
8791 // face_rotation=false and true
8792 {{0, 1}, // RefinementCase<dim>::cut_y, face_flip=false,
8793 // face_rotation=false and true
8794 {1, 0}}}; // RefinementCase<dim>::cut_y, face_flip=true,
8795 // face_rotation=false and true
8796
8797 //-------------------------------------
8798 //
8799 // in the following we will do the same thing for
8800 // each refinement case: create a new vertex (if
8801 // needed), create new interior lines (if needed),
8802 // create new interior quads and afterwards build
8803 // the children hexes out of these and the existing
8804 // subfaces of the outer quads (which have been
8805 // created above). However, even if the steps are
8806 // quite similar, the actual work strongly depends
8807 // on the actual refinement case. therefore, we use
8808 // separate blocks of code for each of these cases,
8809 // which hopefully increases the readability to some
8810 // extend.
8811
8812 switch (ref_case)
8813 {
8815 {
8816 //----------------------------
8817 //
8818 // RefinementCase<dim>::cut_x
8819 //
8820 // the refined cube will look
8821 // like this:
8822 //
8823 // *----*----*
8824 // / / /|
8825 // / / / |
8826 // / / / |
8827 // *----*----* |
8828 // | | | |
8829 // | | | *
8830 // | | | /
8831 // | | | /
8832 // | | |/
8833 // *----*----*
8834 //
8835 // again, first collect some data about the
8836 // indices of the lines, with the following
8837 // numbering:
8838
8839 // face 2: front plane
8840 // (note: x,y exchanged)
8841 // *---*---*
8842 // | | |
8843 // | 0 |
8844 // | | |
8845 // *---*---*
8846 // m0
8847 // face 3: back plane
8848 // (note: x,y exchanged)
8849 // m1
8850 // *---*---*
8851 // | | |
8852 // | 1 |
8853 // | | |
8854 // *---*---*
8855 // face 4: bottom plane
8856 // *---*---*
8857 // / / /
8858 // / 2 /
8859 // / / /
8860 // *---*---*
8861 // m0
8862 // face 5: top plane
8863 // m1
8864 // *---*---*
8865 // / / /
8866 // / 3 /
8867 // / / /
8868 // *---*---*
8869
8870 // set up a list of line iterators first. from
8871 // this, construct lists of line_indices and
8872 // line orientations later on
8873 const typename Triangulation<dim, spacedim>::
8874 raw_line_iterator lines[4] = {
8875 hex->face(2)->child(0)->line(
8876 (hex->face(2)->refinement_case() ==
8878 1 :
8879 3), // 0
8880 hex->face(3)->child(0)->line(
8881 (hex->face(3)->refinement_case() ==
8883 1 :
8884 3), // 1
8885 hex->face(4)->child(0)->line(
8886 (hex->face(4)->refinement_case() ==
8888 1 :
8889 3), // 2
8890 hex->face(5)->child(0)->line(
8891 (hex->face(5)->refinement_case() ==
8893 1 :
8894 3) // 3
8895 };
8896
8897 unsigned int line_indices[4];
8898 for (unsigned int i = 0; i < 4; ++i)
8899 line_indices[i] = lines[i]->index();
8900
8901 // the orientation of lines for the inner quads
8902 // is quite tricky. as these lines are newly
8903 // created ones and thus have no parents, they
8904 // cannot inherit this property. set up an array
8905 // and fill it with the respective values
8906 bool line_orientation[4];
8907
8908 // the middle vertex marked as m0 above is the
8909 // start vertex for lines 0 and 2 in standard
8910 // orientation, whereas m1 is the end vertex of
8911 // lines 1 and 3 in standard orientation
8912 const unsigned int middle_vertices[2] = {
8913 hex->line(2)->child(0)->vertex_index(1),
8914 hex->line(7)->child(0)->vertex_index(1)};
8915
8916 for (unsigned int i = 0; i < 4; ++i)
8917 if (lines[i]->vertex_index(i % 2) ==
8918 middle_vertices[i % 2])
8919 line_orientation[i] = true;
8920 else
8921 {
8922 // it must be the other
8923 // way round then
8924 Assert(lines[i]->vertex_index((i + 1) % 2) ==
8925 middle_vertices[i % 2],
8927 line_orientation[i] = false;
8928 }
8929
8930 // set up the new quad, line numbering is as
8931 // indicated above
8932 new_quads[0]->set_bounding_object_indices(
8933 {line_indices[0],
8934 line_indices[1],
8935 line_indices[2],
8936 line_indices[3]});
8937
8938 new_quads[0]->set_line_orientation(
8939 0, line_orientation[0]);
8940 new_quads[0]->set_line_orientation(
8941 1, line_orientation[1]);
8942 new_quads[0]->set_line_orientation(
8943 2, line_orientation[2]);
8944 new_quads[0]->set_line_orientation(
8945 3, line_orientation[3]);
8946
8947 // the quads are numbered as follows:
8948 //
8949 // planes in the interior of the old hex:
8950 //
8951 // *
8952 // /|
8953 // / | x
8954 // / | *-------* *---------*
8955 // * | | | / /
8956 // | 0 | | | / /
8957 // | * | | / /
8958 // | / *-------*y *---------*x
8959 // | /
8960 // |/
8961 // *
8962 //
8963 // children of the faces of the old hex
8964 //
8965 // *---*---* *---*---*
8966 // /| | | / / /|
8967 // / | | | / 9 / 10/ |
8968 // / | 5 | 6 | / / / |
8969 // * | | | *---*---* |
8970 // | 1 *---*---* | | | 2 *
8971 // | / / / | | | /
8972 // | / 7 / 8 / | 3 | 4 | /
8973 // |/ / / | | |/
8974 // *---*---* *---*---*
8975 //
8976 // note that we have to take care of the
8977 // orientation of faces.
8978 const int quad_indices[11] = {
8979 new_quads[0]->index(), // 0
8980
8981 hex->face(0)->index(), // 1
8982
8983 hex->face(1)->index(), // 2
8984
8985 hex->face(2)->child_index(
8986 child_at_origin[hex->face(2)->refinement_case() -
8987 1][f_fl[2]][f_ro[2]]), // 3
8988 hex->face(2)->child_index(
8989 1 -
8990 child_at_origin[hex->face(2)->refinement_case() -
8991 1][f_fl[2]][f_ro[2]]),
8992
8993 hex->face(3)->child_index(
8994 child_at_origin[hex->face(3)->refinement_case() -
8995 1][f_fl[3]][f_ro[3]]), // 5
8996 hex->face(3)->child_index(
8997 1 -
8998 child_at_origin[hex->face(3)->refinement_case() -
8999 1][f_fl[3]][f_ro[3]]),
9000
9001 hex->face(4)->child_index(
9002 child_at_origin[hex->face(4)->refinement_case() -
9003 1][f_fl[4]][f_ro[4]]), // 7
9004 hex->face(4)->child_index(
9005 1 -
9006 child_at_origin[hex->face(4)->refinement_case() -
9007 1][f_fl[4]][f_ro[4]]),
9008
9009 hex->face(5)->child_index(
9010 child_at_origin[hex->face(5)->refinement_case() -
9011 1][f_fl[5]][f_ro[5]]), // 9
9012 hex->face(5)->child_index(
9013 1 -
9014 child_at_origin[hex->face(5)->refinement_case() -
9015 1][f_fl[5]][f_ro[5]])
9016
9017 };
9018
9019 new_hexes[0]->set_bounding_object_indices(
9020 {quad_indices[1],
9021 quad_indices[0],
9022 quad_indices[3],
9023 quad_indices[5],
9024 quad_indices[7],
9025 quad_indices[9]});
9026 new_hexes[1]->set_bounding_object_indices(
9027 {quad_indices[0],
9028 quad_indices[2],
9029 quad_indices[4],
9030 quad_indices[6],
9031 quad_indices[8],
9032 quad_indices[10]});
9033 break;
9034 }
9035
9037 {
9038 //----------------------------
9039 //
9040 // RefinementCase<dim>::cut_y
9041 //
9042 // the refined cube will look like this:
9043 //
9044 // *---------*
9045 // / /|
9046 // *---------* |
9047 // / /| |
9048 // *---------* | |
9049 // | | | |
9050 // | | | *
9051 // | | |/
9052 // | | *
9053 // | |/
9054 // *---------*
9055 //
9056 // again, first collect some data about the
9057 // indices of the lines, with the following
9058 // numbering:
9059
9060 // face 0: left plane
9061 // *
9062 // /|
9063 // * |
9064 // /| |
9065 // * | |
9066 // | 0 |
9067 // | | *
9068 // | |/
9069 // | *m0
9070 // |/
9071 // *
9072 // face 1: right plane
9073 // *
9074 // /|
9075 // m1* |
9076 // /| |
9077 // * | |
9078 // | 1 |
9079 // | | *
9080 // | |/
9081 // | *
9082 // |/
9083 // *
9084 // face 4: bottom plane
9085 // *-------*
9086 // / /
9087 // m0*---2---*
9088 // / /
9089 // *-------*
9090 // face 5: top plane
9091 // *-------*
9092 // / /
9093 // *---3---*m1
9094 // / /
9095 // *-------*
9096
9097 // set up a list of line iterators first. from
9098 // this, construct lists of line_indices and
9099 // line orientations later on
9100 const typename Triangulation<dim, spacedim>::
9101 raw_line_iterator lines[4] = {
9102 hex->face(0)->child(0)->line(
9103 (hex->face(0)->refinement_case() ==
9105 1 :
9106 3), // 0
9107 hex->face(1)->child(0)->line(
9108 (hex->face(1)->refinement_case() ==
9110 1 :
9111 3), // 1
9112 hex->face(4)->child(0)->line(
9113 (hex->face(4)->refinement_case() ==
9115 1 :
9116 3), // 2
9117 hex->face(5)->child(0)->line(
9118 (hex->face(5)->refinement_case() ==
9120 1 :
9121 3) // 3
9122 };
9123
9124 unsigned int line_indices[4];
9125 for (unsigned int i = 0; i < 4; ++i)
9126 line_indices[i] = lines[i]->index();
9127
9128 // the orientation of lines for the inner quads
9129 // is quite tricky. as these lines are newly
9130 // created ones and thus have no parents, they
9131 // cannot inherit this property. set up an array
9132 // and fill it with the respective values
9133 bool line_orientation[4];
9134
9135 // the middle vertex marked as m0 above is the
9136 // start vertex for lines 0 and 2 in standard
9137 // orientation, whereas m1 is the end vertex of
9138 // lines 1 and 3 in standard orientation
9139 const unsigned int middle_vertices[2] = {
9140 hex->line(0)->child(0)->vertex_index(1),
9141 hex->line(5)->child(0)->vertex_index(1)};
9142
9143 for (unsigned int i = 0; i < 4; ++i)
9144 if (lines[i]->vertex_index(i % 2) ==
9145 middle_vertices[i % 2])
9146 line_orientation[i] = true;
9147 else
9148 {
9149 // it must be the other way round then
9150 Assert(lines[i]->vertex_index((i + 1) % 2) ==
9151 middle_vertices[i % 2],
9153 line_orientation[i] = false;
9154 }
9155
9156 // set up the new quad, line numbering is as
9157 // indicated above
9158 new_quads[0]->set_bounding_object_indices(
9159 {line_indices[2],
9160 line_indices[3],
9161 line_indices[0],
9162 line_indices[1]});
9163
9164 new_quads[0]->set_line_orientation(
9165 0, line_orientation[2]);
9166 new_quads[0]->set_line_orientation(
9167 1, line_orientation[3]);
9168 new_quads[0]->set_line_orientation(
9169 2, line_orientation[0]);
9170 new_quads[0]->set_line_orientation(
9171 3, line_orientation[1]);
9172
9173 // the quads are numbered as follows:
9174 //
9175 // planes in the interior of the old hex:
9176 //
9177 // *
9178 // /|
9179 // / | x
9180 // / | *-------* *---------*
9181 // * | | | / /
9182 // | | | 0 | / /
9183 // | * | | / /
9184 // | / *-------*y *---------*x
9185 // | /
9186 // |/
9187 // *
9188 //
9189 // children of the faces of the old hex
9190 //
9191 // *-------* *-------*
9192 // /| | / 10 /|
9193 // * | | *-------* |
9194 // /| | 6 | / 9 /| |
9195 // * |2| | *-------* |4|
9196 // | | *-------* | | | *
9197 // |1|/ 8 / | |3|/
9198 // | *-------* | 5 | *
9199 // |/ 7 / | |/
9200 // *-------* *-------*
9201 //
9202 // note that we have to take care of the
9203 // orientation of faces.
9204 const int quad_indices[11] = {
9205 new_quads[0]->index(), // 0
9206
9207 hex->face(0)->child_index(
9208 child_at_origin[hex->face(0)->refinement_case() -
9209 1][f_fl[0]][f_ro[0]]), // 1
9210 hex->face(0)->child_index(
9211 1 -
9212 child_at_origin[hex->face(0)->refinement_case() -
9213 1][f_fl[0]][f_ro[0]]),
9214
9215 hex->face(1)->child_index(
9216 child_at_origin[hex->face(1)->refinement_case() -
9217 1][f_fl[1]][f_ro[1]]), // 3
9218 hex->face(1)->child_index(
9219 1 -
9220 child_at_origin[hex->face(1)->refinement_case() -
9221 1][f_fl[1]][f_ro[1]]),
9222
9223 hex->face(2)->index(), // 5
9224
9225 hex->face(3)->index(), // 6
9226
9227 hex->face(4)->child_index(
9228 child_at_origin[hex->face(4)->refinement_case() -
9229 1][f_fl[4]][f_ro[4]]), // 7
9230 hex->face(4)->child_index(
9231 1 -
9232 child_at_origin[hex->face(4)->refinement_case() -
9233 1][f_fl[4]][f_ro[4]]),
9234
9235 hex->face(5)->child_index(
9236 child_at_origin[hex->face(5)->refinement_case() -
9237 1][f_fl[5]][f_ro[5]]), // 9
9238 hex->face(5)->child_index(
9239 1 -
9240 child_at_origin[hex->face(5)->refinement_case() -
9241 1][f_fl[5]][f_ro[5]])
9242
9243 };
9244
9245 new_hexes[0]->set_bounding_object_indices(
9246 {quad_indices[1],
9247 quad_indices[3],
9248 quad_indices[5],
9249 quad_indices[0],
9250 quad_indices[7],
9251 quad_indices[9]});
9252 new_hexes[1]->set_bounding_object_indices(
9253 {quad_indices[2],
9254 quad_indices[4],
9255 quad_indices[0],
9256 quad_indices[6],
9257 quad_indices[8],
9258 quad_indices[10]});
9259 break;
9260 }
9261
9263 {
9264 //----------------------------
9265 //
9266 // RefinementCase<dim>::cut_z
9267 //
9268 // the refined cube will look like this:
9269 //
9270 // *---------*
9271 // / /|
9272 // / / |
9273 // / / *
9274 // *---------* /|
9275 // | | / |
9276 // | |/ *
9277 // *---------* /
9278 // | | /
9279 // | |/
9280 // *---------*
9281 //
9282 // again, first collect some data about the
9283 // indices of the lines, with the following
9284 // numbering:
9285
9286 // face 0: left plane
9287 // *
9288 // /|
9289 // / |
9290 // / *
9291 // * /|
9292 // | 0 |
9293 // |/ *
9294 // m0* /
9295 // | /
9296 // |/
9297 // *
9298 // face 1: right plane
9299 // *
9300 // /|
9301 // / |
9302 // / *m1
9303 // * /|
9304 // | 1 |
9305 // |/ *
9306 // * /
9307 // | /
9308 // |/
9309 // *
9310 // face 2: front plane
9311 // (note: x,y exchanged)
9312 // *-------*
9313 // | |
9314 // m0*---2---*
9315 // | |
9316 // *-------*
9317 // face 3: back plane
9318 // (note: x,y exchanged)
9319 // *-------*
9320 // | |
9321 // *---3---*m1
9322 // | |
9323 // *-------*
9324
9325 // set up a list of line iterators first. from
9326 // this, construct lists of line_indices and
9327 // line orientations later on
9328 const typename Triangulation<dim, spacedim>::
9329 raw_line_iterator lines[4] = {
9330 hex->face(0)->child(0)->line(
9331 (hex->face(0)->refinement_case() ==
9333 1 :
9334 3), // 0
9335 hex->face(1)->child(0)->line(
9336 (hex->face(1)->refinement_case() ==
9338 1 :
9339 3), // 1
9340 hex->face(2)->child(0)->line(
9341 (hex->face(2)->refinement_case() ==
9343 1 :
9344 3), // 2
9345 hex->face(3)->child(0)->line(
9346 (hex->face(3)->refinement_case() ==
9348 1 :
9349 3) // 3
9350 };
9351
9352 unsigned int line_indices[4];
9353 for (unsigned int i = 0; i < 4; ++i)
9354 line_indices[i] = lines[i]->index();
9355
9356 // the orientation of lines for the inner quads
9357 // is quite tricky. as these lines are newly
9358 // created ones and thus have no parents, they
9359 // cannot inherit this property. set up an array
9360 // and fill it with the respective values
9361 bool line_orientation[4];
9362
9363 // the middle vertex marked as m0 above is the
9364 // start vertex for lines 0 and 2 in standard
9365 // orientation, whereas m1 is the end vertex of
9366 // lines 1 and 3 in standard orientation
9367 const unsigned int middle_vertices[2] = {
9368 middle_vertex_index<dim, spacedim>(hex->line(8)),
9369 middle_vertex_index<dim, spacedim>(hex->line(11))};
9370
9371 for (unsigned int i = 0; i < 4; ++i)
9372 if (lines[i]->vertex_index(i % 2) ==
9373 middle_vertices[i % 2])
9374 line_orientation[i] = true;
9375 else
9376 {
9377 // it must be the other way round then
9378 Assert(lines[i]->vertex_index((i + 1) % 2) ==
9379 middle_vertices[i % 2],
9381 line_orientation[i] = false;
9382 }
9383
9384 // set up the new quad, line numbering is as
9385 // indicated above
9386 new_quads[0]->set_bounding_object_indices(
9387 {line_indices[0],
9388 line_indices[1],
9389 line_indices[2],
9390 line_indices[3]});
9391
9392 new_quads[0]->set_line_orientation(
9393 0, line_orientation[0]);
9394 new_quads[0]->set_line_orientation(
9395 1, line_orientation[1]);
9396 new_quads[0]->set_line_orientation(
9397 2, line_orientation[2]);
9398 new_quads[0]->set_line_orientation(
9399 3, line_orientation[3]);
9400
9401 // the quads are numbered as follows:
9402 //
9403 // planes in the interior of the old hex:
9404 //
9405 // *
9406 // /|
9407 // / | x
9408 // / | *-------* *---------*
9409 // * | | | / /
9410 // | | | | / 0 /
9411 // | * | | / /
9412 // | / *-------*y *---------*x
9413 // | /
9414 // |/
9415 // *
9416 //
9417 // children of the faces of the old hex
9418 //
9419 // *---*---* *-------*
9420 // /| 8 | / /|
9421 // / | | / 10 / |
9422 // / *-------* / / *
9423 // * 2/| | *-------* 4/|
9424 // | / | 7 | | 6 | / |
9425 // |/1 *-------* | |/3 *
9426 // * / / *-------* /
9427 // | / 9 / | | /
9428 // |/ / | 5 |/
9429 // *-------* *---*---*
9430 //
9431 // note that we have to take care of the
9432 // orientation of faces.
9433 const int quad_indices[11] = {
9434 new_quads[0]->index(), // 0
9435
9436 hex->face(0)->child_index(
9437 child_at_origin[hex->face(0)->refinement_case() -
9438 1][f_fl[0]][f_ro[0]]), // 1
9439 hex->face(0)->child_index(
9440 1 -
9441 child_at_origin[hex->face(0)->refinement_case() -
9442 1][f_fl[0]][f_ro[0]]),
9443
9444 hex->face(1)->child_index(
9445 child_at_origin[hex->face(1)->refinement_case() -
9446 1][f_fl[1]][f_ro[1]]), // 3
9447 hex->face(1)->child_index(
9448 1 -
9449 child_at_origin[hex->face(1)->refinement_case() -
9450 1][f_fl[1]][f_ro[1]]),
9451
9452 hex->face(2)->child_index(
9453 child_at_origin[hex->face(2)->refinement_case() -
9454 1][f_fl[2]][f_ro[2]]), // 5
9455 hex->face(2)->child_index(
9456 1 -
9457 child_at_origin[hex->face(2)->refinement_case() -
9458 1][f_fl[2]][f_ro[2]]),
9459
9460 hex->face(3)->child_index(
9461 child_at_origin[hex->face(3)->refinement_case() -
9462 1][f_fl[3]][f_ro[3]]), // 7
9463 hex->face(3)->child_index(
9464 1 -
9465 child_at_origin[hex->face(3)->refinement_case() -
9466 1][f_fl[3]][f_ro[3]]),
9467
9468 hex->face(4)->index(), // 9
9469
9470 hex->face(5)->index() // 10
9471 };
9472
9473 new_hexes[0]->set_bounding_object_indices(
9474 {quad_indices[1],
9475 quad_indices[3],
9476 quad_indices[5],
9477 quad_indices[7],
9478 quad_indices[9],
9479 quad_indices[0]});
9480 new_hexes[1]->set_bounding_object_indices(
9481 {quad_indices[2],
9482 quad_indices[4],
9483 quad_indices[6],
9484 quad_indices[8],
9485 quad_indices[0],
9486 quad_indices[10]});
9487 break;
9488 }
9489
9491 {
9492 //----------------------------
9493 //
9494 // RefinementCase<dim>::cut_xy
9495 //
9496 // the refined cube will look like this:
9497 //
9498 // *----*----*
9499 // / / /|
9500 // *----*----* |
9501 // / / /| |
9502 // *----*----* | |
9503 // | | | | |
9504 // | | | | *
9505 // | | | |/
9506 // | | | *
9507 // | | |/
9508 // *----*----*
9509 //
9510
9511 // first, create the new internal line
9512 new_lines[0]->set_bounding_object_indices(
9513 {middle_vertex_index<dim, spacedim>(hex->face(4)),
9514 middle_vertex_index<dim, spacedim>(hex->face(5))});
9515
9516 // again, first collect some data about the
9517 // indices of the lines, with the following
9518 // numbering:
9519
9520 // face 0: left plane
9521 // *
9522 // /|
9523 // * |
9524 // /| |
9525 // * | |
9526 // | 0 |
9527 // | | *
9528 // | |/
9529 // | *
9530 // |/
9531 // *
9532 // face 1: right plane
9533 // *
9534 // /|
9535 // * |
9536 // /| |
9537 // * | |
9538 // | 1 |
9539 // | | *
9540 // | |/
9541 // | *
9542 // |/
9543 // *
9544 // face 2: front plane
9545 // (note: x,y exchanged)
9546 // *---*---*
9547 // | | |
9548 // | 2 |
9549 // | | |
9550 // *-------*
9551 // face 3: back plane
9552 // (note: x,y exchanged)
9553 // *---*---*
9554 // | | |
9555 // | 3 |
9556 // | | |
9557 // *---*---*
9558 // face 4: bottom plane
9559 // *---*---*
9560 // / 5 /
9561 // *-6-*-7-*
9562 // / 4 /
9563 // *---*---*
9564 // face 5: top plane
9565 // *---*---*
9566 // / 9 /
9567 // *10-*-11*
9568 // / 8 /
9569 // *---*---*
9570 // middle planes
9571 // *-------* *---*---*
9572 // / / | | |
9573 // / / | 12 |
9574 // / / | | |
9575 // *-------* *---*---*
9576
9577 // set up a list of line iterators first. from
9578 // this, construct lists of line_indices and
9579 // line orientations later on
9580 const typename Triangulation<
9581 dim,
9582 spacedim>::raw_line_iterator lines[13] = {
9583 hex->face(0)->child(0)->line(
9584 (hex->face(0)->refinement_case() ==
9586 1 :
9587 3), // 0
9588 hex->face(1)->child(0)->line(
9589 (hex->face(1)->refinement_case() ==
9591 1 :
9592 3), // 1
9593 hex->face(2)->child(0)->line(
9594 (hex->face(2)->refinement_case() ==
9596 1 :
9597 3), // 2
9598 hex->face(3)->child(0)->line(
9599 (hex->face(3)->refinement_case() ==
9601 1 :
9602 3), // 3
9603
9604 hex->face(4)
9605 ->isotropic_child(
9607 0, f_or[4], f_fl[4], f_ro[4]))
9608 ->line(
9610 1, f_or[4], f_fl[4], f_ro[4])), // 4
9611 hex->face(4)
9612 ->isotropic_child(
9614 3, f_or[4], f_fl[4], f_ro[4]))
9615 ->line(
9617 0, f_or[4], f_fl[4], f_ro[4])), // 5
9618 hex->face(4)
9619 ->isotropic_child(
9621 0, f_or[4], f_fl[4], f_ro[4]))
9622 ->line(
9624 3, f_or[4], f_fl[4], f_ro[4])), // 6
9625 hex->face(4)
9626 ->isotropic_child(
9628 3, f_or[4], f_fl[4], f_ro[4]))
9629 ->line(
9631 2, f_or[4], f_fl[4], f_ro[4])), // 7
9632
9633 hex->face(5)
9634 ->isotropic_child(
9636 0, f_or[5], f_fl[5], f_ro[5]))
9637 ->line(
9639 1, f_or[5], f_fl[5], f_ro[5])), // 8
9640 hex->face(5)
9641 ->isotropic_child(
9643 3, f_or[5], f_fl[5], f_ro[5]))
9644 ->line(
9646 0, f_or[5], f_fl[5], f_ro[5])), // 9
9647 hex->face(5)
9648 ->isotropic_child(
9650 0, f_or[5], f_fl[5], f_ro[5]))
9651 ->line(
9653 3, f_or[5], f_fl[5], f_ro[5])), // 10
9654 hex->face(5)
9655 ->isotropic_child(
9657 3, f_or[5], f_fl[5], f_ro[5]))
9658 ->line(
9660 2, f_or[5], f_fl[5], f_ro[5])), // 11
9661
9662 new_lines[0] // 12
9663 };
9664
9665 unsigned int line_indices[13];
9666 for (unsigned int i = 0; i < 13; ++i)
9667 line_indices[i] = lines[i]->index();
9668
9669 // the orientation of lines for the inner quads
9670 // is quite tricky. as these lines are newly
9671 // created ones and thus have no parents, they
9672 // cannot inherit this property. set up an array
9673 // and fill it with the respective values
9674 bool line_orientation[13];
9675
9676 // the middle vertices of the lines of our
9677 // bottom face
9678 const unsigned int middle_vertices[4] = {
9679 hex->line(0)->child(0)->vertex_index(1),
9680 hex->line(1)->child(0)->vertex_index(1),
9681 hex->line(2)->child(0)->vertex_index(1),
9682 hex->line(3)->child(0)->vertex_index(1),
9683 };
9684
9685 // note: for lines 0 to 3 the orientation of the
9686 // line is 'true', if vertex 0 is on the bottom
9687 // face
9688 for (unsigned int i = 0; i < 4; ++i)
9689 if (lines[i]->vertex_index(0) == middle_vertices[i])
9690 line_orientation[i] = true;
9691 else
9692 {
9693 // it must be the other way round then
9694 Assert(lines[i]->vertex_index(1) ==
9695 middle_vertices[i],
9697 line_orientation[i] = false;
9698 }
9699
9700 // note: for lines 4 to 11 (inner lines of the
9701 // outer quads) the following holds: the second
9702 // vertex of the even lines in standard
9703 // orientation is the vertex in the middle of
9704 // the quad, whereas for odd lines the first
9705 // vertex is the same middle vertex.
9706 for (unsigned int i = 4; i < 12; ++i)
9707 if (lines[i]->vertex_index((i + 1) % 2) ==
9708 middle_vertex_index<dim, spacedim>(
9709 hex->face(3 + i / 4)))
9710 line_orientation[i] = true;
9711 else
9712 {
9713 // it must be the other way
9714 // round then
9715 Assert(lines[i]->vertex_index(i % 2) ==
9716 (middle_vertex_index<dim, spacedim>(
9717 hex->face(3 + i / 4))),
9719 line_orientation[i] = false;
9720 }
9721 // for the last line the line orientation is
9722 // always true, since it was just constructed
9723 // that way
9724 line_orientation[12] = true;
9725
9726 // set up the 4 quads, numbered as follows (left
9727 // quad numbering, right line numbering
9728 // extracted from above)
9729 //
9730 // * *
9731 // /| 9|
9732 // * | * |
9733 // y/| | 8| 3
9734 // * |1| * | |
9735 // | | |x | 12|
9736 // |0| * | | *
9737 // | |/ 2 |5
9738 // | * | *
9739 // |/ |4
9740 // * *
9741 //
9742 // x
9743 // *---*---* *10-*-11*
9744 // | | | | | |
9745 // | 2 | 3 | 0 12 1
9746 // | | | | | |
9747 // *---*---*y *-6-*-7-*
9748
9749 new_quads[0]->set_bounding_object_indices(
9750 {line_indices[2],
9751 line_indices[12],
9752 line_indices[4],
9753 line_indices[8]});
9754 new_quads[1]->set_bounding_object_indices(
9755 {line_indices[12],
9756 line_indices[3],
9757 line_indices[5],
9758 line_indices[9]});
9759 new_quads[2]->set_bounding_object_indices(
9760 {line_indices[6],
9761 line_indices[10],
9762 line_indices[0],
9763 line_indices[12]});
9764 new_quads[3]->set_bounding_object_indices(
9765 {line_indices[7],
9766 line_indices[11],
9767 line_indices[12],
9768 line_indices[1]});
9769
9770 new_quads[0]->set_line_orientation(
9771 0, line_orientation[2]);
9772 new_quads[0]->set_line_orientation(
9773 2, line_orientation[4]);
9774 new_quads[0]->set_line_orientation(
9775 3, line_orientation[8]);
9776
9777 new_quads[1]->set_line_orientation(
9778 1, line_orientation[3]);
9779 new_quads[1]->set_line_orientation(
9780 2, line_orientation[5]);
9781 new_quads[1]->set_line_orientation(
9782 3, line_orientation[9]);
9783
9784 new_quads[2]->set_line_orientation(
9785 0, line_orientation[6]);
9786 new_quads[2]->set_line_orientation(
9787 1, line_orientation[10]);
9788 new_quads[2]->set_line_orientation(
9789 2, line_orientation[0]);
9790
9791 new_quads[3]->set_line_orientation(
9792 0, line_orientation[7]);
9793 new_quads[3]->set_line_orientation(
9794 1, line_orientation[11]);
9795 new_quads[3]->set_line_orientation(
9796 3, line_orientation[1]);
9797
9798 // the quads are numbered as follows:
9799 //
9800 // planes in the interior of the old hex:
9801 //
9802 // *
9803 // /|
9804 // * | x
9805 // /| | *---*---* *---------*
9806 // * |1| | | | / /
9807 // | | | | 2 | 3 | / /
9808 // |0| * | | | / /
9809 // | |/ *---*---*y *---------*x
9810 // | *
9811 // |/
9812 // *
9813 //
9814 // children of the faces of the old hex
9815 //
9816 // *---*---* *---*---*
9817 // /| | | /18 / 19/|
9818 // * |10 | 11| /---/---* |
9819 // /| | | | /16 / 17/| |
9820 // * |5| | | *---*---* |7|
9821 // | | *---*---* | | | | *
9822 // |4|/14 / 15/ | | |6|/
9823 // | *---/---/ | 8 | 9 | *
9824 // |/12 / 13/ | | |/
9825 // *---*---* *---*---*
9826 //
9827 // note that we have to take care of the
9828 // orientation of faces.
9829 const int quad_indices[20] = {
9830 new_quads[0]->index(), // 0
9831 new_quads[1]->index(),
9832 new_quads[2]->index(),
9833 new_quads[3]->index(),
9834
9835 hex->face(0)->child_index(
9836 child_at_origin[hex->face(0)->refinement_case() -
9837 1][f_fl[0]][f_ro[0]]), // 4
9838 hex->face(0)->child_index(
9839 1 -
9840 child_at_origin[hex->face(0)->refinement_case() -
9841 1][f_fl[0]][f_ro[0]]),
9842
9843 hex->face(1)->child_index(
9844 child_at_origin[hex->face(1)->refinement_case() -
9845 1][f_fl[1]][f_ro[1]]), // 6
9846 hex->face(1)->child_index(
9847 1 -
9848 child_at_origin[hex->face(1)->refinement_case() -
9849 1][f_fl[1]][f_ro[1]]),
9850
9851 hex->face(2)->child_index(
9852 child_at_origin[hex->face(2)->refinement_case() -
9853 1][f_fl[2]][f_ro[2]]), // 8
9854 hex->face(2)->child_index(
9855 1 -
9856 child_at_origin[hex->face(2)->refinement_case() -
9857 1][f_fl[2]][f_ro[2]]),
9858
9859 hex->face(3)->child_index(
9860 child_at_origin[hex->face(3)->refinement_case() -
9861 1][f_fl[3]][f_ro[3]]), // 10
9862 hex->face(3)->child_index(
9863 1 -
9864 child_at_origin[hex->face(3)->refinement_case() -
9865 1][f_fl[3]][f_ro[3]]),
9866
9867 hex->face(4)->isotropic_child_index(
9869 0, f_or[4], f_fl[4], f_ro[4])), // 12
9870 hex->face(4)->isotropic_child_index(
9872 1, f_or[4], f_fl[4], f_ro[4])),
9873 hex->face(4)->isotropic_child_index(
9875 2, f_or[4], f_fl[4], f_ro[4])),
9876 hex->face(4)->isotropic_child_index(
9878 3, f_or[4], f_fl[4], f_ro[4])),
9879
9880 hex->face(5)->isotropic_child_index(
9882 0, f_or[5], f_fl[5], f_ro[5])), // 16
9883 hex->face(5)->isotropic_child_index(
9885 1, f_or[5], f_fl[5], f_ro[5])),
9886 hex->face(5)->isotropic_child_index(
9888 2, f_or[5], f_fl[5], f_ro[5])),
9889 hex->face(5)->isotropic_child_index(
9891 3, f_or[5], f_fl[5], f_ro[5]))};
9892
9893 new_hexes[0]->set_bounding_object_indices(
9894 {quad_indices[4],
9895 quad_indices[0],
9896 quad_indices[8],
9897 quad_indices[2],
9898 quad_indices[12],
9899 quad_indices[16]});
9900 new_hexes[1]->set_bounding_object_indices(
9901 {quad_indices[0],
9902 quad_indices[6],
9903 quad_indices[9],
9904 quad_indices[3],
9905 quad_indices[13],
9906 quad_indices[17]});
9907 new_hexes[2]->set_bounding_object_indices(
9908 {quad_indices[5],
9909 quad_indices[1],
9910 quad_indices[2],
9911 quad_indices[10],
9912 quad_indices[14],
9913 quad_indices[18]});
9914 new_hexes[3]->set_bounding_object_indices(
9915 {quad_indices[1],
9916 quad_indices[7],
9917 quad_indices[3],
9918 quad_indices[11],
9919 quad_indices[15],
9920 quad_indices[19]});
9921 break;
9922 }
9923
9925 {
9926 //----------------------------
9927 //
9928 // RefinementCase<dim>::cut_xz
9929 //
9930 // the refined cube will look like this:
9931 //
9932 // *----*----*
9933 // / / /|
9934 // / / / |
9935 // / / / *
9936 // *----*----* /|
9937 // | | | / |
9938 // | | |/ *
9939 // *----*----* /
9940 // | | | /
9941 // | | |/
9942 // *----*----*
9943 //
9944
9945 // first, create the new internal line
9946 new_lines[0]->set_bounding_object_indices(
9947 {middle_vertex_index<dim, spacedim>(hex->face(2)),
9948 middle_vertex_index<dim, spacedim>(hex->face(3))});
9949
9950 // again, first collect some data about the
9951 // indices of the lines, with the following
9952 // numbering:
9953
9954 // face 0: left plane
9955 // *
9956 // /|
9957 // / |
9958 // / *
9959 // * /|
9960 // | 0 |
9961 // |/ *
9962 // * /
9963 // | /
9964 // |/
9965 // *
9966 // face 1: right plane
9967 // *
9968 // /|
9969 // / |
9970 // / *
9971 // * /|
9972 // | 1 |
9973 // |/ *
9974 // * /
9975 // | /
9976 // |/
9977 // *
9978 // face 2: front plane
9979 // (note: x,y exchanged)
9980 // *---*---*
9981 // | 5 |
9982 // *-6-*-7-*
9983 // | 4 |
9984 // *---*---*
9985 // face 3: back plane
9986 // (note: x,y exchanged)
9987 // *---*---*
9988 // | 9 |
9989 // *10-*-11*
9990 // | 8 |
9991 // *---*---*
9992 // face 4: bottom plane
9993 // *---*---*
9994 // / / /
9995 // / 2 /
9996 // / / /
9997 // *---*---*
9998 // face 5: top plane
9999 // *---*---*
10000 // / / /
10001 // / 3 /
10002 // / / /
10003 // *---*---*
10004 // middle planes
10005 // *---*---* *-------*
10006 // / / / | |
10007 // / 12 / | |
10008 // / / / | |
10009 // *---*---* *-------*
10010
10011 // set up a list of line iterators first. from
10012 // this, construct lists of line_indices and
10013 // line orientations later on
10014 const typename Triangulation<
10015 dim,
10016 spacedim>::raw_line_iterator lines[13] = {
10017 hex->face(0)->child(0)->line(
10018 (hex->face(0)->refinement_case() ==
10020 1 :
10021 3), // 0
10022 hex->face(1)->child(0)->line(
10023 (hex->face(1)->refinement_case() ==
10025 1 :
10026 3), // 1
10027 hex->face(4)->child(0)->line(
10028 (hex->face(4)->refinement_case() ==
10030 1 :
10031 3), // 2
10032 hex->face(5)->child(0)->line(
10033 (hex->face(5)->refinement_case() ==
10035 1 :
10036 3), // 3
10037
10038 hex->face(2)
10039 ->isotropic_child(
10041 0, f_or[2], f_fl[2], f_ro[2]))
10042 ->line(
10044 3, f_or[2], f_fl[2], f_ro[2])), // 4
10045 hex->face(2)
10046 ->isotropic_child(
10048 3, f_or[2], f_fl[2], f_ro[2]))
10049 ->line(
10051 2, f_or[2], f_fl[2], f_ro[2])), // 5
10052 hex->face(2)
10053 ->isotropic_child(
10055 0, f_or[2], f_fl[2], f_ro[2]))
10056 ->line(
10058 1, f_or[2], f_fl[2], f_ro[2])), // 6
10059 hex->face(2)
10060 ->isotropic_child(
10062 3, f_or[2], f_fl[2], f_ro[2]))
10063 ->line(
10065 0, f_or[2], f_fl[2], f_ro[2])), // 7
10066
10067 hex->face(3)
10068 ->isotropic_child(
10070 0, f_or[3], f_fl[3], f_ro[3]))
10071 ->line(
10073 3, f_or[3], f_fl[3], f_ro[3])), // 8
10074 hex->face(3)
10075 ->isotropic_child(
10077 3, f_or[3], f_fl[3], f_ro[3]))
10078 ->line(
10080 2, f_or[3], f_fl[3], f_ro[3])), // 9
10081 hex->face(3)
10082 ->isotropic_child(
10084 0, f_or[3], f_fl[3], f_ro[3]))
10085 ->line(
10087 1, f_or[3], f_fl[3], f_ro[3])), // 10
10088 hex->face(3)
10089 ->isotropic_child(
10091 3, f_or[3], f_fl[3], f_ro[3]))
10092 ->line(
10094 0, f_or[3], f_fl[3], f_ro[3])), // 11
10095
10096 new_lines[0] // 12
10097 };
10098
10099 unsigned int line_indices[13];
10100 for (unsigned int i = 0; i < 13; ++i)
10101 line_indices[i] = lines[i]->index();
10102
10103 // the orientation of lines for the inner quads
10104 // is quite tricky. as these lines are newly
10105 // created ones and thus have no parents, they
10106 // cannot inherit this property. set up an array
10107 // and fill it with the respective values
10108 bool line_orientation[13];
10109
10110 // the middle vertices of the
10111 // lines of our front face
10112 const unsigned int middle_vertices[4] = {
10113 hex->line(8)->child(0)->vertex_index(1),
10114 hex->line(9)->child(0)->vertex_index(1),
10115 hex->line(2)->child(0)->vertex_index(1),
10116 hex->line(6)->child(0)->vertex_index(1),
10117 };
10118
10119 // note: for lines 0 to 3 the orientation of the
10120 // line is 'true', if vertex 0 is on the front
10121 for (unsigned int i = 0; i < 4; ++i)
10122 if (lines[i]->vertex_index(0) == middle_vertices[i])
10123 line_orientation[i] = true;
10124 else
10125 {
10126 // it must be the other way round then
10127 Assert(lines[i]->vertex_index(1) ==
10128 middle_vertices[i],
10130 line_orientation[i] = false;
10131 }
10132
10133 // note: for lines 4 to 11 (inner lines of the
10134 // outer quads) the following holds: the second
10135 // vertex of the even lines in standard
10136 // orientation is the vertex in the middle of
10137 // the quad, whereas for odd lines the first
10138 // vertex is the same middle vertex.
10139 for (unsigned int i = 4; i < 12; ++i)
10140 if (lines[i]->vertex_index((i + 1) % 2) ==
10141 middle_vertex_index<dim, spacedim>(
10142 hex->face(1 + i / 4)))
10143 line_orientation[i] = true;
10144 else
10145 {
10146 // it must be the other way
10147 // round then
10148 Assert(lines[i]->vertex_index(i % 2) ==
10149 (middle_vertex_index<dim, spacedim>(
10150 hex->face(1 + i / 4))),
10152 line_orientation[i] = false;
10153 }
10154 // for the last line the line orientation is
10155 // always true, since it was just constructed
10156 // that way
10157 line_orientation[12] = true;
10158
10159 // set up the 4 quads, numbered as follows (left
10160 // quad numbering, right line numbering
10161 // extracted from above), the drawings denote
10162 // middle planes
10163 //
10164 // * *
10165 // /| /|
10166 // / | 3 9
10167 // y/ * / *
10168 // * 3/| * /|
10169 // | / |x 5 12|8
10170 // |/ * |/ *
10171 // * 2/ * /
10172 // | / 4 2
10173 // |/ |/
10174 // * *
10175 //
10176 // y
10177 // *----*----* *-10-*-11-*
10178 // / / / / / /
10179 // / 0 / 1 / 0 12 1
10180 // / / / / / /
10181 // *----*----*x *--6-*--7-*
10182
10183 new_quads[0]->set_bounding_object_indices(
10184 {line_indices[0],
10185 line_indices[12],
10186 line_indices[6],
10187 line_indices[10]});
10188 new_quads[1]->set_bounding_object_indices(
10189 {line_indices[12],
10190 line_indices[1],
10191 line_indices[7],
10192 line_indices[11]});
10193 new_quads[2]->set_bounding_object_indices(
10194 {line_indices[4],
10195 line_indices[8],
10196 line_indices[2],
10197 line_indices[12]});
10198 new_quads[3]->set_bounding_object_indices(
10199 {line_indices[5],
10200 line_indices[9],
10201 line_indices[12],
10202 line_indices[3]});
10203
10204 new_quads[0]->set_line_orientation(
10205 0, line_orientation[0]);
10206 new_quads[0]->set_line_orientation(
10207 2, line_orientation[6]);
10208 new_quads[0]->set_line_orientation(
10209 3, line_orientation[10]);
10210
10211 new_quads[1]->set_line_orientation(
10212 1, line_orientation[1]);
10213 new_quads[1]->set_line_orientation(
10214 2, line_orientation[7]);
10215 new_quads[1]->set_line_orientation(
10216 3, line_orientation[11]);
10217
10218 new_quads[2]->set_line_orientation(
10219 0, line_orientation[4]);
10220 new_quads[2]->set_line_orientation(
10221 1, line_orientation[8]);
10222 new_quads[2]->set_line_orientation(
10223 2, line_orientation[2]);
10224
10225 new_quads[3]->set_line_orientation(
10226 0, line_orientation[5]);
10227 new_quads[3]->set_line_orientation(
10228 1, line_orientation[9]);
10229 new_quads[3]->set_line_orientation(
10230 3, line_orientation[3]);
10231
10232 // the quads are numbered as follows:
10233 //
10234 // planes in the interior of the old hex:
10235 //
10236 // *
10237 // /|
10238 // / | x
10239 // /3 * *-------* *----*----*
10240 // * /| | | / / /
10241 // | / | | | / 0 / 1 /
10242 // |/ * | | / / /
10243 // * 2/ *-------*y *----*----*x
10244 // | /
10245 // |/
10246 // *
10247 //
10248 // children of the faces
10249 // of the old hex
10250 // *---*---* *---*---*
10251 // /|13 | 15| / / /|
10252 // / | | | /18 / 19/ |
10253 // / *---*---* / / / *
10254 // * 5/| | | *---*---* 7/|
10255 // | / |12 | 14| | 9 | 11| / |
10256 // |/4 *---*---* | | |/6 *
10257 // * / / / *---*---* /
10258 // | /16 / 17/ | | | /
10259 // |/ / / | 8 | 10|/
10260 // *---*---* *---*---*
10261 //
10262 // note that we have to take care of the
10263 // orientation of faces.
10264 const int quad_indices[20] = {
10265 new_quads[0]->index(), // 0
10266 new_quads[1]->index(),
10267 new_quads[2]->index(),
10268 new_quads[3]->index(),
10269
10270 hex->face(0)->child_index(
10271 child_at_origin[hex->face(0)->refinement_case() -
10272 1][f_fl[0]][f_ro[0]]), // 4
10273 hex->face(0)->child_index(
10274 1 -
10275 child_at_origin[hex->face(0)->refinement_case() -
10276 1][f_fl[0]][f_ro[0]]),
10277
10278 hex->face(1)->child_index(
10279 child_at_origin[hex->face(1)->refinement_case() -
10280 1][f_fl[1]][f_ro[1]]), // 6
10281 hex->face(1)->child_index(
10282 1 -
10283 child_at_origin[hex->face(1)->refinement_case() -
10284 1][f_fl[1]][f_ro[1]]),
10285
10286 hex->face(2)->isotropic_child_index(
10288 0, f_or[2], f_fl[2], f_ro[2])), // 8
10289 hex->face(2)->isotropic_child_index(
10291 1, f_or[2], f_fl[2], f_ro[2])),
10292 hex->face(2)->isotropic_child_index(
10294 2, f_or[2], f_fl[2], f_ro[2])),
10295 hex->face(2)->isotropic_child_index(
10297 3, f_or[2], f_fl[2], f_ro[2])),
10298
10299 hex->face(3)->isotropic_child_index(
10301 0, f_or[3], f_fl[3], f_ro[3])), // 12
10302 hex->face(3)->isotropic_child_index(
10304 1, f_or[3], f_fl[3], f_ro[3])),
10305 hex->face(3)->isotropic_child_index(
10307 2, f_or[3], f_fl[3], f_ro[3])),
10308 hex->face(3)->isotropic_child_index(
10310 3, f_or[3], f_fl[3], f_ro[3])),
10311
10312 hex->face(4)->child_index(
10313 child_at_origin[hex->face(4)->refinement_case() -
10314 1][f_fl[4]][f_ro[4]]), // 16
10315 hex->face(4)->child_index(
10316 1 -
10317 child_at_origin[hex->face(4)->refinement_case() -
10318 1][f_fl[4]][f_ro[4]]),
10319
10320 hex->face(5)->child_index(
10321 child_at_origin[hex->face(5)->refinement_case() -
10322 1][f_fl[5]][f_ro[5]]), // 18
10323 hex->face(5)->child_index(
10324 1 -
10325 child_at_origin[hex->face(5)->refinement_case() -
10326 1][f_fl[5]][f_ro[5]])};
10327
10328 // due to the exchange of x and y for the front
10329 // and back face, we order the children
10330 // according to
10331 //
10332 // *---*---*
10333 // | 1 | 3 |
10334 // *---*---*
10335 // | 0 | 2 |
10336 // *---*---*
10337 new_hexes[0]->set_bounding_object_indices(
10338 {quad_indices[4],
10339 quad_indices[2],
10340 quad_indices[8],
10341 quad_indices[12],
10342 quad_indices[16],
10343 quad_indices[0]});
10344 new_hexes[1]->set_bounding_object_indices(
10345 {quad_indices[5],
10346 quad_indices[3],
10347 quad_indices[9],
10348 quad_indices[13],
10349 quad_indices[0],
10350 quad_indices[18]});
10351 new_hexes[2]->set_bounding_object_indices(
10352 {quad_indices[2],
10353 quad_indices[6],
10354 quad_indices[10],
10355 quad_indices[14],
10356 quad_indices[17],
10357 quad_indices[1]});
10358 new_hexes[3]->set_bounding_object_indices(
10359 {quad_indices[3],
10360 quad_indices[7],
10361 quad_indices[11],
10362 quad_indices[15],
10363 quad_indices[1],
10364 quad_indices[19]});
10365 break;
10366 }
10367
10369 {
10370 //----------------------------
10371 //
10372 // RefinementCase<dim>::cut_yz
10373 //
10374 // the refined cube will look like this:
10375 //
10376 // *---------*
10377 // / /|
10378 // *---------* |
10379 // / /| |
10380 // *---------* |/|
10381 // | | * |
10382 // | |/| *
10383 // *---------* |/
10384 // | | *
10385 // | |/
10386 // *---------*
10387 //
10388
10389 // first, create the new
10390 // internal line
10391 new_lines[0]->set_bounding_object_indices(
10392
10393 {middle_vertex_index<dim, spacedim>(hex->face(0)),
10394 middle_vertex_index<dim, spacedim>(hex->face(1))});
10395
10396 // again, first collect some data about the
10397 // indices of the lines, with the following
10398 // numbering: (note that face 0 and 1 each are
10399 // shown twice for better readability)
10400
10401 // face 0: left plane
10402 // * *
10403 // /| /|
10404 // * | * |
10405 // /| * /| *
10406 // * 5/| * |7|
10407 // | * | | * |
10408 // |/| * |6| *
10409 // * 4/ * |/
10410 // | * | *
10411 // |/ |/
10412 // * *
10413 // face 1: right plane
10414 // * *
10415 // /| /|
10416 // * | * |
10417 // /| * /| *
10418 // * 9/| * |11
10419 // | * | | * |
10420 // |/| * |10 *
10421 // * 8/ * |/
10422 // | * | *
10423 // |/ |/
10424 // * *
10425 // face 2: front plane
10426 // (note: x,y exchanged)
10427 // *-------*
10428 // | |
10429 // *---0---*
10430 // | |
10431 // *-------*
10432 // face 3: back plane
10433 // (note: x,y exchanged)
10434 // *-------*
10435 // | |
10436 // *---1---*
10437 // | |
10438 // *-------*
10439 // face 4: bottom plane
10440 // *-------*
10441 // / /
10442 // *---2---*
10443 // / /
10444 // *-------*
10445 // face 5: top plane
10446 // *-------*
10447 // / /
10448 // *---3---*
10449 // / /
10450 // *-------*
10451 // middle planes
10452 // *-------* *-------*
10453 // / / | |
10454 // *---12--* | |
10455 // / / | |
10456 // *-------* *-------*
10457
10458 // set up a list of line iterators first. from
10459 // this, construct lists of line_indices and
10460 // line orientations later on
10461 const typename Triangulation<
10462 dim,
10463 spacedim>::raw_line_iterator lines[13] = {
10464 hex->face(2)->child(0)->line(
10465 (hex->face(2)->refinement_case() ==
10467 1 :
10468 3), // 0
10469 hex->face(3)->child(0)->line(
10470 (hex->face(3)->refinement_case() ==
10472 1 :
10473 3), // 1
10474 hex->face(4)->child(0)->line(
10475 (hex->face(4)->refinement_case() ==
10477 1 :
10478 3), // 2
10479 hex->face(5)->child(0)->line(
10480 (hex->face(5)->refinement_case() ==
10482 1 :
10483 3), // 3
10484
10485 hex->face(0)
10486 ->isotropic_child(
10488 0, f_or[0], f_fl[0], f_ro[0]))
10489 ->line(
10491 1, f_or[0], f_fl[0], f_ro[0])), // 4
10492 hex->face(0)
10493 ->isotropic_child(
10495 3, f_or[0], f_fl[0], f_ro[0]))
10496 ->line(
10498 0, f_or[0], f_fl[0], f_ro[0])), // 5
10499 hex->face(0)
10500 ->isotropic_child(
10502 0, f_or[0], f_fl[0], f_ro[0]))
10503 ->line(
10505 3, f_or[0], f_fl[0], f_ro[0])), // 6
10506 hex->face(0)
10507 ->isotropic_child(
10509 3, f_or[0], f_fl[0], f_ro[0]))
10510 ->line(
10512 2, f_or[0], f_fl[0], f_ro[0])), // 7
10513
10514 hex->face(1)
10515 ->isotropic_child(
10517 0, f_or[1], f_fl[1], f_ro[1]))
10518 ->line(
10520 1, f_or[1], f_fl[1], f_ro[1])), // 8
10521 hex->face(1)
10522 ->isotropic_child(
10524 3, f_or[1], f_fl[1], f_ro[1]))
10525 ->line(
10527 0, f_or[1], f_fl[1], f_ro[1])), // 9
10528 hex->face(1)
10529 ->isotropic_child(
10531 0, f_or[1], f_fl[1], f_ro[1]))
10532 ->line(
10534 3, f_or[1], f_fl[1], f_ro[1])), // 10
10535 hex->face(1)
10536 ->isotropic_child(
10538 3, f_or[1], f_fl[1], f_ro[1]))
10539 ->line(
10541 2, f_or[1], f_fl[1], f_ro[1])), // 11
10542
10543 new_lines[0] // 12
10544 };
10545
10546 unsigned int line_indices[13];
10547
10548 for (unsigned int i = 0; i < 13; ++i)
10549 line_indices[i] = lines[i]->index();
10550
10551 // the orientation of lines for the inner quads
10552 // is quite tricky. as these lines are newly
10553 // created ones and thus have no parents, they
10554 // cannot inherit this property. set up an array
10555 // and fill it with the respective values
10556 bool line_orientation[13];
10557
10558 // the middle vertices of the lines of our front
10559 // face
10560 const unsigned int middle_vertices[4] = {
10561 hex->line(8)->child(0)->vertex_index(1),
10562 hex->line(10)->child(0)->vertex_index(1),
10563 hex->line(0)->child(0)->vertex_index(1),
10564 hex->line(4)->child(0)->vertex_index(1),
10565 };
10566
10567 // note: for lines 0 to 3 the orientation of the
10568 // line is 'true', if vertex 0 is on the front
10569 for (unsigned int i = 0; i < 4; ++i)
10570 if (lines[i]->vertex_index(0) == middle_vertices[i])
10571 line_orientation[i] = true;
10572 else
10573 {
10574 // it must be the other way round then
10575 Assert(lines[i]->vertex_index(1) ==
10576 middle_vertices[i],
10578 line_orientation[i] = false;
10579 }
10580
10581 // note: for lines 4 to 11 (inner lines of the
10582 // outer quads) the following holds: the second
10583 // vertex of the even lines in standard
10584 // orientation is the vertex in the middle of
10585 // the quad, whereas for odd lines the first
10586 // vertex is the same middle vertex.
10587 for (unsigned int i = 4; i < 12; ++i)
10588 if (lines[i]->vertex_index((i + 1) % 2) ==
10589 middle_vertex_index<dim, spacedim>(
10590 hex->face(i / 4 - 1)))
10591 line_orientation[i] = true;
10592 else
10593 {
10594 // it must be the other way
10595 // round then
10596 Assert(lines[i]->vertex_index(i % 2) ==
10597 (middle_vertex_index<dim, spacedim>(
10598 hex->face(i / 4 - 1))),
10600 line_orientation[i] = false;
10601 }
10602 // for the last line the line orientation is
10603 // always true, since it was just constructed
10604 // that way
10605 line_orientation[12] = true;
10606
10607 // set up the 4 quads, numbered as follows (left
10608 // quad numbering, right line numbering
10609 // extracted from above)
10610 //
10611 // x
10612 // *-------* *---3---*
10613 // | 3 | 5 9
10614 // *-------* *---12--*
10615 // | 2 | 4 8
10616 // *-------*y *---2---*
10617 //
10618 // y
10619 // *---------* *----1----*
10620 // / 1 / 7 11
10621 // *---------* *----12---*
10622 // / 0 / 6 10
10623 // *---------*x *----0----*
10624
10625 new_quads[0]->set_bounding_object_indices(
10626 {line_indices[6],
10627 line_indices[10],
10628 line_indices[0],
10629 line_indices[12]});
10630 new_quads[1]->set_bounding_object_indices(
10631 {line_indices[7],
10632 line_indices[11],
10633 line_indices[12],
10634 line_indices[1]});
10635 new_quads[2]->set_bounding_object_indices(
10636 {line_indices[2],
10637 line_indices[12],
10638 line_indices[4],
10639 line_indices[8]});
10640 new_quads[3]->set_bounding_object_indices(
10641 {line_indices[12],
10642 line_indices[3],
10643 line_indices[5],
10644 line_indices[9]});
10645
10646 new_quads[0]->set_line_orientation(
10647 0, line_orientation[6]);
10648 new_quads[0]->set_line_orientation(
10649 1, line_orientation[10]);
10650 new_quads[0]->set_line_orientation(
10651 2, line_orientation[0]);
10652
10653 new_quads[1]->set_line_orientation(
10654 0, line_orientation[7]);
10655 new_quads[1]->set_line_orientation(
10656 1, line_orientation[11]);
10657 new_quads[1]->set_line_orientation(
10658 3, line_orientation[1]);
10659
10660 new_quads[2]->set_line_orientation(
10661 0, line_orientation[2]);
10662 new_quads[2]->set_line_orientation(
10663 2, line_orientation[4]);
10664 new_quads[2]->set_line_orientation(
10665 3, line_orientation[8]);
10666
10667 new_quads[3]->set_line_orientation(
10668 1, line_orientation[3]);
10669 new_quads[3]->set_line_orientation(
10670 2, line_orientation[5]);
10671 new_quads[3]->set_line_orientation(
10672 3, line_orientation[9]);
10673
10674 // the quads are numbered as follows:
10675 //
10676 // planes in the interior of the old hex:
10677 //
10678 // *
10679 // /|
10680 // / | x
10681 // / | *-------* *---------*
10682 // * | | 3 | / 1 /
10683 // | | *-------* *---------*
10684 // | * | 2 | / 0 /
10685 // | / *-------*y *---------*x
10686 // | /
10687 // |/
10688 // *
10689 //
10690 // children of the faces
10691 // of the old hex
10692 // *-------* *-------*
10693 // /| | / 19 /|
10694 // * | 15 | *-------* |
10695 // /|7*-------* / 18 /|11
10696 // * |/| | *-------* |/|
10697 // |6* | 14 | | 10* |
10698 // |/|5*-------* | 13 |/|9*
10699 // * |/ 17 / *-------* |/
10700 // |4*-------* | |8*
10701 // |/ 16 / | 12 |/
10702 // *-------* *-------*
10703 //
10704 // note that we have to take care of the
10705 // orientation of faces.
10706 const int quad_indices[20] = {
10707 new_quads[0]->index(), // 0
10708 new_quads[1]->index(),
10709 new_quads[2]->index(),
10710 new_quads[3]->index(),
10711
10712 hex->face(0)->isotropic_child_index(
10714 0, f_or[0], f_fl[0], f_ro[0])), // 4
10715 hex->face(0)->isotropic_child_index(
10717 1, f_or[0], f_fl[0], f_ro[0])),
10718 hex->face(0)->isotropic_child_index(
10720 2, f_or[0], f_fl[0], f_ro[0])),
10721 hex->face(0)->isotropic_child_index(
10723 3, f_or[0], f_fl[0], f_ro[0])),
10724
10725 hex->face(1)->isotropic_child_index(
10727 0, f_or[1], f_fl[1], f_ro[1])), // 8
10728 hex->face(1)->isotropic_child_index(
10730 1, f_or[1], f_fl[1], f_ro[1])),
10731 hex->face(1)->isotropic_child_index(
10733 2, f_or[1], f_fl[1], f_ro[1])),
10734 hex->face(1)->isotropic_child_index(
10736 3, f_or[1], f_fl[1], f_ro[1])),
10737
10738 hex->face(2)->child_index(
10739 child_at_origin[hex->face(2)->refinement_case() -
10740 1][f_fl[2]][f_ro[2]]), // 12
10741 hex->face(2)->child_index(
10742 1 -
10743 child_at_origin[hex->face(2)->refinement_case() -
10744 1][f_fl[2]][f_ro[2]]),
10745
10746 hex->face(3)->child_index(
10747 child_at_origin[hex->face(3)->refinement_case() -
10748 1][f_fl[3]][f_ro[3]]), // 14
10749 hex->face(3)->child_index(
10750 1 -
10751 child_at_origin[hex->face(3)->refinement_case() -
10752 1][f_fl[3]][f_ro[3]]),
10753
10754 hex->face(4)->child_index(
10755 child_at_origin[hex->face(4)->refinement_case() -
10756 1][f_fl[4]][f_ro[4]]), // 16
10757 hex->face(4)->child_index(
10758 1 -
10759 child_at_origin[hex->face(4)->refinement_case() -
10760 1][f_fl[4]][f_ro[4]]),
10761
10762 hex->face(5)->child_index(
10763 child_at_origin[hex->face(5)->refinement_case() -
10764 1][f_fl[5]][f_ro[5]]), // 18
10765 hex->face(5)->child_index(
10766 1 -
10767 child_at_origin[hex->face(5)->refinement_case() -
10768 1][f_fl[5]][f_ro[5]])};
10769
10770 new_hexes[0]->set_bounding_object_indices(
10771 {quad_indices[4],
10772 quad_indices[8],
10773 quad_indices[12],
10774 quad_indices[2],
10775 quad_indices[16],
10776 quad_indices[0]});
10777 new_hexes[1]->set_bounding_object_indices(
10778 {quad_indices[5],
10779 quad_indices[9],
10780 quad_indices[2],
10781 quad_indices[14],
10782 quad_indices[17],
10783 quad_indices[1]});
10784 new_hexes[2]->set_bounding_object_indices(
10785 {quad_indices[6],
10786 quad_indices[10],
10787 quad_indices[13],
10788 quad_indices[3],
10789 quad_indices[0],
10790 quad_indices[18]});
10791 new_hexes[3]->set_bounding_object_indices(
10792 {quad_indices[7],
10793 quad_indices[11],
10794 quad_indices[3],
10795 quad_indices[15],
10796 quad_indices[1],
10797 quad_indices[19]});
10798 break;
10799 }
10800
10802 {
10803 //----------------------------
10804 //
10805 // RefinementCase<dim>::cut_xyz
10806 // isotropic refinement
10807 //
10808 // the refined cube will look
10809 // like this:
10810 //
10811 // *----*----*
10812 // / / /|
10813 // *----*----* |
10814 // / / /| *
10815 // *----*----* |/|
10816 // | | | * |
10817 // | | |/| *
10818 // *----*----* |/
10819 // | | | *
10820 // | | |/
10821 // *----*----*
10822 //
10823
10824 // find the next unused vertex and set it
10825 // appropriately
10826 while (
10827 triangulation.vertices_used[next_unused_vertex] ==
10828 true)
10829 ++next_unused_vertex;
10830 Assert(
10831 next_unused_vertex < triangulation.vertices.size(),
10832 ExcMessage(
10833 "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."));
10834 triangulation.vertices_used[next_unused_vertex] =
10835 true;
10836
10837 // the new vertex is definitely in the interior,
10838 // so we need not worry about the
10839 // boundary. However we need to worry about
10840 // Manifolds. Let the cell compute its own
10841 // center, by querying the underlying manifold
10842 // object.
10843 triangulation.vertices[next_unused_vertex] =
10844 hex->center(true, true);
10845
10846 // set the data of the six lines. first collect
10847 // the indices of the seven vertices (consider
10848 // the two planes to be crossed to form the
10849 // planes cutting the hex in two vertically and
10850 // horizontally)
10851 //
10852 // *--3--* *--5--*
10853 // / / / | | |
10854 // 0--6--1 0--6--1
10855 // / / / | | |
10856 // *--2--* *--4--*
10857 // the lines are numbered
10858 // as follows:
10859 // *--*--* *--*--*
10860 // / 1 / | 5 |
10861 // *2-*-3* *2-*-3*
10862 // / 0 / | 4 |
10863 // *--*--* *--*--*
10864 //
10865 const unsigned int vertex_indices[7] = {
10866 middle_vertex_index<dim, spacedim>(hex->face(0)),
10867 middle_vertex_index<dim, spacedim>(hex->face(1)),
10868 middle_vertex_index<dim, spacedim>(hex->face(2)),
10869 middle_vertex_index<dim, spacedim>(hex->face(3)),
10870 middle_vertex_index<dim, spacedim>(hex->face(4)),
10871 middle_vertex_index<dim, spacedim>(hex->face(5)),
10872 next_unused_vertex};
10873
10874 new_lines[0]->set_bounding_object_indices(
10876 new_lines[1]->set_bounding_object_indices(
10878 new_lines[2]->set_bounding_object_indices(
10880 new_lines[3]->set_bounding_object_indices(
10882 new_lines[4]->set_bounding_object_indices(
10884 new_lines[5]->set_bounding_object_indices(
10886
10887 // again, first collect some data about the
10888 // indices of the lines, with the following
10889 // numbering: (note that face 0 and 1 each are
10890 // shown twice for better readability)
10891
10892 // face 0: left plane
10893 // * *
10894 // /| /|
10895 // * | * |
10896 // /| * /| *
10897 // * 1/| * |3|
10898 // | * | | * |
10899 // |/| * |2| *
10900 // * 0/ * |/
10901 // | * | *
10902 // |/ |/
10903 // * *
10904 // face 1: right plane
10905 // * *
10906 // /| /|
10907 // * | * |
10908 // /| * /| *
10909 // * 5/| * |7|
10910 // | * | | * |
10911 // |/| * |6| *
10912 // * 4/ * |/
10913 // | * | *
10914 // |/ |/
10915 // * *
10916 // face 2: front plane
10917 // (note: x,y exchanged)
10918 // *---*---*
10919 // | 11 |
10920 // *-8-*-9-*
10921 // | 10 |
10922 // *---*---*
10923 // face 3: back plane
10924 // (note: x,y exchanged)
10925 // *---*---*
10926 // | 15 |
10927 // *12-*-13*
10928 // | 14 |
10929 // *---*---*
10930 // face 4: bottom plane
10931 // *---*---*
10932 // / 17 /
10933 // *18-*-19*
10934 // / 16 /
10935 // *---*---*
10936 // face 5: top plane
10937 // *---*---*
10938 // / 21 /
10939 // *22-*-23*
10940 // / 20 /
10941 // *---*---*
10942 // middle planes
10943 // *---*---* *---*---*
10944 // / 25 / | 29 |
10945 // *26-*-27* *26-*-27*
10946 // / 24 / | 28 |
10947 // *---*---* *---*---*
10948
10949 // set up a list of line iterators first. from
10950 // this, construct lists of line_indices and
10951 // line orientations later on
10952 const typename Triangulation<
10953 dim,
10954 spacedim>::raw_line_iterator lines[30] = {
10955 hex->face(0)
10956 ->isotropic_child(
10958 0, f_or[0], f_fl[0], f_ro[0]))
10959 ->line(
10961 1, f_or[0], f_fl[0], f_ro[0])), // 0
10962 hex->face(0)
10963 ->isotropic_child(
10965 3, f_or[0], f_fl[0], f_ro[0]))
10966 ->line(
10968 0, f_or[0], f_fl[0], f_ro[0])), // 1
10969 hex->face(0)
10970 ->isotropic_child(
10972 0, f_or[0], f_fl[0], f_ro[0]))
10973 ->line(
10975 3, f_or[0], f_fl[0], f_ro[0])), // 2
10976 hex->face(0)
10977 ->isotropic_child(
10979 3, f_or[0], f_fl[0], f_ro[0]))
10980 ->line(
10982 2, f_or[0], f_fl[0], f_ro[0])), // 3
10983
10984 hex->face(1)
10985 ->isotropic_child(
10987 0, f_or[1], f_fl[1], f_ro[1]))
10988 ->line(
10990 1, f_or[1], f_fl[1], f_ro[1])), // 4
10991 hex->face(1)
10992 ->isotropic_child(
10994 3, f_or[1], f_fl[1], f_ro[1]))
10995 ->line(
10997 0, f_or[1], f_fl[1], f_ro[1])), // 5
10998 hex->face(1)
10999 ->isotropic_child(
11001 0, f_or[1], f_fl[1], f_ro[1]))
11002 ->line(
11004 3, f_or[1], f_fl[1], f_ro[1])), // 6
11005 hex->face(1)
11006 ->isotropic_child(
11008 3, f_or[1], f_fl[1], f_ro[1]))
11009 ->line(
11011 2, f_or[1], f_fl[1], f_ro[1])), // 7
11012
11013 hex->face(2)
11014 ->isotropic_child(
11016 0, f_or[2], f_fl[2], f_ro[2]))
11017 ->line(
11019 1, f_or[2], f_fl[2], f_ro[2])), // 8
11020 hex->face(2)
11021 ->isotropic_child(
11023 3, f_or[2], f_fl[2], f_ro[2]))
11024 ->line(
11026 0, f_or[2], f_fl[2], f_ro[2])), // 9
11027 hex->face(2)
11028 ->isotropic_child(
11030 0, f_or[2], f_fl[2], f_ro[2]))
11031 ->line(
11033 3, f_or[2], f_fl[2], f_ro[2])), // 10
11034 hex->face(2)
11035 ->isotropic_child(
11037 3, f_or[2], f_fl[2], f_ro[2]))
11038 ->line(
11040 2, f_or[2], f_fl[2], f_ro[2])), // 11
11041
11042 hex->face(3)
11043 ->isotropic_child(
11045 0, f_or[3], f_fl[3], f_ro[3]))
11046 ->line(
11048 1, f_or[3], f_fl[3], f_ro[3])), // 12
11049 hex->face(3)
11050 ->isotropic_child(
11052 3, f_or[3], f_fl[3], f_ro[3]))
11053 ->line(
11055 0, f_or[3], f_fl[3], f_ro[3])), // 13
11056 hex->face(3)
11057 ->isotropic_child(
11059 0, f_or[3], f_fl[3], f_ro[3]))
11060 ->line(
11062 3, f_or[3], f_fl[3], f_ro[3])), // 14
11063 hex->face(3)
11064 ->isotropic_child(
11066 3, f_or[3], f_fl[3], f_ro[3]))
11067 ->line(
11069 2, f_or[3], f_fl[3], f_ro[3])), // 15
11070
11071 hex->face(4)
11072 ->isotropic_child(
11074 0, f_or[4], f_fl[4], f_ro[4]))
11075 ->line(
11077 1, f_or[4], f_fl[4], f_ro[4])), // 16
11078 hex->face(4)
11079 ->isotropic_child(
11081 3, f_or[4], f_fl[4], f_ro[4]))
11082 ->line(
11084 0, f_or[4], f_fl[4], f_ro[4])), // 17
11085 hex->face(4)
11086 ->isotropic_child(
11088 0, f_or[4], f_fl[4], f_ro[4]))
11089 ->line(
11091 3, f_or[4], f_fl[4], f_ro[4])), // 18
11092 hex->face(4)
11093 ->isotropic_child(
11095 3, f_or[4], f_fl[4], f_ro[4]))
11096 ->line(
11098 2, f_or[4], f_fl[4], f_ro[4])), // 19
11099
11100 hex->face(5)
11101 ->isotropic_child(
11103 0, f_or[5], f_fl[5], f_ro[5]))
11104 ->line(
11106 1, f_or[5], f_fl[5], f_ro[5])), // 20
11107 hex->face(5)
11108 ->isotropic_child(
11110 3, f_or[5], f_fl[5], f_ro[5]))
11111 ->line(
11113 0, f_or[5], f_fl[5], f_ro[5])), // 21
11114 hex->face(5)
11115 ->isotropic_child(
11117 0, f_or[5], f_fl[5], f_ro[5]))
11118 ->line(
11120 3, f_or[5], f_fl[5], f_ro[5])), // 22
11121 hex->face(5)
11122 ->isotropic_child(
11124 3, f_or[5], f_fl[5], f_ro[5]))
11125 ->line(
11127 2, f_or[5], f_fl[5], f_ro[5])), // 23
11128
11129 new_lines[0], // 24
11130 new_lines[1], // 25
11131 new_lines[2], // 26
11132 new_lines[3], // 27
11133 new_lines[4], // 28
11134 new_lines[5] // 29
11135 };
11136
11137 unsigned int line_indices[30];
11138 for (unsigned int i = 0; i < 30; ++i)
11139 line_indices[i] = lines[i]->index();
11140
11141 // the orientation of lines for the inner quads
11142 // is quite tricky. as these lines are newly
11143 // created ones and thus have no parents, they
11144 // cannot inherit this property. set up an array
11145 // and fill it with the respective values
11146 bool line_orientation[30];
11147
11148 // note: for the first 24 lines (inner lines of
11149 // the outer quads) the following holds: the
11150 // second vertex of the even lines in standard
11151 // orientation is the vertex in the middle of
11152 // the quad, whereas for odd lines the first
11153 // vertex is the same middle vertex.
11154 for (unsigned int i = 0; i < 24; ++i)
11155 if (lines[i]->vertex_index((i + 1) % 2) ==
11156 vertex_indices[i / 4])
11157 line_orientation[i] = true;
11158 else
11159 {
11160 // it must be the other way
11161 // round then
11162 Assert(lines[i]->vertex_index(i % 2) ==
11163 vertex_indices[i / 4],
11165 line_orientation[i] = false;
11166 }
11167 // for the last 6 lines the line orientation is
11168 // always true, since they were just constructed
11169 // that way
11170 for (unsigned int i = 24; i < 30; ++i)
11171 line_orientation[i] = true;
11172
11173 // set up the 12 quads, numbered as follows
11174 // (left quad numbering, right line numbering
11175 // extracted from above)
11176 //
11177 // * *
11178 // /| 21|
11179 // * | * 15
11180 // y/|3* 20| *
11181 // * |/| * |/|
11182 // |2* |x 11 * 14
11183 // |/|1* |/| *
11184 // * |/ * |17
11185 // |0* 10 *
11186 // |/ |16
11187 // * *
11188 //
11189 // x
11190 // *---*---* *22-*-23*
11191 // | 5 | 7 | 1 29 5
11192 // *---*---* *26-*-27*
11193 // | 4 | 6 | 0 28 4
11194 // *---*---*y *18-*-19*
11195 //
11196 // y
11197 // *----*----* *-12-*-13-*
11198 // / 10 / 11 / 3 25 7
11199 // *----*----* *-26-*-27-*
11200 // / 8 / 9 / 2 24 6
11201 // *----*----*x *--8-*--9-*
11202
11203 new_quads[0]->set_bounding_object_indices(
11204 {line_indices[10],
11205 line_indices[28],
11206 line_indices[16],
11207 line_indices[24]});
11208 new_quads[1]->set_bounding_object_indices(
11209 {line_indices[28],
11210 line_indices[14],
11211 line_indices[17],
11212 line_indices[25]});
11213 new_quads[2]->set_bounding_object_indices(
11214 {line_indices[11],
11215 line_indices[29],
11216 line_indices[24],
11217 line_indices[20]});
11218 new_quads[3]->set_bounding_object_indices(
11219 {line_indices[29],
11220 line_indices[15],
11221 line_indices[25],
11222 line_indices[21]});
11223 new_quads[4]->set_bounding_object_indices(
11224 {line_indices[18],
11225 line_indices[26],
11226 line_indices[0],
11227 line_indices[28]});
11228 new_quads[5]->set_bounding_object_indices(
11229 {line_indices[26],
11230 line_indices[22],
11231 line_indices[1],
11232 line_indices[29]});
11233 new_quads[6]->set_bounding_object_indices(
11234 {line_indices[19],
11235 line_indices[27],
11236 line_indices[28],
11237 line_indices[4]});
11238 new_quads[7]->set_bounding_object_indices(
11239 {line_indices[27],
11240 line_indices[23],
11241 line_indices[29],
11242 line_indices[5]});
11243 new_quads[8]->set_bounding_object_indices(
11244 {line_indices[2],
11245 line_indices[24],
11246 line_indices[8],
11247 line_indices[26]});
11248 new_quads[9]->set_bounding_object_indices(
11249 {line_indices[24],
11250 line_indices[6],
11251 line_indices[9],
11252 line_indices[27]});
11253 new_quads[10]->set_bounding_object_indices(
11254 {line_indices[3],
11255 line_indices[25],
11256 line_indices[26],
11257 line_indices[12]});
11258 new_quads[11]->set_bounding_object_indices(
11259 {line_indices[25],
11260 line_indices[7],
11261 line_indices[27],
11262 line_indices[13]});
11263
11264 // now reset the line_orientation flags of outer
11265 // lines as they cannot be set in a loop (at
11266 // least not easily)
11267 new_quads[0]->set_line_orientation(
11268 0, line_orientation[10]);
11269 new_quads[0]->set_line_orientation(
11270 2, line_orientation[16]);
11271
11272 new_quads[1]->set_line_orientation(
11273 1, line_orientation[14]);
11274 new_quads[1]->set_line_orientation(
11275 2, line_orientation[17]);
11276
11277 new_quads[2]->set_line_orientation(
11278 0, line_orientation[11]);
11279 new_quads[2]->set_line_orientation(
11280 3, line_orientation[20]);
11281
11282 new_quads[3]->set_line_orientation(
11283 1, line_orientation[15]);
11284 new_quads[3]->set_line_orientation(
11285 3, line_orientation[21]);
11286
11287 new_quads[4]->set_line_orientation(
11288 0, line_orientation[18]);
11289 new_quads[4]->set_line_orientation(
11290 2, line_orientation[0]);
11291
11292 new_quads[5]->set_line_orientation(
11293 1, line_orientation[22]);
11294 new_quads[5]->set_line_orientation(
11295 2, line_orientation[1]);
11296
11297 new_quads[6]->set_line_orientation(
11298 0, line_orientation[19]);
11299 new_quads[6]->set_line_orientation(
11300 3, line_orientation[4]);
11301
11302 new_quads[7]->set_line_orientation(
11303 1, line_orientation[23]);
11304 new_quads[7]->set_line_orientation(
11305 3, line_orientation[5]);
11306
11307 new_quads[8]->set_line_orientation(
11308 0, line_orientation[2]);
11309 new_quads[8]->set_line_orientation(
11310 2, line_orientation[8]);
11311
11312 new_quads[9]->set_line_orientation(
11313 1, line_orientation[6]);
11314 new_quads[9]->set_line_orientation(
11315 2, line_orientation[9]);
11316
11317 new_quads[10]->set_line_orientation(
11318 0, line_orientation[3]);
11319 new_quads[10]->set_line_orientation(
11320 3, line_orientation[12]);
11321
11322 new_quads[11]->set_line_orientation(
11323 1, line_orientation[7]);
11324 new_quads[11]->set_line_orientation(
11325 3, line_orientation[13]);
11326
11327 //-------------------------------
11328 // create the eight new hexes
11329 //
11330 // again first collect some data. here, we need
11331 // the indices of a whole lotta quads.
11332
11333 // the quads are numbered as follows:
11334 //
11335 // planes in the interior of the old hex:
11336 //
11337 // *
11338 // /|
11339 // * |
11340 // /|3* *---*---* *----*----*
11341 // * |/| | 5 | 7 | / 10 / 11 /
11342 // |2* | *---*---* *----*----*
11343 // |/|1* | 4 | 6 | / 8 / 9 /
11344 // * |/ *---*---*y *----*----*x
11345 // |0*
11346 // |/
11347 // *
11348 //
11349 // children of the faces
11350 // of the old hex
11351 // *-------* *-------*
11352 // /|25 27| /34 35/|
11353 // 15| | / /19
11354 // / | | /32 33/ |
11355 // * |24 26| *-------*18 |
11356 // 1413*-------* |21 23| 17*
11357 // | /30 31/ | | /
11358 // 12/ / | |16
11359 // |/28 29/ |20 22|/
11360 // *-------* *-------*
11361 //
11362 // note that we have to
11363 // take care of the
11364 // orientation of
11365 // faces.
11366 const int quad_indices[36] = {
11367 new_quads[0]->index(), // 0
11368 new_quads[1]->index(),
11369 new_quads[2]->index(),
11370 new_quads[3]->index(),
11371 new_quads[4]->index(),
11372 new_quads[5]->index(),
11373 new_quads[6]->index(),
11374 new_quads[7]->index(),
11375 new_quads[8]->index(),
11376 new_quads[9]->index(),
11377 new_quads[10]->index(),
11378 new_quads[11]->index(), // 11
11379
11380 hex->face(0)->isotropic_child_index(
11382 0, f_or[0], f_fl[0], f_ro[0])), // 12
11383 hex->face(0)->isotropic_child_index(
11385 1, f_or[0], f_fl[0], f_ro[0])),
11386 hex->face(0)->isotropic_child_index(
11388 2, f_or[0], f_fl[0], f_ro[0])),
11389 hex->face(0)->isotropic_child_index(
11391 3, f_or[0], f_fl[0], f_ro[0])),
11392
11393 hex->face(1)->isotropic_child_index(
11395 0, f_or[1], f_fl[1], f_ro[1])), // 16
11396 hex->face(1)->isotropic_child_index(
11398 1, f_or[1], f_fl[1], f_ro[1])),
11399 hex->face(1)->isotropic_child_index(
11401 2, f_or[1], f_fl[1], f_ro[1])),
11402 hex->face(1)->isotropic_child_index(
11404 3, f_or[1], f_fl[1], f_ro[1])),
11405
11406 hex->face(2)->isotropic_child_index(
11408 0, f_or[2], f_fl[2], f_ro[2])), // 20
11409 hex->face(2)->isotropic_child_index(
11411 1, f_or[2], f_fl[2], f_ro[2])),
11412 hex->face(2)->isotropic_child_index(
11414 2, f_or[2], f_fl[2], f_ro[2])),
11415 hex->face(2)->isotropic_child_index(
11417 3, f_or[2], f_fl[2], f_ro[2])),
11418
11419 hex->face(3)->isotropic_child_index(
11421 0, f_or[3], f_fl[3], f_ro[3])), // 24
11422 hex->face(3)->isotropic_child_index(
11424 1, f_or[3], f_fl[3], f_ro[3])),
11425 hex->face(3)->isotropic_child_index(
11427 2, f_or[3], f_fl[3], f_ro[3])),
11428 hex->face(3)->isotropic_child_index(
11430 3, f_or[3], f_fl[3], f_ro[3])),
11431
11432 hex->face(4)->isotropic_child_index(
11434 0, f_or[4], f_fl[4], f_ro[4])), // 28
11435 hex->face(4)->isotropic_child_index(
11437 1, f_or[4], f_fl[4], f_ro[4])),
11438 hex->face(4)->isotropic_child_index(
11440 2, f_or[4], f_fl[4], f_ro[4])),
11441 hex->face(4)->isotropic_child_index(
11443 3, f_or[4], f_fl[4], f_ro[4])),
11444
11445 hex->face(5)->isotropic_child_index(
11447 0, f_or[5], f_fl[5], f_ro[5])), // 32
11448 hex->face(5)->isotropic_child_index(
11450 1, f_or[5], f_fl[5], f_ro[5])),
11451 hex->face(5)->isotropic_child_index(
11453 2, f_or[5], f_fl[5], f_ro[5])),
11454 hex->face(5)->isotropic_child_index(
11456 3, f_or[5], f_fl[5], f_ro[5]))};
11457
11458 // bottom children
11459 new_hexes[0]->set_bounding_object_indices(
11460 {quad_indices[12],
11461 quad_indices[0],
11462 quad_indices[20],
11463 quad_indices[4],
11464 quad_indices[28],
11465 quad_indices[8]});
11466 new_hexes[1]->set_bounding_object_indices(
11467 {quad_indices[0],
11468 quad_indices[16],
11469 quad_indices[22],
11470 quad_indices[6],
11471 quad_indices[29],
11472 quad_indices[9]});
11473 new_hexes[2]->set_bounding_object_indices(
11474 {quad_indices[13],
11475 quad_indices[1],
11476 quad_indices[4],
11477 quad_indices[24],
11478 quad_indices[30],
11479 quad_indices[10]});
11480 new_hexes[3]->set_bounding_object_indices(
11481 {quad_indices[1],
11482 quad_indices[17],
11483 quad_indices[6],
11484 quad_indices[26],
11485 quad_indices[31],
11486 quad_indices[11]});
11487
11488 // top children
11489 new_hexes[4]->set_bounding_object_indices(
11490 {quad_indices[14],
11491 quad_indices[2],
11492 quad_indices[21],
11493 quad_indices[5],
11494 quad_indices[8],
11495 quad_indices[32]});
11496 new_hexes[5]->set_bounding_object_indices(
11497 {quad_indices[2],
11498 quad_indices[18],
11499 quad_indices[23],
11500 quad_indices[7],
11501 quad_indices[9],
11502 quad_indices[33]});
11503 new_hexes[6]->set_bounding_object_indices(
11504 {quad_indices[15],
11505 quad_indices[3],
11506 quad_indices[5],
11507 quad_indices[25],
11508 quad_indices[10],
11509 quad_indices[34]});
11510 new_hexes[7]->set_bounding_object_indices(
11511 {quad_indices[3],
11512 quad_indices[19],
11513 quad_indices[7],
11514 quad_indices[27],
11515 quad_indices[11],
11516 quad_indices[35]});
11517 break;
11518 }
11519 default:
11520 // all refinement cases have been treated, there
11521 // only remains
11522 // RefinementCase<dim>::no_refinement as
11523 // untreated enumeration value. However, in that
11524 // case we should have aborted much
11525 // earlier. thus we should never get here
11527 break;
11528 } // switch (ref_case)
11529
11530 // and set face orientation flags. note that new
11531 // faces in the interior of the mother cell always
11532 // have a correctly oriented face, but the ones on
11533 // the outer faces will inherit this flag
11534 //
11535 // the flag have been set to true for all faces
11536 // initially, now go the other way round and reset
11537 // faces that are at the boundary of the mother cube
11538 //
11539 // the same is true for the face_flip and
11540 // face_rotation flags. however, the latter two are
11541 // set to false by default as this is the standard
11542 // value
11543
11544 // loop over all faces and all (relevant) subfaces
11545 // of that in order to set the correct values for
11546 // face_orientation, face_flip and face_rotation,
11547 // which are inherited from the corresponding face
11548 // of the mother cube
11549 for (const unsigned int f : GeometryInfo<dim>::face_indices())
11550 for (unsigned int s = 0;
11553 ref_case, f)),
11554 1U);
11555 ++s)
11556 {
11557 const unsigned int current_child =
11559 ref_case,
11560 f,
11561 s,
11562 f_or[f],
11563 f_fl[f],
11564 f_ro[f],
11566 ref_case, f, f_or[f], f_fl[f], f_ro[f]));
11567 new_hexes[current_child]->set_combined_face_orientation(
11568 f, f_co[f]);
11569 }
11570
11571 // now see if we have created cells that are
11572 // distorted and if so add them to our list
11573 if (check_for_distorted_cells &&
11574 has_distorted_children<dim, spacedim>(hex))
11575 cells_with_distorted_children.distorted_cells.push_back(
11576 hex);
11577
11578 // note that the refinement flag was already cleared
11579 // at the beginning of this loop
11580
11581 // inform all listeners that cell refinement is done
11582 triangulation.signals.post_refinement_on_cell(hex);
11583 }
11584 }
11585
11586 // clear user data on quads. we used some of this data to
11587 // indicate anisotropic refinemnt cases on faces. all data
11588 // should be cleared by now, but the information whether we
11589 // used indices or pointers is still present. reset it now to
11590 // enable the user to use whichever they like later on.
11591 triangulation.faces->quads.clear_user_data();
11592
11593 // return the list with distorted children
11594 return cells_with_distorted_children;
11595 }
11596
11597
11610 template <int spacedim>
11611 static void
11614
11615
11616
11617 template <int dim, int spacedim>
11618 static void
11621 {
11622 // If the codimension is one, we cannot perform this check
11623 // yet.
11624 if (spacedim > dim)
11625 return;
11626
11627 for (const auto &cell : triangulation.cell_iterators())
11628 if (cell->at_boundary() && cell->refine_flag_set() &&
11629 cell->refine_flag_set() !=
11631 {
11632 // The cell is at the boundary and it is flagged for
11633 // anisotropic refinement. Therefore, we have a closer
11634 // look
11635 const RefinementCase<dim> ref_case = cell->refine_flag_set();
11636 for (const unsigned int face_no :
11638 if (cell->face(face_no)->at_boundary())
11639 {
11640 // this is the critical face at the boundary.
11642 face_no) !=
11643 RefinementCase<dim - 1>::isotropic_refinement)
11644 {
11645 // up to now, we do not want to refine this
11646 // cell along the face under consideration
11647 // here.
11648 const typename Triangulation<dim,
11649 spacedim>::face_iterator
11650 face = cell->face(face_no);
11651 // the new point on the boundary would be this
11652 // one.
11653 const Point<spacedim> new_bound = face->center(true);
11654 // to check it, transform to the unit cell
11655 // with a linear mapping
11656 const Point<dim> new_unit =
11657 cell->reference_cell()
11658 .template get_default_linear_mapping<dim,
11659 spacedim>()
11660 .transform_real_to_unit_cell(cell, new_bound);
11661
11662 // Now, we have to calculate the distance from
11663 // the face in the unit cell.
11664
11665 // take the correct coordinate direction (0
11666 // for faces 0 and 1, 1 for faces 2 and 3, 2
11667 // for faces 4 and 5) and subtract the correct
11668 // boundary value of the face (0 for faces 0,
11669 // 2, and 4; 1 for faces 1, 3 and 5)
11670 const double dist =
11671 std::fabs(new_unit[face_no / 2] - face_no % 2);
11672
11673 // compare this with the empirical value
11674 // allowed. if it is too big, flag the face
11675 // for isotropic refinement
11676 const double allowed = 0.25;
11677
11678 if (dist > allowed)
11679 cell->flag_for_face_refinement(face_no);
11680 } // if flagged for anistropic refinement
11681 } // if (cell->face(face)->at_boundary())
11682 } // for all cells
11683 }
11684
11685
11698 template <int dim, int spacedim>
11699 static void
11701 {
11702 Assert(dim < 3,
11703 ExcMessage("Wrong function called -- there should "
11704 "be a specialization."));
11705 }
11706
11707
11708 template <int spacedim>
11709 static void
11712 {
11713 const unsigned int dim = 3;
11714 using raw_line_iterator =
11716
11717 // variable to store whether the mesh was changed in the
11718 // present loop and in the whole process
11719 bool mesh_changed = false;
11720
11721 do
11722 {
11723 mesh_changed = false;
11724
11725 // for this following, we need to know which cells are
11726 // going to be coarsened, if we had to make a
11727 // decision. the following function sets these flags:
11728 triangulation.fix_coarsen_flags();
11729
11730 // first clear flags on lines, since we need them to determine
11731 // which lines will be refined
11732 triangulation.clear_user_flags_line();
11733
11734 // flag those lines that are refined and will not be
11735 // coarsened and those that will be refined
11736 for (const auto &cell : triangulation.cell_iterators())
11737 if (cell->refine_flag_set())
11738 {
11739 const std::array<unsigned int, 12> line_indices =
11740 TriaAccessorImplementation::Implementation::
11741 get_line_indices_of_cell(*cell);
11742 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11744 cell->refine_flag_set(), l) ==
11746 {
11747 raw_line_iterator line(&triangulation,
11748 0,
11749 line_indices[l]);
11750 // flag a line, that will be refined
11751 line->set_user_flag();
11752 }
11753 }
11754 else if (cell->has_children() &&
11755 !cell->child(0)->coarsen_flag_set())
11756 {
11757 const std::array<unsigned int, 12> line_indices =
11758 TriaAccessorImplementation::Implementation::
11759 get_line_indices_of_cell(*cell);
11760 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11762 cell->refinement_case(), l) ==
11764 {
11765 raw_line_iterator line(&triangulation,
11766 0,
11767 line_indices[l]);
11768 // flag a line, that is refined and will stay so
11769 line->set_user_flag();
11770 }
11771 }
11772 else if (cell->has_children() &&
11773 cell->child(0)->coarsen_flag_set())
11774 cell->set_user_flag();
11775
11776
11777 // now check whether there are cells with lines that are
11778 // more than once refined or that will be more than once
11779 // refined. The first thing should never be the case, in
11780 // the second case we flag the cell for refinement
11782 cell = triangulation.last_active();
11783 cell != triangulation.end();
11784 --cell)
11785 {
11786 const std::array<unsigned int, 12> line_indices =
11787 TriaAccessorImplementation::Implementation::
11788 get_line_indices_of_cell(*cell);
11789 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11790 {
11791 raw_line_iterator line(&triangulation, 0, line_indices[l]);
11792 if (line->has_children())
11793 {
11794 // if this line is refined, its children should
11795 // not have further children
11796 //
11797 // however, if any of the children is flagged
11798 // for further refinement, we need to refine
11799 // this cell also (at least, if the cell is not
11800 // already flagged)
11801 bool offending_line_found = false;
11802
11803 for (unsigned int c = 0; c < 2; ++c)
11804 {
11805 Assert(line->child(c)->has_children() == false,
11807
11808 if (line->child(c)->user_flag_set() &&
11810 cell->refine_flag_set(), l) ==
11812 {
11813 // tag this cell for refinement
11814 cell->clear_coarsen_flag();
11815 // if anisotropic coarsening is allowed:
11816 // extend the refine_flag in the needed
11817 // direction, else set refine_flag
11818 // (isotropic)
11819 if (triangulation.smooth_grid &
11821 allow_anisotropic_smoothing)
11822 cell->flag_for_line_refinement(l);
11823 else
11824 cell->set_refine_flag();
11825
11826 for (unsigned int k = 0; k < cell->n_lines();
11827 ++k)
11829 cell->refine_flag_set(), l) ==
11831 // flag a line, that will be refined
11832 raw_line_iterator(&triangulation,
11833 0,
11834 line_indices[k])
11835 ->set_user_flag();
11836
11837 // note that we have changed the grid
11838 offending_line_found = true;
11839
11840 // it may save us several loop
11841 // iterations if we flag all lines of
11842 // this cell now (and not at the outset
11843 // of the next iteration) for refinement
11844 for (unsigned int k = 0; k < cell->n_lines();
11845 ++k)
11846 {
11847 const auto line =
11848 raw_line_iterator(&triangulation,
11849 0,
11850 line_indices[k]);
11851 if (!line->has_children() &&
11853 line_refinement_case(
11854 cell->refine_flag_set(), k) !=
11856 line->set_user_flag();
11857 }
11858
11859 break;
11860 }
11861 }
11862
11863 if (offending_line_found)
11864 {
11865 mesh_changed = true;
11866 break;
11867 }
11868 }
11869 }
11870 }
11871
11872
11873 // there is another thing here: if any of the lines will
11874 // be refined, then we may not coarsen the present cell
11875 // similarly, if any of the lines *is* already refined, we
11876 // may not coarsen the current cell. however, there's a
11877 // catch: if the line is refined, but the cell behind it
11878 // is going to be coarsened, then the situation
11879 // changes. if we forget this second condition, the
11880 // refine_and_coarsen_3d test will start to fail. note
11881 // that to know which cells are going to be coarsened, the
11882 // call for fix_coarsen_flags above is necessary
11884 triangulation.last();
11885 cell != triangulation.end();
11886 --cell)
11887 if (cell->user_flag_set())
11888 {
11889 const std::array<unsigned int, 12> line_indices =
11890 TriaAccessorImplementation::Implementation::
11891 get_line_indices_of_cell(*cell);
11892 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11893 {
11894 raw_line_iterator line(&triangulation,
11895 0,
11896 line_indices[l]);
11897 if (line->has_children() &&
11898 (line->child(0)->user_flag_set() ||
11899 line->child(1)->user_flag_set()))
11900 {
11901 for (unsigned int c = 0; c < cell->n_children(); ++c)
11902 cell->child(c)->clear_coarsen_flag();
11903 cell->clear_user_flag();
11904 for (unsigned int k = 0; k < cell->n_lines(); ++k)
11906 cell->refinement_case(), k) ==
11908 // flag a line, that is refined and will
11909 // stay so
11910 raw_line_iterator(&triangulation,
11911 0,
11912 line_indices[k])
11913 ->set_user_flag();
11914 mesh_changed = true;
11915 break;
11916 }
11917 }
11918 }
11919 }
11920 while (mesh_changed == true);
11921 }
11922
11923
11924
11931 template <int dim, int spacedim>
11932 static bool
11935 {
11936 // in 1d, coarsening is always allowed since we don't enforce
11937 // the 2:1 constraint there
11938 if (dim == 1)
11939 return true;
11940
11941 const RefinementCase<dim> ref_case = cell->refinement_case();
11942 for (const unsigned int n : GeometryInfo<dim>::face_indices())
11943 {
11944 // if the cell is not refined along that face, coarsening
11945 // will not change anything, so do nothing. the same
11946 // applies, if the face is at the boundary
11947 const RefinementCase<dim - 1> face_ref_case =
11948 GeometryInfo<dim>::face_refinement_case(cell->refinement_case(),
11949 n);
11950
11951 const unsigned int n_subfaces =
11952 GeometryInfo<dim - 1>::n_children(face_ref_case);
11953
11954 if (n_subfaces == 0 || cell->at_boundary(n))
11955 continue;
11956 for (unsigned int c = 0; c < n_subfaces; ++c)
11957 {
11959 child = cell->child(
11961
11963 child_neighbor = child->neighbor(n);
11964 if (!child->neighbor_is_coarser(n))
11965 {
11966 // in 2d, if the child's neighbor is coarser, then it has
11967 // no children. however, in 3d it might be
11968 // otherwise. consider for example, that our face might be
11969 // refined with cut_x, but the neighbor is refined with
11970 // cut_xy at that face. then the neighbor pointers of the
11971 // children of our cell will point to the common neighbor
11972 // cell, not to its children. what we really want to know
11973 // in the following is, whether the neighbor cell is
11974 // refined twice with reference to our cell. that only
11975 // has to be asked, if the child's neighbor is not a
11976 // coarser one. we check whether some of the children on
11977 // the neighbor are not flagged for coarsening, in that
11978 // case we may not coarsen. it is enough to check the
11979 // first child because we have already fixed the coarsen
11980 // flags on finer levels
11981 if (child_neighbor->has_children() &&
11982 !(child_neighbor->child(0)->is_active() &&
11983 child_neighbor->child(0)->coarsen_flag_set()))
11984 return false;
11985
11986 // the same applies, if the neighbors children are not
11987 // refined but will be after refinement
11988 if (child_neighbor->refine_flag_set())
11989 return false;
11990 }
11991 }
11992 }
11993 return true;
11994 }
11995 };
11996
11997
12002 {
12003 template <int spacedim>
12004 static void
12007
12008 template <int dim, int spacedim>
12010 {
12011 std::vector<std::pair<unsigned int, unsigned int>> adjacent_cells(
12012 2 * triangulation.n_raw_faces(),
12013 {numbers::invalid_unsigned_int, numbers::invalid_unsigned_int});
12014
12015 const auto set_entry = [&](const auto &face_index, const auto &cell) {
12016 const std::pair<unsigned int, unsigned int> cell_pair = {
12017 cell->level(), cell->index()};
12018 unsigned int index;
12019
12020 if (adjacent_cells[2 * face_index].first ==
12022 adjacent_cells[2 * face_index].second ==
12024 {
12025 index = 2 * face_index + 0;
12026 }
12027 else
12028 {
12029 Assert(((adjacent_cells[2 * face_index + 1].first ==
12031 (adjacent_cells[2 * face_index + 1].second ==
12034 index = 2 * face_index + 1;
12035 }
12036
12037 adjacent_cells[index] = cell_pair;
12038 };
12039
12040 const auto get_entry =
12041 [&](const auto &face_index,
12042 const auto &cell) -> TriaIterator<CellAccessor<dim, spacedim>> {
12043 auto test = adjacent_cells[2 * face_index];
12044
12045 if (test == std::pair<unsigned int, unsigned int>(cell->level(),
12046 cell->index()))
12047 test = adjacent_cells[2 * face_index + 1];
12048
12049 if ((test.first != numbers::invalid_unsigned_int) &&
12050 (test.second != numbers::invalid_unsigned_int))
12052 test.first,
12053 test.second);
12054 else
12056 };
12057
12058 for (const auto &cell : triangulation.cell_iterators())
12059 for (const auto &face : cell->face_iterators())
12060 {
12061 set_entry(face->index(), cell);
12062
12063 if (cell->is_active() && face->has_children())
12064 for (unsigned int c = 0; c < face->n_children(); ++c)
12065 set_entry(face->child(c)->index(), cell);
12066 }
12067
12068 for (const auto &cell : triangulation.cell_iterators())
12069 for (auto f : cell->face_indices())
12070 cell->set_neighbor(f, get_entry(cell->face(f)->index(), cell));
12071 }
12072
12073 template <int dim, int spacedim>
12074 static void
12078 std::vector<unsigned int> &line_cell_count,
12079 std::vector<unsigned int> &quad_cell_count)
12080 {
12082 (void)triangulation;
12083 (void)cell;
12084 (void)line_cell_count;
12085 (void)quad_cell_count;
12086 }
12087
12088 template <int dim, int spacedim>
12091 const bool check_for_distorted_cells)
12092 {
12093 return Implementation::execute_refinement_isotropic(
12094 triangulation, check_for_distorted_cells);
12095 }
12096
12097 template <int dim, int spacedim>
12098 static void
12101 {
12102 // nothing to do since anisotropy is not supported
12103 (void)triangulation;
12104 }
12105
12106 template <int dim, int spacedim>
12107 static void
12110 {
12111 Implementation::prepare_refinement_dim_dependent(triangulation);
12112 }
12113
12114 template <int dim, int spacedim>
12115 static bool
12118 {
12120
12121 return false;
12122 }
12123 };
12124
12125
12126 template <int dim, int spacedim>
12129 {
12130 static const FlatManifold<dim, spacedim> flat_manifold;
12131 return flat_manifold;
12132 }
12133 } // namespace TriangulationImplementation
12134} // namespace internal
12135
12136#ifndef DOXYGEN
12137
12138template <int dim, int spacedim>
12141
12142
12143
12144template <int dim, int spacedim>
12147 const MeshSmoothing smooth_grid,
12148 const bool check_for_distorted_cells)
12149 : cell_attached_data({0, 0, {}, {}})
12150 , smooth_grid(smooth_grid)
12151 , anisotropic_refinement(false)
12152 , check_for_distorted_cells(check_for_distorted_cells)
12153{
12154 if (dim == 1)
12155 {
12156 vertex_to_boundary_id_map_1d =
12157 std::make_unique<std::map<unsigned int, types::boundary_id>>();
12158 vertex_to_manifold_id_map_1d =
12159 std::make_unique<std::map<unsigned int, types::manifold_id>>();
12160 }
12161
12162 // connect the any_change signal to the other top level signals
12163 signals.create.connect(signals.any_change);
12164 signals.post_refinement.connect(signals.any_change);
12165 signals.clear.connect(signals.any_change);
12166 signals.mesh_movement.connect(signals.any_change);
12167}
12168
12169
12170
12171template <int dim, int spacedim>
12174 Triangulation<dim, spacedim> &&tria) noexcept
12175 : Subscriptor(std::move(tria))
12176 , smooth_grid(tria.smooth_grid)
12177 , reference_cells(std::move(tria.reference_cells))
12178 , periodic_face_pairs_level_0(std::move(tria.periodic_face_pairs_level_0))
12179 , periodic_face_map(std::move(tria.periodic_face_map))
12180 , levels(std::move(tria.levels))
12181 , faces(std::move(tria.faces))
12182 , vertices(std::move(tria.vertices))
12183 , vertices_used(std::move(tria.vertices_used))
12184 , manifolds(std::move(tria.manifolds))
12185 , anisotropic_refinement(tria.anisotropic_refinement)
12186 , check_for_distorted_cells(tria.check_for_distorted_cells)
12187 , number_cache(std::move(tria.number_cache))
12188 , vertex_to_boundary_id_map_1d(std::move(tria.vertex_to_boundary_id_map_1d))
12189 , vertex_to_manifold_id_map_1d(std::move(tria.vertex_to_manifold_id_map_1d))
12190{
12192
12193 if (tria.policy)
12194 this->policy = tria.policy->clone();
12195}
12196
12197
12198template <int dim, int spacedim>
12201 Triangulation<dim, spacedim> &&tria) noexcept
12202{
12203 Subscriptor::operator=(std::move(tria));
12204
12205 smooth_grid = tria.smooth_grid;
12206 reference_cells = std::move(tria.reference_cells);
12207 periodic_face_pairs_level_0 = std::move(tria.periodic_face_pairs_level_0);
12208 periodic_face_map = std::move(tria.periodic_face_map);
12209 levels = std::move(tria.levels);
12210 faces = std::move(tria.faces);
12211 vertices = std::move(tria.vertices);
12212 vertices_used = std::move(tria.vertices_used);
12213 manifolds = std::move(tria.manifolds);
12214 anisotropic_refinement = tria.anisotropic_refinement;
12215 number_cache = tria.number_cache;
12216 vertex_to_boundary_id_map_1d = std::move(tria.vertex_to_boundary_id_map_1d);
12217 vertex_to_manifold_id_map_1d = std::move(tria.vertex_to_manifold_id_map_1d);
12218
12220
12221 if (tria.policy)
12222 this->policy = tria.policy->clone();
12223
12224 return *this;
12225}
12226
12227
12228
12229template <int dim, int spacedim>
12232{
12233 // notify listeners that the triangulation is going down...
12234 try
12235 {
12236 signals.clear();
12237 }
12238 catch (...)
12239 {}
12240
12241 levels.clear();
12242
12243 // the vertex_to_boundary_id_map_1d field should be unused except in
12244 // 1d. double check this here, as destruction is a good place to
12245 // ensure that what we've done over the course of the lifetime of
12246 // this object makes sense
12247 AssertNothrow((dim == 1) || (vertex_to_boundary_id_map_1d == nullptr),
12249
12250 // the vertex_to_manifold_id_map_1d field should be also unused
12251 // except in 1d. check this as well
12252 AssertNothrow((dim == 1) || (vertex_to_manifold_id_map_1d == nullptr),
12254}
12255
12256
12257
12258template <int dim, int spacedim>
12261{
12262 // notify listeners that the triangulation is going down...
12263 signals.clear();
12264
12265 // ...and then actually clear all content of it
12266 clear_despite_subscriptions();
12267 periodic_face_pairs_level_0.clear();
12268 periodic_face_map.clear();
12269 reference_cells.clear();
12270
12271 cell_attached_data = {0, 0, {}, {}};
12272 data_serializer.clear();
12273}
12274
12275template <int dim, int spacedim>
12278{
12279 return MPI_COMM_SELF;
12280}
12281
12282
12283
12284template <int dim, int spacedim>
12286std::weak_ptr<const Utilities::MPI::Partitioner> Triangulation<dim, spacedim>::
12288{
12289 return number_cache.active_cell_index_partitioner;
12290}
12291
12292
12293
12294template <int dim, int spacedim>
12296std::weak_ptr<const Utilities::MPI::Partitioner> Triangulation<dim, spacedim>::
12297 global_level_cell_index_partitioner(const unsigned int level) const
12298{
12299 AssertIndexRange(level, this->n_levels());
12300
12301 return number_cache.level_cell_index_partitioners[level];
12302}
12303
12304
12305
12306template <int dim, int spacedim>
12309 const MeshSmoothing mesh_smoothing)
12310{
12311 smooth_grid = mesh_smoothing;
12312}
12313
12314
12315
12316template <int dim, int spacedim>
12320{
12321 return smooth_grid;
12322}
12323
12324
12325
12326template <int dim, int spacedim>
12329 const types::manifold_id m_number,
12330 const Manifold<dim, spacedim> &manifold_object)
12331{
12333
12334 manifolds[m_number] = manifold_object.clone();
12335}
12336
12337
12338
12339template <int dim, int spacedim>
12342 const types::manifold_id m_number)
12343{
12345
12346 // delete the entry located at number.
12347 manifolds[m_number] =
12349 spacedim>()
12350 .clone();
12351}
12352
12353
12354template <int dim, int spacedim>
12357{
12358 for (auto &m : manifolds)
12359 m.second = internal::TriangulationImplementation::
12360 get_default_flat_manifold<dim, spacedim>()
12361 .clone();
12362}
12363
12364
12365template <int dim, int spacedim>
12368 const types::manifold_id m_number)
12369{
12370 Assert(
12371 n_cells() > 0,
12372 ExcMessage(
12373 "Error: set_all_manifold_ids() can not be called on an empty Triangulation."));
12374
12375 for (const auto &cell : this->active_cell_iterators())
12376 cell->set_all_manifold_ids(m_number);
12377}
12378
12379
12380template <int dim, int spacedim>
12383 const types::manifold_id m_number)
12384{
12385 Assert(
12386 n_cells() > 0,
12387 ExcMessage(
12388 "Error: set_all_manifold_ids_on_boundary() can not be called on an empty Triangulation."));
12389
12390 for (const auto &cell : this->active_cell_iterators())
12391 for (auto f : GeometryInfo<dim>::face_indices())
12392 if (cell->face(f)->at_boundary())
12393 cell->face(f)->set_all_manifold_ids(m_number);
12394}
12395
12396
12397template <int dim, int spacedim>
12400 const types::boundary_id b_id,
12401 const types::manifold_id m_number)
12402{
12403 Assert(
12404 n_cells() > 0,
12405 ExcMessage(
12406 "Error: set_all_manifold_ids_on_boundary() can not be called on an empty Triangulation."));
12407
12408 bool boundary_found = false;
12409
12410 for (const auto &cell : this->active_cell_iterators())
12411 {
12412 // loop on faces
12413 for (auto f : GeometryInfo<dim>::face_indices())
12414 if (cell->face(f)->at_boundary() &&
12415 cell->face(f)->boundary_id() == b_id)
12416 {
12417 boundary_found = true;
12418 cell->face(f)->set_manifold_id(m_number);
12419 }
12420
12421 // loop on edges if dim >= 3
12422 if (dim >= 3)
12423 for (unsigned int e = 0; e < GeometryInfo<dim>::lines_per_cell; ++e)
12424 if (cell->line(e)->at_boundary() &&
12425 cell->line(e)->boundary_id() == b_id)
12426 {
12427 boundary_found = true;
12428 cell->line(e)->set_manifold_id(m_number);
12429 }
12430 }
12431
12432 (void)boundary_found;
12433 Assert(boundary_found, ExcBoundaryIdNotFound(b_id));
12434}
12435
12436
12437
12438template <int dim, int spacedim>
12441 const types::manifold_id m_number) const
12442{
12443 // check if flat manifold has been queried
12444 if (m_number == numbers::flat_manifold_id)
12445 return internal::TriangulationImplementation::
12446 get_default_flat_manifold<dim, spacedim>();
12447
12448 // look, if there is a manifold stored at
12449 // manifold_id number.
12450 const auto it = manifolds.find(m_number);
12451
12452 if (it != manifolds.end())
12453 {
12454 // if we have found an entry, return it
12455 return *(it->second);
12456 }
12457
12458 Assert(
12459 false,
12460 ExcMessage(
12461 "No manifold of the manifold id " + std::to_string(m_number) +
12462 " has been attached to the triangulation. "
12463 "Please attach the right manifold with Triangulation::set_manifold()."));
12464
12465 return internal::TriangulationImplementation::
12466 get_default_flat_manifold<dim, spacedim>(); // never reached
12467}
12468
12469
12470
12471template <int dim, int spacedim>
12473std::vector<types::boundary_id> Triangulation<dim, spacedim>::get_boundary_ids()
12474 const
12475{
12476 // in 1d, we store a map of all used boundary indicators. use it for
12477 // our purposes
12478 if (dim == 1)
12479 {
12480 std::vector<types::boundary_id> boundary_ids;
12481 for (std::map<unsigned int, types::boundary_id>::const_iterator p =
12482 vertex_to_boundary_id_map_1d->begin();
12483 p != vertex_to_boundary_id_map_1d->end();
12484 ++p)
12485 boundary_ids.push_back(p->second);
12486
12487 return boundary_ids;
12488 }
12489 else
12490 {
12491 std::set<types::boundary_id> b_ids;
12492 for (auto cell : active_cell_iterators())
12493 if (cell->is_locally_owned())
12494 for (const unsigned int face : cell->face_indices())
12495 if (cell->at_boundary(face))
12496 b_ids.insert(cell->face(face)->boundary_id());
12497 std::vector<types::boundary_id> boundary_ids(b_ids.begin(), b_ids.end());
12498 return boundary_ids;
12499 }
12500}
12501
12502
12503
12504template <int dim, int spacedim>
12506std::vector<types::manifold_id> Triangulation<dim, spacedim>::get_manifold_ids()
12507 const
12508{
12509 std::set<types::manifold_id> m_ids;
12510 for (const auto &cell : active_cell_iterators())
12511 if (cell->is_locally_owned())
12512 {
12513 m_ids.insert(cell->manifold_id());
12514 for (const auto &face : cell->face_iterators())
12515 m_ids.insert(face->manifold_id());
12516 if (dim == 3)
12517 {
12518 const auto line_indices = internal::TriaAccessorImplementation::
12519 Implementation::get_line_indices_of_cell(*cell);
12520 for (unsigned int l = 0; l < cell->n_lines(); ++l)
12521 {
12522 raw_line_iterator line(this, 0, line_indices[l]);
12523 m_ids.insert(line->manifold_id());
12524 }
12525 }
12526 }
12527 return {m_ids.begin(), m_ids.end()};
12528}
12529
12530#endif
12531/*-----------------------------------------------------------------*/
12532
12533#ifndef DOXYGEN
12534
12535template <int dim, int spacedim>
12538 const Triangulation<dim, spacedim> &other_tria)
12539{
12540 Assert((vertices.empty()) && (levels.empty()) && (faces == nullptr),
12541 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
12542 Assert((other_tria.levels.size() != 0) && (other_tria.vertices.size() != 0) &&
12543 (dim == 1 || other_tria.faces != nullptr),
12544 ExcMessage(
12545 "When calling Triangulation::copy_triangulation(), "
12546 "the target triangulation must be empty but the source "
12547 "triangulation (the argument to this function) must contain "
12548 "something. Here, it seems like the source does not "
12549 "contain anything at all."));
12550
12551
12552 // copy normal elements
12553 vertices = other_tria.vertices;
12554 vertices_used = other_tria.vertices_used;
12555 anisotropic_refinement = other_tria.anisotropic_refinement;
12556 smooth_grid = other_tria.smooth_grid;
12557 reference_cells = other_tria.reference_cells;
12558
12559 if (dim > 1)
12560 faces = std::make_unique<internal::TriangulationImplementation::TriaFaces>(
12561 *other_tria.faces);
12562
12563 for (const auto &p : other_tria.manifolds)
12564 set_manifold(p.first, *p.second);
12565
12566
12567 levels.reserve(other_tria.levels.size());
12568 for (unsigned int level = 0; level < other_tria.levels.size(); ++level)
12569 levels.push_back(
12570 std::make_unique<internal::TriangulationImplementation::TriaLevel>(
12571 *other_tria.levels[level]));
12572
12573 number_cache = other_tria.number_cache;
12574
12575 if (dim == 1)
12576 {
12577 vertex_to_boundary_id_map_1d =
12578 std::make_unique<std::map<unsigned int, types::boundary_id>>(
12579 *other_tria.vertex_to_boundary_id_map_1d);
12580
12581 vertex_to_manifold_id_map_1d =
12582 std::make_unique<std::map<unsigned int, types::manifold_id>>(
12583 *other_tria.vertex_to_manifold_id_map_1d);
12584 }
12585
12586 if (other_tria.policy)
12587 this->policy = other_tria.policy->clone();
12588
12589 // periodic faces
12590 this->periodic_face_pairs_level_0.reserve(
12591 other_tria.periodic_face_pairs_level_0.size());
12592
12593 for (const auto &other_entry : other_tria.periodic_face_pairs_level_0)
12594 {
12595 auto entry = other_entry;
12596 entry.cell[0] =
12597 cell_iterator(this, entry.cell[0]->level(), entry.cell[0]->index());
12598 entry.cell[1] =
12599 cell_iterator(this, entry.cell[1]->level(), entry.cell[1]->index());
12600 periodic_face_pairs_level_0.emplace_back(entry);
12601 }
12602
12603 for (auto [first_cell_, second_cell_and_orientation] :
12604 other_tria.periodic_face_map)
12605 {
12606 auto first_cell = first_cell_; // make copy since key is const
12607 first_cell.first = cell_iterator(this,
12608 first_cell.first->level(),
12609 first_cell.first->index());
12610 second_cell_and_orientation.first.first =
12611 cell_iterator(this,
12612 second_cell_and_orientation.first.first->level(),
12613 second_cell_and_orientation.first.first->index());
12614
12615 this->periodic_face_map[first_cell] = second_cell_and_orientation;
12616 }
12617
12618 // inform those who are listening on other_tria of the copy operation
12619 other_tria.signals.copy(*this);
12620 // also inform all listeners of the current triangulation that the
12621 // triangulation has been created
12622 signals.create();
12623
12624 // note that we need not copy the
12625 // subscriptor!
12626}
12627
12628
12629
12630template <int dim, int spacedim>
12633{
12634 this->update_reference_cells();
12635
12636 if (this->all_reference_cells_are_hyper_cube())
12637 {
12638 this->policy =
12640 dim,
12641 spacedim,
12643 }
12644 else
12645 {
12646 this->policy =
12648 dim,
12649 spacedim,
12651 }
12652}
12653
12654
12655
12656template <int dim, int spacedim>
12659 const std::vector<Point<spacedim>> &v,
12660 const std::vector<CellData<dim>> &cells,
12661 const SubCellData &subcelldata)
12662{
12663 Assert((vertices.empty()) && (levels.empty()) && (faces == nullptr),
12664 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
12665 // check that no forbidden arrays
12666 // are used
12667 Assert(subcelldata.check_consistency(dim), ExcInternalError());
12668
12669 // try to create a triangulation; if this fails, we still want to
12670 // throw an exception but if we just do so we'll get into trouble
12671 // because sometimes other objects are already attached to it:
12672 try
12673 {
12675 create_triangulation(v, cells, subcelldata, *this);
12676 }
12677 catch (...)
12678 {
12679 clear_despite_subscriptions();
12680 throw;
12681 }
12682
12683 reset_policy();
12684
12685 // update our counts of the various elements of a triangulation, and set
12686 // active_cell_indices of all cells
12687 reset_cell_vertex_indices_cache();
12689 *this, levels.size(), number_cache);
12690 reset_active_cell_indices();
12691 reset_global_cell_indices();
12692
12693 // now verify that there are indeed no distorted cells. as per the
12694 // documentation of this class, we first collect all distorted cells
12695 // and then throw an exception if there are any
12696 if (check_for_distorted_cells)
12697 {
12698 DistortedCellList distorted_cells = collect_distorted_coarse_cells(*this);
12699 // throw the array (and fill the various location fields) if
12700 // there are distorted cells. otherwise, just fall off the end
12701 // of the function
12702 AssertThrow(distorted_cells.distorted_cells.empty(), distorted_cells);
12703 }
12704
12705
12706 /*
12707 When the triangulation is a manifold (dim < spacedim) and made of
12708 quadrilaterals, the normal field provided from the map class depends on
12709 the order of the vertices. It may happen that this normal field is
12710 discontinuous. The following code takes care that this is not the case by
12711 setting the cell direction flag on those cell that produce the wrong
12712 orientation.
12713
12714 To determine if 2 neighbors have the same or opposite orientation we use
12715 a truth table. Its entries are indexed by the local indices of the
12716 common face. For example if two elements share a face, and this face is
12717 face 0 for element 0 and face 1 for element 1, then table(0,1) will tell
12718 whether the orientation are the same (true) or opposite (false).
12719
12720 Even though there may be a combinatorial/graph theory argument to get this
12721 table in any dimension, I tested by hand all the different possible cases
12722 in 1D and 2D to generate the table.
12723
12724 Assuming that a surface respects the standard orientation for 2d meshes,
12725 the truth tables are symmetric and their true values are the following
12726
12727 - 1D curves: (0,1)
12728 - 2D surface: (0,1),(0,2),(1,3),(2,3)
12729
12730 We store this data using an n_faces x n_faces full matrix, which is
12731 actually much bigger than the minimal data required, but it makes the code
12732 more readable.
12733
12734 */
12735 if ((dim == spacedim - 1) && all_reference_cells_are_hyper_cube())
12736 {
12739 switch (dim)
12740 {
12741 case 1:
12742 {
12743 const bool values[][2] = {{false, true}, {true, false}};
12744 for (const unsigned int i : GeometryInfo<dim>::face_indices())
12745 for (const unsigned int j : GeometryInfo<dim>::face_indices())
12746 correct(i, j) = values[i][j];
12747 break;
12748 }
12749 case 2:
12750 {
12751 const bool values[][4] = {{false, true, true, false},
12752 {true, false, false, true},
12753 {true, false, false, true},
12754 {false, true, true, false}};
12755 for (const unsigned int i : GeometryInfo<dim>::face_indices())
12756 for (const unsigned int j : GeometryInfo<dim>::face_indices())
12757 correct(i, j) = (values[i][j]);
12758 break;
12759 }
12760 default:
12762 }
12763
12764
12765 std::list<active_cell_iterator> this_round, next_round;
12766 active_cell_iterator neighbor;
12767
12768 // Start with the first cell and (arbitrarily) decide that its
12769 // direction flag should be 'true':
12770 this_round.push_back(begin_active());
12771 begin_active()->set_direction_flag(true);
12772 begin_active()->set_user_flag();
12773
12774 while (this_round.size() > 0)
12775 {
12776 for (const auto &cell : this_round)
12777 {
12778 for (const unsigned int i : cell->face_indices())
12779 {
12780 if (cell->face(i)->at_boundary() == false)
12781 {
12782 // Consider the i'th neighbor of a cell for
12783 // which we have already set the direction:
12784 neighbor = cell->neighbor(i);
12785
12786 const unsigned int nb_of_nb =
12787 cell->neighbor_of_neighbor(i);
12788
12789 // If we already saw this neighboring cell,
12790 // check that everything is fine:
12791 if (neighbor->user_flag_set())
12792 {
12793 Assert(
12794 !(correct(i, nb_of_nb) ^
12795 (neighbor->direction_flag() ==
12796 cell->direction_flag())),
12797 ExcMessage(
12798 "The triangulation you are trying to create is not orientable."));
12799 }
12800 else
12801 {
12802 // We had not seen this cell yet. Set its
12803 // orientation flag (if necessary), mark it
12804 // as treated via the user flag, and push it
12805 // onto the list of cells to start work from
12806 // the next time around:
12807 if (correct(i, nb_of_nb) ^
12808 (neighbor->direction_flag() ==
12809 cell->direction_flag()))
12810 neighbor->set_direction_flag(
12811 !neighbor->direction_flag());
12812 neighbor->set_user_flag();
12813 next_round.push_back(neighbor);
12814 }
12815 }
12816 }
12817 }
12818
12819 // Before we quit let's check that if the triangulation is
12820 // disconnected that we still get all cells by starting
12821 // again from the first cell we haven't treated yet -- that
12822 // is, the first cell of the next disconnected component we
12823 // had not yet touched.
12824 if (next_round.empty())
12825 for (const auto &cell : this->active_cell_iterators())
12826 if (cell->user_flag_set() == false)
12827 {
12828 next_round.push_back(cell);
12829 cell->set_direction_flag(true);
12830 cell->set_user_flag();
12831 break;
12832 }
12833
12834 // Go on to the next round:
12835 next_round.swap(this_round);
12836 next_round.clear();
12837 }
12838 clear_user_flags();
12839 }
12840
12841 // inform all listeners that the triangulation has been created
12842 signals.create();
12843}
12844
12845
12846
12847template <int dim, int spacedim>
12851{
12852 // 1) create coarse grid
12854 construction_data.coarse_cells,
12855 SubCellData());
12856
12857 // create a copy of cell_infos such that we can sort them
12858 auto cell_infos = construction_data.cell_infos;
12859
12860 // sort cell_infos on each level separately
12861 for (auto &cell_info : cell_infos)
12862 std::sort(
12863 cell_info.begin(),
12864 cell_info.end(),
12867 const CellId a_id(a.id);
12868 const CellId b_id(b.id);
12869
12870 const auto a_coarse_cell_index =
12871 this->coarse_cell_id_to_coarse_cell_index(a_id.get_coarse_cell_id());
12872 const auto b_coarse_cell_index =
12873 this->coarse_cell_id_to_coarse_cell_index(b_id.get_coarse_cell_id());
12874
12875 // according to their coarse-cell index and if that is
12876 // same according to their cell id (the result is that
12877 // cells on each level are sorted according to their
12878 // index on that level - what we need in the following
12879 // operations)
12880 if (a_coarse_cell_index != b_coarse_cell_index)
12881 return a_coarse_cell_index < b_coarse_cell_index;
12882 else
12883 return a_id < b_id;
12884 });
12885
12886 // 2) create all levels via a sequence of refinements. note that
12887 // we must make sure that we actually have cells on this level,
12888 // which is not clear in a parallel context for some processes
12889 for (unsigned int level = 0;
12890 level < cell_infos.size() && !cell_infos[level].empty();
12891 ++level)
12892 {
12893 // a) set manifold ids here (because new vertices have to be
12894 // positioned correctly during each refinement step)
12895 {
12896 auto cell = this->begin(level);
12897 auto cell_info = cell_infos[level].begin();
12898 for (; cell_info != cell_infos[level].end(); ++cell_info)
12899 {
12900 while (cell_info->id != cell->id().template to_binary<dim>())
12901 ++cell;
12902 if (dim == 2)
12903 for (const auto face : cell->face_indices())
12904 cell->face(face)->set_manifold_id(
12905 cell_info->manifold_line_ids[face]);
12906 else if (dim == 3)
12907 {
12908 for (const auto face : cell->face_indices())
12909 cell->face(face)->set_manifold_id(
12910 cell_info->manifold_quad_ids[face]);
12911
12912 const auto line_indices = internal::TriaAccessorImplementation::
12913 Implementation::get_line_indices_of_cell(*cell);
12914 for (unsigned int l = 0; l < cell->n_lines(); ++l)
12915 {
12916 raw_line_iterator line(this, 0, line_indices[l]);
12917 line->set_manifold_id(cell_info->manifold_line_ids[l]);
12918 }
12919 }
12920
12921 cell->set_manifold_id(cell_info->manifold_id);
12922 }
12923 }
12924
12925 // b) perform refinement on all levels but on the finest
12926 if (level + 1 != cell_infos.size())
12927 {
12928 // find cells that should have children and mark them for
12929 // refinement
12930 auto coarse_cell = this->begin(level);
12931 auto fine_cell_info = cell_infos[level + 1].begin();
12932
12933 // loop over all cells on the next level
12934 for (; fine_cell_info != cell_infos[level + 1].end();
12935 ++fine_cell_info)
12936 {
12937 // find the parent of that cell
12938 while (
12939 !coarse_cell->id().is_parent_of(CellId(fine_cell_info->id)))
12940 ++coarse_cell;
12941
12942 // set parent for refinement
12943 coarse_cell->set_refine_flag();
12944 }
12945
12946 // execute refinement
12947 ::Triangulation<dim,
12948 spacedim>::execute_coarsening_and_refinement();
12949 }
12950 }
12951
12952 // 3) set boundary ids
12953 for (unsigned int level = 0;
12954 level < cell_infos.size() && !cell_infos[level].empty();
12955 ++level)
12956 {
12957 auto cell = this->begin(level);
12958 auto cell_info = cell_infos[level].begin();
12959 for (; cell_info != cell_infos[level].end(); ++cell_info)
12960 {
12961 // find cell that has the correct cell
12962 while (cell_info->id != cell->id().template to_binary<dim>())
12963 ++cell;
12964
12965 // boundary ids
12966 for (auto pair : cell_info->boundary_ids)
12967 if (cell->face(pair.first)->at_boundary())
12968 cell->face(pair.first)->set_boundary_id(pair.second);
12969 }
12970 }
12971
12972 // inform all listeners that the triangulation has been created
12973 signals.create();
12974}
12975
12976
12977template <int dim, int spacedim>
12980{
12981 AssertThrow(dim + 1 == spacedim,
12982 ExcMessage(
12983 "This function can only be called if dim == spacedim-1."));
12984 for (const auto &cell : this->active_cell_iterators())
12985 cell->set_direction_flag(!cell->direction_flag());
12986}
12987
12988
12989
12990template <int dim, int spacedim>
12993{
12994 Assert(n_cells() > 0,
12995 ExcMessage("Error: An empty Triangulation can not be refined."));
12996
12997 for (const auto &cell : this->active_cell_iterators())
12998 {
12999 cell->clear_coarsen_flag();
13000 cell->set_refine_flag();
13001 }
13002}
13003
13004
13005
13006template <int dim, int spacedim>
13008void Triangulation<dim, spacedim>::refine_global(const unsigned int times)
13009{
13010 for (unsigned int i = 0; i < times; ++i)
13011 {
13012 set_all_refine_flags();
13013 execute_coarsening_and_refinement();
13014 }
13015}
13016
13017
13018
13019template <int dim, int spacedim>
13021void Triangulation<dim, spacedim>::coarsen_global(const unsigned int times)
13022{
13023 for (unsigned int i = 0; i < times; ++i)
13024 {
13025 for (const auto &cell : this->active_cell_iterators())
13026 {
13027 cell->clear_refine_flag();
13028 cell->set_coarsen_flag();
13029 }
13030 execute_coarsening_and_refinement();
13031 }
13032}
13033
13034
13035#endif
13036/*-------------------- refine/coarsen flags -------------------------*/
13037
13038#ifndef DOXYGEN
13039
13040template <int dim, int spacedim>
13042void Triangulation<dim, spacedim>::save_refine_flags(std::vector<bool> &v) const
13043{
13044 v.resize(dim * n_active_cells(), false);
13045 std::vector<bool>::iterator i = v.begin();
13046
13047 for (const auto &cell : this->active_cell_iterators())
13048 for (unsigned int j = 0; j < dim; ++j, ++i)
13049 if (cell->refine_flag_set() & (1 << j))
13050 *i = true;
13051
13052 Assert(i == v.end(), ExcInternalError());
13053}
13054
13055
13056
13057template <int dim, int spacedim>
13059void Triangulation<dim, spacedim>::save_refine_flags(std::ostream &out) const
13060{
13061 std::vector<bool> v;
13062 save_refine_flags(v);
13063 write_bool_vector(mn_tria_refine_flags_begin,
13064 v,
13066 out);
13067}
13068
13069
13070
13071template <int dim, int spacedim>
13074{
13075 std::vector<bool> v;
13076 read_bool_vector(mn_tria_refine_flags_begin, v, mn_tria_refine_flags_end, in);
13077 load_refine_flags(v);
13078}
13079
13080
13081
13082template <int dim, int spacedim>
13084void Triangulation<dim, spacedim>::load_refine_flags(const std::vector<bool> &v)
13085{
13086 AssertThrow(v.size() == dim * n_active_cells(), ExcGridReadError());
13087
13088 std::vector<bool>::const_iterator i = v.begin();
13089 for (const auto &cell : this->active_cell_iterators())
13090 {
13091 unsigned int ref_case = 0;
13092
13093 for (unsigned int j = 0; j < dim; ++j, ++i)
13094 if (*i == true)
13095 ref_case += 1 << j;
13097 ExcGridReadError());
13098 if (ref_case > 0)
13099 cell->set_refine_flag(RefinementCase<dim>(ref_case));
13100 else
13101 cell->clear_refine_flag();
13102 }
13103
13104 Assert(i == v.end(), ExcInternalError());
13105}
13106
13107
13108
13109template <int dim, int spacedim>
13112 std::vector<bool> &v) const
13113{
13114 v.resize(n_active_cells(), false);
13115 std::vector<bool>::iterator i = v.begin();
13116 for (const auto &cell : this->active_cell_iterators())
13117 {
13118 *i = cell->coarsen_flag_set();
13119 ++i;
13120 }
13121
13122 Assert(i == v.end(), ExcInternalError());
13123}
13124
13125
13126
13127template <int dim, int spacedim>
13129void Triangulation<dim, spacedim>::save_coarsen_flags(std::ostream &out) const
13130{
13131 std::vector<bool> v;
13132 save_coarsen_flags(v);
13133 write_bool_vector(mn_tria_coarsen_flags_begin,
13134 v,
13136 out);
13137}
13138
13139
13140
13141template <int dim, int spacedim>
13144{
13145 std::vector<bool> v;
13146 read_bool_vector(mn_tria_coarsen_flags_begin,
13147 v,
13149 in);
13150 load_coarsen_flags(v);
13151}
13152
13153
13154
13155template <int dim, int spacedim>
13158 const std::vector<bool> &v)
13159{
13160 Assert(v.size() == n_active_cells(), ExcGridReadError());
13161
13162 std::vector<bool>::const_iterator i = v.begin();
13163 for (const auto &cell : this->active_cell_iterators())
13164 {
13165 if (*i == true)
13166 cell->set_coarsen_flag();
13167 else
13168 cell->clear_coarsen_flag();
13169 ++i;
13170 }
13171
13172 Assert(i == v.end(), ExcInternalError());
13173}
13174
13175
13176template <int dim, int spacedim>
13179{
13180 return anisotropic_refinement;
13181}
13182
13183
13184#endif
13185
13186namespace internal
13187{
13188 namespace
13189 {
13190 std::vector<std::vector<bool>>
13191 extract_raw_coarsen_flags(
13192 const std::vector<std::unique_ptr<
13194 {
13195 std::vector<std::vector<bool>> coarsen_flags(levels.size());
13196 for (unsigned int level = 0; level < levels.size(); ++level)
13197 coarsen_flags[level] = levels[level]->coarsen_flags;
13198 return coarsen_flags;
13199 }
13200
13201 std::vector<std::vector<std::uint8_t>>
13202 extract_raw_refine_flags(
13203 const std::vector<std::unique_ptr<
13205 {
13206 std::vector<std::vector<std::uint8_t>> refine_flags(levels.size());
13207 for (unsigned int level = 0; level < levels.size(); ++level)
13208 refine_flags[level] = levels[level]->refine_flags;
13209 return refine_flags;
13210 }
13211 } // namespace
13212} // namespace internal
13213
13214
13215/*-------------------- user data/flags -------------------------*/
13216
13217
13218namespace
13219{
13220 // clear user data of cells
13221 void
13222 clear_user_data(std::vector<std::unique_ptr<
13224 {
13225 for (auto &level : levels)
13226 level->cells.clear_user_data();
13227 }
13228
13229
13230 // clear user data of faces
13231 void
13233 {
13234 if (faces->dim == 2)
13235 {
13236 faces->lines.clear_user_data();
13237 }
13238
13239
13240 if (faces->dim == 3)
13241 {
13242 faces->lines.clear_user_data();
13243 faces->quads.clear_user_data();
13244 }
13245 }
13246} // namespace
13247
13248#ifndef DOXYGEN
13249
13250template <int dim, int spacedim>
13253{
13254 // let functions in anonymous namespace do their work
13255 ::clear_user_data(levels);
13256 if (dim > 1)
13257 ::clear_user_data(faces.get());
13258}
13259
13260
13261
13262namespace
13263{
13264 void
13265 clear_user_flags_line(
13266 unsigned int dim,
13267 std::vector<
13268 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
13269 &levels,
13271 {
13272 if (dim == 1)
13273 {
13274 for (const auto &level : levels)
13275 level->cells.clear_user_flags();
13276 }
13277 else if (dim == 2 || dim == 3)
13278 {
13279 faces->lines.clear_user_flags();
13280 }
13281 else
13282 {
13284 }
13285 }
13286} // namespace
13287
13288
13289template <int dim, int spacedim>
13292{
13293 ::clear_user_flags_line(dim, levels, faces.get());
13294}
13295
13296
13297
13298namespace
13299{
13300 void
13301 clear_user_flags_quad(
13302 unsigned int dim,
13303 std::vector<
13304 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
13305 &levels,
13307 {
13308 if (dim == 1)
13309 {
13310 // nothing to do in 1d
13311 }
13312 else if (dim == 2)
13313 {
13314 for (const auto &level : levels)
13315 level->cells.clear_user_flags();
13316 }
13317 else if (dim == 3)
13318 {
13319 faces->quads.clear_user_flags();
13320 }
13321 else
13322 {
13324 }
13325 }
13326} // namespace
13327
13328
13329template <int dim, int spacedim>
13332{
13333 ::clear_user_flags_quad(dim, levels, faces.get());
13334}
13335
13336
13337
13338namespace
13339{
13340 void
13341 clear_user_flags_hex(
13342 unsigned int dim,
13343 std::vector<
13344 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
13345 &levels,
13347 {
13348 if (dim == 1)
13349 {
13350 // nothing to do in 1d
13351 }
13352 else if (dim == 2)
13353 {
13354 // nothing to do in 2d
13355 }
13356 else if (dim == 3)
13357 {
13358 for (const auto &level : levels)
13359 level->cells.clear_user_flags();
13360 }
13361 else
13362 {
13364 }
13365 }
13366} // namespace
13367
13368
13369template <int dim, int spacedim>
13372{
13373 ::clear_user_flags_hex(dim, levels, faces.get());
13374}
13375
13376
13377
13378template <int dim, int spacedim>
13381{
13382 clear_user_flags_line();
13383 clear_user_flags_quad();
13384 clear_user_flags_hex();
13385}
13386
13387
13388
13389template <int dim, int spacedim>
13391void Triangulation<dim, spacedim>::save_user_flags(std::ostream &out) const
13392{
13393 save_user_flags_line(out);
13394
13395 if (dim >= 2)
13396 save_user_flags_quad(out);
13397
13398 if (dim >= 3)
13399 save_user_flags_hex(out);
13400
13401 if (dim >= 4)
13403}
13404
13405
13406
13407template <int dim, int spacedim>
13409void Triangulation<dim, spacedim>::save_user_flags(std::vector<bool> &v) const
13410{
13411 // clear vector and append
13412 // all the stuff later on
13413 v.clear();
13414
13415 std::vector<bool> tmp;
13416
13417 save_user_flags_line(tmp);
13418 v.insert(v.end(), tmp.begin(), tmp.end());
13419
13420 if (dim >= 2)
13421 {
13422 save_user_flags_quad(tmp);
13423 v.insert(v.end(), tmp.begin(), tmp.end());
13424 }
13425
13426 if (dim >= 3)
13427 {
13428 save_user_flags_hex(tmp);
13429 v.insert(v.end(), tmp.begin(), tmp.end());
13430 }
13431
13432 if (dim >= 4)
13434}
13435
13436
13437
13438template <int dim, int spacedim>
13441{
13442 load_user_flags_line(in);
13443
13444 if (dim >= 2)
13445 load_user_flags_quad(in);
13446
13447 if (dim >= 3)
13448 load_user_flags_hex(in);
13449
13450 if (dim >= 4)
13452}
13453
13454
13455
13456template <int dim, int spacedim>
13458void Triangulation<dim, spacedim>::load_user_flags(const std::vector<bool> &v)
13459{
13460 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
13461 std::vector<bool> tmp;
13462
13463 // first extract the flags
13464 // belonging to lines
13465 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
13466 // and set the lines
13467 load_user_flags_line(tmp);
13468
13469 if (dim >= 2)
13470 {
13471 tmp.clear();
13472 tmp.insert(tmp.end(),
13473 v.begin() + n_lines(),
13474 v.begin() + n_lines() + n_quads());
13475 load_user_flags_quad(tmp);
13476 }
13477
13478 if (dim >= 3)
13479 {
13480 tmp.clear();
13481 tmp.insert(tmp.end(),
13482 v.begin() + n_lines() + n_quads(),
13483 v.begin() + n_lines() + n_quads() + n_hexs());
13484 load_user_flags_hex(tmp);
13485 }
13486
13487 if (dim >= 4)
13489}
13490
13491
13492
13493template <int dim, int spacedim>
13496 std::vector<bool> &v) const
13497{
13498 v.resize(n_lines(), false);
13499 std::vector<bool>::iterator i = v.begin();
13500 line_iterator line = begin_line(), endl = end_line();
13501 for (; line != endl; ++line, ++i)
13502 *i = line->user_flag_set();
13503
13504 Assert(i == v.end(), ExcInternalError());
13505}
13506
13507
13508
13509template <int dim, int spacedim>
13511void Triangulation<dim, spacedim>::save_user_flags_line(std::ostream &out) const
13512{
13513 std::vector<bool> v;
13514 save_user_flags_line(v);
13515 write_bool_vector(mn_tria_line_user_flags_begin,
13516 v,
13518 out);
13519}
13520
13521
13522
13523template <int dim, int spacedim>
13526{
13527 std::vector<bool> v;
13528 read_bool_vector(mn_tria_line_user_flags_begin,
13529 v,
13531 in);
13532 load_user_flags_line(v);
13533}
13534
13535
13536
13537template <int dim, int spacedim>
13540 const std::vector<bool> &v)
13541{
13542 Assert(v.size() == n_lines(), ExcGridReadError());
13543
13544 line_iterator line = begin_line(), endl = end_line();
13545 std::vector<bool>::const_iterator i = v.begin();
13546 for (; line != endl; ++line, ++i)
13547 if (*i == true)
13548 line->set_user_flag();
13549 else
13550 line->clear_user_flag();
13551
13552 Assert(i == v.end(), ExcInternalError());
13553}
13554
13555#endif
13556
13557namespace
13558{
13559 template <typename Iterator>
13560 bool
13561 get_user_flag(const Iterator &i)
13562 {
13563 return i->user_flag_set();
13564 }
13565
13566
13567
13568 template <int structdim, int dim, int spacedim>
13569 bool
13571 {
13573 return false;
13574 }
13575
13576
13577
13578 template <typename Iterator>
13579 void
13580 set_user_flag(const Iterator &i)
13581 {
13582 i->set_user_flag();
13583 }
13584
13585
13586
13587 template <int structdim, int dim, int spacedim>
13588 void
13590 {
13592 }
13593
13594
13595
13596 template <typename Iterator>
13597 void
13598 clear_user_flag(const Iterator &i)
13599 {
13600 i->clear_user_flag();
13601 }
13602
13603
13604
13605 template <int structdim, int dim, int spacedim>
13606 void
13607 clear_user_flag(
13609 {
13611 }
13612} // namespace
13613
13614#ifndef DOXYGEN
13615
13616template <int dim, int spacedim>
13619 std::vector<bool> &v) const
13620{
13621 v.resize(n_quads(), false);
13622
13623 if (dim >= 2)
13624 {
13625 std::vector<bool>::iterator i = v.begin();
13626 quad_iterator quad = begin_quad(), endq = end_quad();
13627 for (; quad != endq; ++quad, ++i)
13628 *i = get_user_flag(quad);
13629
13630 Assert(i == v.end(), ExcInternalError());
13631 }
13632}
13633
13634
13635
13636template <int dim, int spacedim>
13638void Triangulation<dim, spacedim>::save_user_flags_quad(std::ostream &out) const
13639{
13640 std::vector<bool> v;
13641 save_user_flags_quad(v);
13642 write_bool_vector(mn_tria_quad_user_flags_begin,
13643 v,
13645 out);
13646}
13647
13648
13649
13650template <int dim, int spacedim>
13653{
13654 std::vector<bool> v;
13655 read_bool_vector(mn_tria_quad_user_flags_begin,
13656 v,
13658 in);
13659 load_user_flags_quad(v);
13660}
13661
13662
13663
13664template <int dim, int spacedim>
13667 const std::vector<bool> &v)
13668{
13669 Assert(v.size() == n_quads(), ExcGridReadError());
13670
13671 if (dim >= 2)
13672 {
13673 quad_iterator quad = begin_quad(), endq = end_quad();
13674 std::vector<bool>::const_iterator i = v.begin();
13675 for (; quad != endq; ++quad, ++i)
13676 if (*i == true)
13677 set_user_flag(quad);
13678 else
13679 clear_user_flag(quad);
13680
13681 Assert(i == v.end(), ExcInternalError());
13682 }
13683}
13684
13685
13686
13687template <int dim, int spacedim>
13690 std::vector<bool> &v) const
13691{
13692 v.resize(n_hexs(), false);
13693
13694 if (dim >= 3)
13695 {
13696 std::vector<bool>::iterator i = v.begin();
13697 hex_iterator hex = begin_hex(), endh = end_hex();
13698 for (; hex != endh; ++hex, ++i)
13699 *i = get_user_flag(hex);
13700
13701 Assert(i == v.end(), ExcInternalError());
13702 }
13703}
13704
13705
13706
13707template <int dim, int spacedim>
13709void Triangulation<dim, spacedim>::save_user_flags_hex(std::ostream &out) const
13710{
13711 std::vector<bool> v;
13712 save_user_flags_hex(v);
13713 write_bool_vector(mn_tria_hex_user_flags_begin,
13714 v,
13716 out);
13717}
13718
13719
13720
13721template <int dim, int spacedim>
13724{
13725 std::vector<bool> v;
13726 read_bool_vector(mn_tria_hex_user_flags_begin,
13727 v,
13729 in);
13730 load_user_flags_hex(v);
13731}
13732
13733
13734
13735template <int dim, int spacedim>
13738 const std::vector<bool> &v)
13739{
13740 Assert(v.size() == n_hexs(), ExcGridReadError());
13741
13742 if (dim >= 3)
13743 {
13744 hex_iterator hex = begin_hex(), endh = end_hex();
13745 std::vector<bool>::const_iterator i = v.begin();
13746 for (; hex != endh; ++hex, ++i)
13747 if (*i == true)
13748 set_user_flag(hex);
13749 else
13750 clear_user_flag(hex);
13751
13752 Assert(i == v.end(), ExcInternalError());
13753 }
13754}
13755
13756
13757
13758template <int dim, int spacedim>
13761 std::vector<unsigned int> &v) const
13762{
13763 // clear vector and append all the
13764 // stuff later on
13765 v.clear();
13766
13767 std::vector<unsigned int> tmp;
13768
13769 save_user_indices_line(tmp);
13770 v.insert(v.end(), tmp.begin(), tmp.end());
13771
13772 if (dim >= 2)
13773 {
13774 save_user_indices_quad(tmp);
13775 v.insert(v.end(), tmp.begin(), tmp.end());
13776 }
13777
13778 if (dim >= 3)
13779 {
13780 save_user_indices_hex(tmp);
13781 v.insert(v.end(), tmp.begin(), tmp.end());
13782 }
13783
13784 if (dim >= 4)
13786}
13787
13788
13789
13790template <int dim, int spacedim>
13793 const std::vector<unsigned int> &v)
13794{
13795 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
13796 std::vector<unsigned int> tmp;
13797
13798 // first extract the indices
13799 // belonging to lines
13800 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
13801 // and set the lines
13802 load_user_indices_line(tmp);
13803
13804 if (dim >= 2)
13805 {
13806 tmp.clear();
13807 tmp.insert(tmp.end(),
13808 v.begin() + n_lines(),
13809 v.begin() + n_lines() + n_quads());
13810 load_user_indices_quad(tmp);
13811 }
13812
13813 if (dim >= 3)
13814 {
13815 tmp.clear();
13816 tmp.insert(tmp.end(),
13817 v.begin() + n_lines() + n_quads(),
13818 v.begin() + n_lines() + n_quads() + n_hexs());
13819 load_user_indices_hex(tmp);
13820 }
13821
13822 if (dim >= 4)
13824}
13825
13826template <int dim, int spacedim>
13828void Triangulation<dim, spacedim>::save(const std::string &filename) const
13829{
13830 // Create boost archive then call alternative version of the save function
13831 std::ofstream ofs(filename);
13832 boost::archive::text_oarchive oa(ofs, boost::archive::no_header);
13833 save(oa, 0);
13834}
13835
13836template <int dim, int spacedim>
13838void Triangulation<dim, spacedim>::load(const std::string &filename)
13839{
13840 // Create boost archive then call alternative version of the load function
13841 std::ifstream ifs(filename);
13842 boost::archive::text_iarchive ia(ifs, boost::archive::no_header);
13843 load(ia, 0);
13844}
13845
13846#endif
13847namespace
13848{
13849 template <typename Iterator>
13850 unsigned int
13851 get_user_index(const Iterator &i)
13852 {
13853 return i->user_index();
13854 }
13855
13856
13857
13858 template <int structdim, int dim, int spacedim>
13859 unsigned int
13860 get_user_index(
13862 {
13865 }
13866
13867
13868
13869 template <typename Iterator>
13870 void
13871 set_user_index(const Iterator &i, const unsigned int x)
13872 {
13873 i->set_user_index(x);
13874 }
13875
13876
13877
13878 template <int structdim, int dim, int spacedim>
13879 void
13880 set_user_index(
13882 const unsigned int)
13883 {
13885 }
13886} // namespace
13887
13888#ifndef DOXYGEN
13889
13890template <int dim, int spacedim>
13893 std::vector<unsigned int> &v) const
13894{
13895 v.resize(n_lines(), 0);
13896 std::vector<unsigned int>::iterator i = v.begin();
13897 line_iterator line = begin_line(), endl = end_line();
13898 for (; line != endl; ++line, ++i)
13899 *i = line->user_index();
13900}
13901
13902
13903
13904template <int dim, int spacedim>
13907 const std::vector<unsigned int> &v)
13908{
13909 Assert(v.size() == n_lines(), ExcGridReadError());
13910
13911 line_iterator line = begin_line(), endl = end_line();
13912 std::vector<unsigned int>::const_iterator i = v.begin();
13913 for (; line != endl; ++line, ++i)
13914 line->set_user_index(*i);
13915}
13916
13917
13918template <int dim, int spacedim>
13921 std::vector<unsigned int> &v) const
13922{
13923 v.resize(n_quads(), 0);
13924
13925 if (dim >= 2)
13926 {
13927 std::vector<unsigned int>::iterator i = v.begin();
13928 quad_iterator quad = begin_quad(), endq = end_quad();
13929 for (; quad != endq; ++quad, ++i)
13930 *i = get_user_index(quad);
13931 }
13932}
13933
13934
13935
13936template <int dim, int spacedim>
13939 const std::vector<unsigned int> &v)
13940{
13941 Assert(v.size() == n_quads(), ExcGridReadError());
13942
13943 if (dim >= 2)
13944 {
13945 quad_iterator quad = begin_quad(), endq = end_quad();
13946 std::vector<unsigned int>::const_iterator i = v.begin();
13947 for (; quad != endq; ++quad, ++i)
13948 set_user_index(quad, *i);
13949 }
13950}
13951
13952
13953template <int dim, int spacedim>
13956 std::vector<unsigned int> &v) const
13957{
13958 v.resize(n_hexs(), 0);
13959
13960 if (dim >= 3)
13961 {
13962 std::vector<unsigned int>::iterator i = v.begin();
13963 hex_iterator hex = begin_hex(), endh = end_hex();
13964 for (; hex != endh; ++hex, ++i)
13965 *i = get_user_index(hex);
13966 }
13967}
13968
13969
13970
13971template <int dim, int spacedim>
13974 const std::vector<unsigned int> &v)
13975{
13976 Assert(v.size() == n_hexs(), ExcGridReadError());
13977
13978 if (dim >= 3)
13979 {
13980 hex_iterator hex = begin_hex(), endh = end_hex();
13981 std::vector<unsigned int>::const_iterator i = v.begin();
13982 for (; hex != endh; ++hex, ++i)
13983 set_user_index(hex, *i);
13984 }
13985}
13986
13987#endif
13988
13989
13990//---------------- user pointers ----------------------------------------//
13991
13992
13993namespace
13994{
13995 template <typename Iterator>
13996 void *
13997 get_user_pointer(const Iterator &i)
13998 {
13999 return i->user_pointer();
14000 }
14001
14002
14003
14004 template <int structdim, int dim, int spacedim>
14005 void *
14006 get_user_pointer(
14008 {
14010 return nullptr;
14011 }
14012
14013
14014
14015 template <typename Iterator>
14016 void
14017 set_user_pointer(const Iterator &i, void *x)
14018 {
14019 i->set_user_pointer(x);
14020 }
14021
14022
14023
14024 template <int structdim, int dim, int spacedim>
14025 void
14026 set_user_pointer(
14028 void *)
14029 {
14031 }
14032} // namespace
14033
14034#ifndef DOXYGEN
14035
14036template <int dim, int spacedim>
14039 std::vector<void *> &v) const
14040{
14041 // clear vector and append all the
14042 // stuff later on
14043 v.clear();
14044
14045 std::vector<void *> tmp;
14046
14047 save_user_pointers_line(tmp);
14048 v.insert(v.end(), tmp.begin(), tmp.end());
14049
14050 if (dim >= 2)
14051 {
14052 save_user_pointers_quad(tmp);
14053 v.insert(v.end(), tmp.begin(), tmp.end());
14054 }
14055
14056 if (dim >= 3)
14057 {
14058 save_user_pointers_hex(tmp);
14059 v.insert(v.end(), tmp.begin(), tmp.end());
14060 }
14061
14062 if (dim >= 4)
14064}
14065
14066
14067
14068template <int dim, int spacedim>
14071 const std::vector<void *> &v)
14072{
14073 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
14074 std::vector<void *> tmp;
14075
14076 // first extract the pointers
14077 // belonging to lines
14078 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
14079 // and set the lines
14080 load_user_pointers_line(tmp);
14081
14082 if (dim >= 2)
14083 {
14084 tmp.clear();
14085 tmp.insert(tmp.end(),
14086 v.begin() + n_lines(),
14087 v.begin() + n_lines() + n_quads());
14088 load_user_pointers_quad(tmp);
14089 }
14090
14091 if (dim >= 3)
14092 {
14093 tmp.clear();
14094 tmp.insert(tmp.end(),
14095 v.begin() + n_lines() + n_quads(),
14096 v.begin() + n_lines() + n_quads() + n_hexs());
14097 load_user_pointers_hex(tmp);
14098 }
14099
14100 if (dim >= 4)
14102}
14103
14104
14105
14106template <int dim, int spacedim>
14109 std::vector<void *> &v) const
14110{
14111 v.resize(n_lines(), nullptr);
14112 std::vector<void *>::iterator i = v.begin();
14113 line_iterator line = begin_line(), endl = end_line();
14114 for (; line != endl; ++line, ++i)
14115 *i = line->user_pointer();
14116}
14117
14118
14119
14120template <int dim, int spacedim>
14123 const std::vector<void *> &v)
14124{
14125 Assert(v.size() == n_lines(), ExcGridReadError());
14126
14127 line_iterator line = begin_line(), endl = end_line();
14128 std::vector<void *>::const_iterator i = v.begin();
14129 for (; line != endl; ++line, ++i)
14130 line->set_user_pointer(*i);
14131}
14132
14133
14134
14135template <int dim, int spacedim>
14138 std::vector<void *> &v) const
14139{
14140 v.resize(n_quads(), nullptr);
14141
14142 if (dim >= 2)
14143 {
14144 std::vector<void *>::iterator i = v.begin();
14145 quad_iterator quad = begin_quad(), endq = end_quad();
14146 for (; quad != endq; ++quad, ++i)
14147 *i = get_user_pointer(quad);
14148 }
14149}
14150
14151
14152
14153template <int dim, int spacedim>
14156 const std::vector<void *> &v)
14157{
14158 Assert(v.size() == n_quads(), ExcGridReadError());
14159
14160 if (dim >= 2)
14161 {
14162 quad_iterator quad = begin_quad(), endq = end_quad();
14163 std::vector<void *>::const_iterator i = v.begin();
14164 for (; quad != endq; ++quad, ++i)
14165 set_user_pointer(quad, *i);
14166 }
14167}
14168
14169
14170template <int dim, int spacedim>
14173 std::vector<void *> &v) const
14174{
14175 v.resize(n_hexs(), nullptr);
14176
14177 if (dim >= 3)
14178 {
14179 std::vector<void *>::iterator i = v.begin();
14180 hex_iterator hex = begin_hex(), endh = end_hex();
14181 for (; hex != endh; ++hex, ++i)
14182 *i = get_user_pointer(hex);
14183 }
14184}
14185
14186
14187
14188template <int dim, int spacedim>
14191 const std::vector<void *> &v)
14192{
14193 Assert(v.size() == n_hexs(), ExcGridReadError());
14194
14195 if (dim >= 3)
14196 {
14197 hex_iterator hex = begin_hex(), endh = end_hex();
14198 std::vector<void *>::const_iterator i = v.begin();
14199 for (; hex != endh; ++hex, ++i)
14200 set_user_pointer(hex, *i);
14201 }
14202}
14203
14204#endif
14205
14206/*------------------------ Cell iterator functions ------------------------*/
14207
14208#ifndef DOXYGEN
14209
14210template <int dim, int spacedim>
14213 Triangulation<dim, spacedim>::begin_raw(const unsigned int level) const
14214{
14215 switch (dim)
14216 {
14217 case 1:
14218 return begin_raw_line(level);
14219 case 2:
14220 return begin_raw_quad(level);
14221 case 3:
14222 return begin_raw_hex(level);
14223 default:
14225 return raw_cell_iterator();
14226 }
14227}
14228
14229
14230
14231template <int dim, int spacedim>
14234 Triangulation<dim, spacedim>::begin(const unsigned int level) const
14235{
14236 switch (dim)
14237 {
14238 case 1:
14239 return begin_line(level);
14240 case 2:
14241 return begin_quad(level);
14242 case 3:
14243 return begin_hex(level);
14244 default:
14245 Assert(false, ExcImpossibleInDim(dim));
14246 return cell_iterator();
14247 }
14248}
14249
14250
14251
14252template <int dim, int spacedim>
14255 Triangulation<dim, spacedim>::begin_active(const unsigned int level) const
14256{
14257 switch (dim)
14258 {
14259 case 1:
14260 return begin_active_line(level);
14261 case 2:
14262 return begin_active_quad(level);
14263 case 3:
14264 return begin_active_hex(level);
14265 default:
14267 return active_cell_iterator();
14268 }
14269}
14270
14271
14272
14273template <int dim, int spacedim>
14277{
14278 const unsigned int level = levels.size() - 1;
14279 if (levels[level]->cells.n_objects() == 0)
14280 return end(level);
14281
14282 // find the last raw iterator on
14283 // this level
14284 raw_cell_iterator ri(const_cast<Triangulation<dim, spacedim> *>(this),
14285 level,
14286 levels[level]->cells.n_objects() - 1);
14287
14288 // then move to the last used one
14289 if (ri->used() == true)
14290 return ri;
14291 while ((--ri).state() == IteratorState::valid)
14292 if (ri->used() == true)
14293 return ri;
14294 return ri;
14295}
14296
14297
14298
14299template <int dim, int spacedim>
14303{
14304 // get the last used cell
14305 cell_iterator cell = last();
14306
14307 if (cell != end())
14308 {
14309 // then move to the last active one
14310 if (cell->is_active() == true)
14311 return cell;
14312 while ((--cell).state() == IteratorState::valid)
14313 if (cell->is_active() == true)
14314 return cell;
14315 }
14316 return cell;
14317}
14318
14319
14320
14321template <int dim, int spacedim>
14325 const CellId &cell_id) const
14326{
14327 Assert(
14328 this->contains_cell(cell_id),
14329 ExcMessage(
14330 "CellId is invalid for this triangulation.\n"
14331 "Either the provided CellId does not correspond to a cell in this "
14332 "triangulation object, or, in case you are using a parallel "
14333 "triangulation, may correspond to an artificial cell that is less "
14334 "refined on this processor. In the case of "
14335 "parallel::fullydistributed::Triangulation, the corresponding coarse "
14336 "cell might not be accessible by the current process."));
14337
14338 cell_iterator cell(
14339 this, 0, coarse_cell_id_to_coarse_cell_index(cell_id.get_coarse_cell_id()));
14340
14341 for (const auto &child_index : cell_id.get_child_indices())
14342 cell = cell->child(static_cast<unsigned int>(child_index));
14343
14344 return cell;
14345}
14346
14347
14348
14349template <int dim, int spacedim>
14351bool Triangulation<dim, spacedim>::contains_cell(const CellId &cell_id) const
14352{
14353 const auto coarse_cell_index =
14354 coarse_cell_id_to_coarse_cell_index(cell_id.get_coarse_cell_id());
14355
14356 if (coarse_cell_index == numbers::invalid_unsigned_int)
14357 return false;
14358
14359 cell_iterator cell(this, 0, coarse_cell_index);
14360
14361 for (const auto &child_index : cell_id.get_child_indices())
14362 {
14363 if (cell->has_children() == false)
14364 return false;
14365 cell = cell->child(static_cast<unsigned int>(child_index));
14366 }
14367
14368 return true;
14369}
14370
14371
14372
14373template <int dim, int spacedim>
14377{
14378 return cell_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14379 -1,
14380 -1);
14381}
14382
14383
14384
14385template <int dim, int spacedim>
14388 Triangulation<dim, spacedim>::end_raw(const unsigned int level) const
14389{
14390 // This function may be called on parallel triangulations on levels
14391 // that exist globally, but not on the local portion of the
14392 // triangulation. In that case, just return the end iterator.
14393 //
14394 // We need to use levels.size() instead of n_levels() because the
14395 // latter function uses the cache, but we need to be able to call
14396 // this function at a time when the cache is not currently up to
14397 // date.
14398 if (level >= levels.size())
14399 {
14400 Assert(level < n_global_levels(),
14401 ExcInvalidLevel(level, n_global_levels()));
14402 return end();
14403 }
14404
14405 // Query whether the given level is valid for the local portion of the
14406 // triangulation.
14407 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14408 if (level < levels.size() - 1)
14409 return begin_raw(level + 1);
14410 else
14411 return end();
14412}
14413
14414
14415template <int dim, int spacedim>
14418 Triangulation<dim, spacedim>::end(const unsigned int level) const
14419{
14420 // This function may be called on parallel triangulations on levels
14421 // that exist globally, but not on the local portion of the
14422 // triangulation. In that case, just return the end iterator.
14423 //
14424 // We need to use levels.size() instead of n_levels() because the
14425 // latter function uses the cache, but we need to be able to call
14426 // this function at a time when the cache is not currently up to
14427 // date.
14428 if (level >= levels.size())
14429 {
14430 Assert(level < n_global_levels(),
14431 ExcInvalidLevel(level, n_global_levels()));
14432 return end();
14433 }
14434
14435 // Query whether the given level is valid for the local portion of the
14436 // triangulation.
14437 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14438 if (level < levels.size() - 1)
14439 return begin(level + 1);
14440 else
14441 return end();
14442}
14443
14444
14445template <int dim, int spacedim>
14448 Triangulation<dim, spacedim>::end_active(const unsigned int level) const
14449{
14450 // This function may be called on parallel triangulations on levels
14451 // that exist globally, but not on the local portion of the
14452 // triangulation. In that case, just return the end iterator.
14453 //
14454 // We need to use levels.size() instead of n_levels() because the
14455 // latter function uses the cache, but we need to be able to call
14456 // this function at a time when the cache is not currently up to
14457 // date.
14458 if (level >= levels.size())
14459 {
14460 Assert(level < n_global_levels(),
14461 ExcInvalidLevel(level, n_global_levels()));
14462 return end();
14463 }
14464
14465 // Query whether the given level is valid for the local portion of the
14466 // triangulation.
14467 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14468 return (level >= levels.size() - 1 ? active_cell_iterator(end()) :
14469 begin_active(level + 1));
14470}
14471
14472
14473
14474template <int dim, int spacedim>
14478 const
14479{
14481 begin(), end());
14482}
14483
14484
14485template <int dim, int spacedim>
14488 active_cell_iterator> Triangulation<dim, spacedim>::
14490{
14491 return IteratorRange<
14493 end());
14494}
14495
14496
14497
14498template <int dim, int spacedim>
14501 cell_iterator> Triangulation<dim, spacedim>::
14502 cell_iterators_on_level(const unsigned int level) const
14503{
14505 begin(level), end(level));
14506}
14507
14508
14509
14510template <int dim, int spacedim>
14513 active_cell_iterator> Triangulation<dim, spacedim>::
14514 active_cell_iterators_on_level(const unsigned int level) const
14515{
14516 return IteratorRange<
14518 begin_active(level), end_active(level));
14519}
14520#endif
14521
14522/*------------------------ Face iterator functions ------------------------*/
14523
14524#ifndef DOXYGEN
14525
14526template <int dim, int spacedim>
14530{
14531 switch (dim)
14532 {
14533 case 1:
14534 Assert(false, ExcImpossibleInDim(1));
14535 return raw_face_iterator();
14536 case 2:
14537 return begin_line();
14538 case 3:
14539 return begin_quad();
14540 default:
14542 return face_iterator();
14543 }
14544}
14545
14546
14547
14548template <int dim, int spacedim>
14552{
14553 switch (dim)
14554 {
14555 case 1:
14556 Assert(false, ExcImpossibleInDim(1));
14557 return raw_face_iterator();
14558 case 2:
14559 return begin_active_line();
14560 case 3:
14561 return begin_active_quad();
14562 default:
14564 return active_face_iterator();
14565 }
14566}
14567
14568
14569
14570template <int dim, int spacedim>
14574{
14575 switch (dim)
14576 {
14577 case 1:
14578 Assert(false, ExcImpossibleInDim(1));
14579 return raw_face_iterator();
14580 case 2:
14581 return end_line();
14582 case 3:
14583 return end_quad();
14584 default:
14586 return raw_face_iterator();
14587 }
14588}
14589
14590
14591
14592template <int dim, int spacedim>
14595 active_face_iterator> Triangulation<dim, spacedim>::
14597{
14598 return IteratorRange<
14600 begin_active_face(), end_face());
14601}
14602
14603/*------------------------ Vertex iterator functions ------------------------*/
14604
14605
14606template <int dim, int spacedim>
14610{
14611 vertex_iterator i =
14612 raw_vertex_iterator(const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
14613 if (i.state() != IteratorState::valid)
14614 return i;
14615 // This loop will end because every triangulation has used vertices.
14616 while (i->used() == false)
14617 if ((++i).state() != IteratorState::valid)
14618 return i;
14619 return i;
14620}
14621
14622
14623
14624template <int dim, int spacedim>
14628{
14629 // every vertex is active
14630 return begin_vertex();
14631}
14632
14633
14634
14635template <int dim, int spacedim>
14639{
14640 return raw_vertex_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14641 -1,
14643}
14644
14645#endif
14646
14647
14648/*------------------------ Line iterator functions ------------------------*/
14649
14650#ifndef DOXYGEN
14651
14652template <int dim, int spacedim>
14655 Triangulation<dim, spacedim>::begin_raw_line(const unsigned int level) const
14656{
14657 // This function may be called on parallel triangulations on levels
14658 // that exist globally, but not on the local portion of the
14659 // triangulation. In that case, just return the end iterator.
14660 //
14661 // We need to use levels.size() instead of n_levels() because the
14662 // latter function uses the cache, but we need to be able to call
14663 // this function at a time when the cache is not currently up to
14664 // date.
14665 if (level >= levels.size())
14666 {
14667 Assert(level < n_global_levels(),
14668 ExcInvalidLevel(level, n_global_levels()));
14669 return end_line();
14670 }
14671
14672 switch (dim)
14673 {
14674 case 1:
14675 // Query whether the given level is valid for the local portion of the
14676 // triangulation.
14677 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14678
14679 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
14680 return end_line();
14681
14682 return raw_line_iterator(
14683 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
14684
14685 default:
14686 Assert(level == 0, ExcFacesHaveNoLevel());
14687 return raw_line_iterator(
14688 const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
14689 }
14690}
14691
14692
14693template <int dim, int spacedim>
14696 Triangulation<dim, spacedim>::begin_line(const unsigned int level) const
14697{
14698 // level is checked in begin_raw
14699 raw_line_iterator ri = begin_raw_line(level);
14700 if (ri.state() != IteratorState::valid)
14701 return ri;
14702 while (ri->used() == false)
14703 if ((++ri).state() != IteratorState::valid)
14704 return ri;
14705 return ri;
14706}
14707
14708
14709
14710template <int dim, int spacedim>
14714 const unsigned int level) const
14715{
14716 // level is checked in begin_raw
14717 line_iterator i = begin_line(level);
14718 if (i.state() != IteratorState::valid)
14719 return i;
14720 while (i->has_children())
14721 if ((++i).state() != IteratorState::valid)
14722 return i;
14723 return i;
14724}
14725
14726
14727
14728template <int dim, int spacedim>
14732{
14733 return raw_line_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14734 -1,
14735 -1);
14736}
14737
14738#endif
14739
14740/*------------------------ Quad iterator functions ------------------------*/
14741
14742#ifndef DOXYGEN
14743
14744template <int dim, int spacedim>
14747 Triangulation<dim, spacedim>::begin_raw_quad(const unsigned int level) const
14748{
14749 // This function may be called on parallel triangulations on levels
14750 // that exist globally, but not on the local portion of the
14751 // triangulation. In that case, just return the end iterator.
14752 //
14753 // We need to use levels.size() instead of n_levels() because the
14754 // latter function uses the cache, but we need to be able to call
14755 // this function at a time when the cache is not currently up to
14756 // date.
14757 if (level >= levels.size())
14758 {
14759 Assert(level < n_global_levels(),
14760 ExcInvalidLevel(level, n_global_levels()));
14761 return end_quad();
14762 }
14763
14764 switch (dim)
14765 {
14766 case 1:
14767 Assert(false, ExcImpossibleInDim(1));
14768 return raw_hex_iterator();
14769 case 2:
14770 {
14771 // Query whether the given level is valid for the local portion of the
14772 // triangulation.
14773 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14774
14775 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
14776 return end_quad();
14777
14778 return raw_quad_iterator(
14779 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
14780 }
14781
14782 case 3:
14783 {
14784 Assert(level == 0, ExcFacesHaveNoLevel());
14785
14786 return raw_quad_iterator(
14787 const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
14788 }
14789
14790
14791 default:
14793 return raw_hex_iterator();
14794 }
14795}
14796
14797
14798
14799template <int dim, int spacedim>
14802 Triangulation<dim, spacedim>::begin_quad(const unsigned int level) const
14803{
14804 // level is checked in begin_raw
14805 raw_quad_iterator ri = begin_raw_quad(level);
14806 if (ri.state() != IteratorState::valid)
14807 return ri;
14808 while (ri->used() == false)
14809 if ((++ri).state() != IteratorState::valid)
14810 return ri;
14811 return ri;
14812}
14813
14814
14815
14816template <int dim, int spacedim>
14820 const unsigned int level) const
14821{
14822 // level is checked in begin_raw
14823 quad_iterator i = begin_quad(level);
14824 if (i.state() != IteratorState::valid)
14825 return i;
14826 while (i->has_children())
14827 if ((++i).state() != IteratorState::valid)
14828 return i;
14829 return i;
14830}
14831
14832
14833
14834template <int dim, int spacedim>
14838{
14839 return raw_quad_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14840 -1,
14841 -1);
14842}
14843
14844#endif
14845
14846/*------------------------ Hex iterator functions ------------------------*/
14847
14848#ifndef DOXYGEN
14849
14850template <int dim, int spacedim>
14853 Triangulation<dim, spacedim>::begin_raw_hex(const unsigned int level) const
14854{
14855 // This function may be called on parallel triangulations on levels
14856 // that exist globally, but not on the local portion of the
14857 // triangulation. In that case, just return the end iterator.
14858 //
14859 // We need to use levels.size() instead of n_levels() because the
14860 // latter function uses the cache, but we need to be able to call
14861 // this function at a time when the cache is not currently up to
14862 // date.
14863 if (level >= levels.size())
14864 {
14865 Assert(level < n_global_levels(),
14866 ExcInvalidLevel(level, n_global_levels()));
14867 return end_hex();
14868 }
14869
14870 switch (dim)
14871 {
14872 case 1:
14873 case 2:
14874 Assert(false, ExcImpossibleInDim(1));
14875 return raw_hex_iterator();
14876 case 3:
14877 {
14878 // Query whether the given level is valid for the local portion of the
14879 // triangulation.
14880 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14881
14882 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
14883 return end_hex();
14884
14885 return raw_hex_iterator(
14886 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
14887 }
14888
14889 default:
14891 return raw_hex_iterator();
14892 }
14893}
14894
14895
14896
14897template <int dim, int spacedim>
14900 Triangulation<dim, spacedim>::begin_hex(const unsigned int level) const
14901{
14902 // level is checked in begin_raw
14903 raw_hex_iterator ri = begin_raw_hex(level);
14904 if (ri.state() != IteratorState::valid)
14905 return ri;
14906 while (ri->used() == false)
14907 if ((++ri).state() != IteratorState::valid)
14908 return ri;
14909 return ri;
14910}
14911
14912
14913
14914template <int dim, int spacedim>
14918{
14919 // level is checked in begin_raw
14920 hex_iterator i = begin_hex(level);
14921 if (i.state() != IteratorState::valid)
14922 return i;
14923 while (i->has_children())
14924 if ((++i).state() != IteratorState::valid)
14925 return i;
14926 return i;
14927}
14928
14929
14930
14931template <int dim, int spacedim>
14935{
14936 return raw_hex_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14937 -1,
14938 -1);
14939}
14940
14941#endif
14942
14943// -------------------------------- number of cells etc ---------------
14944
14945
14946namespace internal
14947{
14948 namespace TriangulationImplementation
14949 {
14950 inline unsigned int
14952 {
14953 return c.n_lines;
14954 }
14955
14956
14957 inline unsigned int
14960 {
14961 return c.n_active_lines;
14962 }
14963
14964
14965 inline unsigned int
14967 {
14968 return c.n_quads;
14969 }
14970
14971
14972 inline unsigned int
14975 {
14976 return c.n_active_quads;
14977 }
14978
14979
14980 inline unsigned int
14982 {
14983 return c.n_hexes;
14984 }
14985
14986
14987 inline unsigned int
14990 {
14991 return c.n_active_hexes;
14992 }
14993 } // namespace TriangulationImplementation
14994} // namespace internal
14995
14996#ifndef DOXYGEN
14997
14998template <int dim, int spacedim>
15000unsigned int Triangulation<dim, spacedim>::n_cells() const
15001{
15003}
15004
15005
15006template <int dim, int spacedim>
15009{
15011}
15012
15013template <int dim, int spacedim>
15017{
15018 return n_active_cells();
15019}
15020
15021template <int dim, int spacedim>
15025{
15026 return n_cells(0);
15027}
15028
15029template <int dim, int spacedim>
15031unsigned int Triangulation<dim, spacedim>::n_faces() const
15032{
15033 switch (dim)
15034 {
15035 case 1:
15036 return n_used_vertices();
15037 case 2:
15038 return n_lines();
15039 case 3:
15040 return n_quads();
15041 default:
15043 }
15044 return 0;
15045}
15046
15047
15048template <int dim, int spacedim>
15051{
15052 switch (dim)
15053 {
15054 case 1:
15055 return n_vertices();
15056 case 2:
15057 return n_raw_lines();
15058 case 3:
15059 return n_raw_quads();
15060 default:
15062 }
15063 return 0;
15064}
15065
15066
15067template <int dim, int spacedim>
15070{
15071 switch (dim)
15072 {
15073 case 1:
15074 return n_used_vertices();
15075 case 2:
15076 return n_active_lines();
15077 case 3:
15078 return n_active_quads();
15079 default:
15081 }
15082 return 0;
15083}
15084
15085
15086template <int dim, int spacedim>
15089 const unsigned int level) const
15090{
15091 switch (dim)
15092 {
15093 case 1:
15094 return n_raw_lines(level);
15095 case 2:
15096 return n_raw_quads(level);
15097 case 3:
15098 return n_raw_hexs(level);
15099 default:
15101 }
15102 return 0;
15103}
15104
15105
15106
15107template <int dim, int spacedim>
15110 const unsigned int level) const
15111{
15112 switch (dim)
15113 {
15114 case 1:
15115 return n_lines(level);
15116 case 2:
15117 return n_quads(level);
15118 case 3:
15119 return n_hexs(level);
15120 default:
15122 }
15123 return 0;
15124}
15125
15126
15127
15128template <int dim, int spacedim>
15131 const unsigned int level) const
15132{
15133 switch (dim)
15134 {
15135 case 1:
15136 return n_active_lines(level);
15137 case 2:
15138 return n_active_quads(level);
15139 case 3:
15140 return n_active_hexs(level);
15141 default:
15143 }
15144 return 0;
15145}
15146
15147
15148template <int dim, int spacedim>
15151{
15152 if (anisotropic_refinement == false)
15153 {
15154 for (unsigned int lvl = 0; lvl < n_global_levels() - 1; ++lvl)
15155 if (n_active_cells(lvl) != 0)
15156 return true;
15157 }
15158 else
15159 {
15160 for (const auto &cell : active_cell_iterators())
15161 for (const auto &i : cell->face_indices())
15162 if (cell->face(i)->has_children())
15163 return true;
15164 }
15165 return false;
15166}
15167
15168
15169template <int dim, int spacedim>
15171unsigned int Triangulation<dim, spacedim>::n_lines() const
15172{
15173 return number_cache.n_lines;
15174}
15175
15176
15177
15178template <int dim, int spacedim>
15181 const unsigned int level) const
15182{
15183 if (dim == 1)
15184 {
15185 AssertIndexRange(level, n_levels());
15186 return levels[level]->cells.n_objects();
15187 }
15188
15189 Assert(false, ExcFacesHaveNoLevel());
15190 return 0;
15191}
15192
15193
15194template <int dim, int spacedim>
15197{
15198 if (dim == 1)
15199 {
15201 return 0;
15202 }
15203
15204 return faces->lines.n_objects();
15205}
15206
15207
15208template <int dim, int spacedim>
15211 const unsigned int level) const
15212{
15213 AssertIndexRange(level, number_cache.n_lines_level.size());
15214 Assert(dim == 1, ExcFacesHaveNoLevel());
15215 return number_cache.n_lines_level[level];
15216}
15217
15218
15219template <int dim, int spacedim>
15222{
15223 return number_cache.n_active_lines;
15224}
15225
15226
15227template <int dim, int spacedim>
15230 const unsigned int level) const
15231{
15232 AssertIndexRange(level, number_cache.n_lines_level.size());
15233 Assert(dim == 1, ExcFacesHaveNoLevel());
15234
15235 return number_cache.n_active_lines_level[level];
15236}
15237#endif
15238
15239template <>
15240unsigned int
15242{
15243 return 0;
15244}
15245
15246
15247template <>
15248unsigned int
15249Triangulation<1, 1>::n_quads(const unsigned int) const
15250{
15251 return 0;
15252}
15253
15254
15255template <>
15256unsigned int
15257Triangulation<1, 1>::n_raw_quads(const unsigned int) const
15258{
15259 return 0;
15260}
15261
15262
15263template <>
15264unsigned int
15265Triangulation<1, 1>::n_raw_hexs(const unsigned int) const
15266{
15267 return 0;
15268}
15269
15270
15271template <>
15272unsigned int
15274{
15275 return 0;
15276}
15277
15278
15279template <>
15280unsigned int
15282{
15283 return 0;
15284}
15285
15286
15287
15288template <>
15289unsigned int
15291{
15292 return 0;
15293}
15294
15295
15296template <>
15297unsigned int
15298Triangulation<1, 2>::n_quads(const unsigned int) const
15299{
15300 return 0;
15301}
15302
15303
15304template <>
15305unsigned int
15306Triangulation<1, 2>::n_raw_quads(const unsigned int) const
15307{
15308 return 0;
15309}
15310
15311
15312template <>
15313unsigned int
15314Triangulation<1, 2>::n_raw_hexs(const unsigned int) const
15315{
15316 return 0;
15317}
15318
15319
15320template <>
15321unsigned int
15323{
15324 return 0;
15325}
15326
15327
15328template <>
15329unsigned int
15331{
15332 return 0;
15333}
15334
15335
15336template <>
15337unsigned int
15339{
15340 return 0;
15341}
15342
15343
15344template <>
15345unsigned int
15346Triangulation<1, 3>::n_quads(const unsigned int) const
15347{
15348 return 0;
15349}
15350
15351
15352template <>
15353unsigned int
15354Triangulation<1, 3>::n_raw_quads(const unsigned int) const
15355{
15356 return 0;
15357}
15358
15359
15360template <>
15361unsigned int
15362Triangulation<1, 3>::n_raw_hexs(const unsigned int) const
15363{
15364 return 0;
15365}
15366
15367
15368template <>
15369unsigned int
15371{
15372 return 0;
15373}
15374
15375
15376template <>
15377unsigned int
15379{
15380 return 0;
15381}
15382
15383#ifndef DOXYGEN
15384
15385template <int dim, int spacedim>
15387unsigned int Triangulation<dim, spacedim>::n_quads() const
15388{
15389 return number_cache.n_quads;
15390}
15391
15392
15393template <int dim, int spacedim>
15396 const unsigned int level) const
15397{
15398 Assert(dim == 2, ExcFacesHaveNoLevel());
15399 AssertIndexRange(level, number_cache.n_quads_level.size());
15400 return number_cache.n_quads_level[level];
15401}
15402
15403#endif
15404
15405template <>
15406unsigned int
15408{
15409 AssertIndexRange(level, n_levels());
15410 return levels[level]->cells.n_objects();
15411}
15412
15413
15414
15415template <>
15416unsigned int
15418{
15419 AssertIndexRange(level, n_levels());
15420 return levels[level]->cells.n_objects();
15421}
15422
15423
15424template <>
15425unsigned int
15426Triangulation<3, 3>::n_raw_quads(const unsigned int) const
15427{
15428 Assert(false, ExcFacesHaveNoLevel());
15429 return 0;
15430}
15431
15432#ifndef DOXYGEN
15433
15434template <int dim, int spacedim>
15437{
15439 return 0;
15440}
15441
15442#endif
15443
15444template <>
15445unsigned int
15447{
15448 return faces->quads.n_objects();
15449}
15450
15451#ifndef DOXYGEN
15452
15453template <int dim, int spacedim>
15456{
15457 return number_cache.n_active_quads;
15458}
15459
15460
15461template <int dim, int spacedim>
15464 const unsigned int level) const
15465{
15466 AssertIndexRange(level, number_cache.n_quads_level.size());
15467 Assert(dim == 2, ExcFacesHaveNoLevel());
15468
15469 return number_cache.n_active_quads_level[level];
15470}
15471
15472
15473template <int dim, int spacedim>
15475unsigned int Triangulation<dim, spacedim>::n_hexs() const
15476{
15477 return 0;
15478}
15479
15480
15481
15482template <int dim, int spacedim>
15484unsigned int Triangulation<dim, spacedim>::n_hexs(const unsigned int) const
15485{
15486 return 0;
15487}
15488
15489
15490
15491template <int dim, int spacedim>
15493unsigned int Triangulation<dim, spacedim>::n_raw_hexs(const unsigned int) const
15494{
15495 return 0;
15496}
15497
15498
15499template <int dim, int spacedim>
15502{
15503 return 0;
15504}
15505
15506
15507
15508template <int dim, int spacedim>
15511 const unsigned int) const
15512{
15513 return 0;
15514}
15515
15516#endif
15517
15518template <>
15519unsigned int
15521{
15522 return number_cache.n_hexes;
15523}
15524
15525
15526
15527template <>
15528unsigned int
15529Triangulation<3, 3>::n_hexs(const unsigned int level) const
15530{
15531 AssertIndexRange(level, number_cache.n_hexes_level.size());
15532
15533 return number_cache.n_hexes_level[level];
15534}
15535
15536
15537
15538template <>
15539unsigned int
15541{
15542 AssertIndexRange(level, n_levels());
15543 return levels[level]->cells.n_objects();
15544}
15545
15546
15547template <>
15548unsigned int
15550{
15551 return number_cache.n_active_hexes;
15552}
15553
15554
15555
15556template <>
15557unsigned int
15559{
15560 AssertIndexRange(level, number_cache.n_hexes_level.size());
15561
15562 return number_cache.n_active_hexes_level[level];
15563}
15564
15565#ifndef DOXYGEN
15566
15567template <int dim, int spacedim>
15570{
15571 return std::count(vertices_used.begin(), vertices_used.end(), true);
15572}
15573
15574
15575
15576template <int dim, int spacedim>
15578const std::vector<bool> &Triangulation<dim, spacedim>::get_used_vertices() const
15579{
15580 return vertices_used;
15581}
15582
15583#endif
15584
15585template <>
15586unsigned int
15588{
15589 return 2;
15590}
15591
15592
15593
15594template <>
15595unsigned int
15597{
15598 return 2;
15599}
15600
15601
15602template <>
15603unsigned int
15605{
15606 return 2;
15607}
15608
15609#ifndef DOXYGEN
15610
15611template <int dim, int spacedim>
15614{
15615 cell_iterator cell = begin(0),
15616 endc = (n_levels() > 1 ? begin(1) : cell_iterator(end()));
15617 // store the largest index of the
15618 // vertices used on level 0
15619 unsigned int max_vertex_index = 0;
15620 for (; cell != endc; ++cell)
15621 for (const unsigned int vertex : GeometryInfo<dim>::vertex_indices())
15622 if (cell->vertex_index(vertex) > max_vertex_index)
15623 max_vertex_index = cell->vertex_index(vertex);
15624
15625 // store the number of times a cell
15626 // touches a vertex. An unsigned
15627 // int should suffice, even for
15628 // larger dimensions
15629 std::vector<unsigned short int> usage_count(max_vertex_index + 1, 0);
15630 // touch a vertex's usage count
15631 // every time we find an adjacent
15632 // element
15633 for (cell = begin(); cell != endc; ++cell)
15634 for (const unsigned int vertex : GeometryInfo<dim>::vertex_indices())
15635 ++usage_count[cell->vertex_index(vertex)];
15636
15638 static_cast<unsigned int>(
15639 *std::max_element(usage_count.begin(), usage_count.end())));
15640}
15641
15642
15643
15644template <int dim, int spacedim>
15648{
15650}
15651
15652
15653
15654template <int dim, int spacedim>
15657{
15658 return *this;
15659}
15660
15661
15662
15663template <int dim, int spacedim>
15667{
15668 return *this;
15669}
15670
15671
15672
15673template <int dim, int spacedim>
15677 &periodicity_vector)
15678{
15679 periodic_face_pairs_level_0.insert(periodic_face_pairs_level_0.end(),
15680 periodicity_vector.begin(),
15681 periodicity_vector.end());
15682
15683 // Now initialize periodic_face_map
15684 update_periodic_face_map();
15685}
15686
15687
15688
15689template <int dim, int spacedim>
15691const typename std::map<
15692 std::pair<typename Triangulation<dim, spacedim>::cell_iterator, unsigned int>,
15693 std::pair<std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
15694 unsigned int>,
15695 unsigned char>>
15697{
15698 return periodic_face_map;
15699}
15700
15701
15702
15703template <int dim, int spacedim>
15706{
15707 // Call our version of prepare_coarsening_and_refinement() even if a derived
15708 // class like parallel::distributed::Triangulation overrides it. Their
15709 // function will be called in their execute_coarsening_and_refinement()
15710 // function. Even in a distributed computation our job here is to reconstruct
15711 // the local part of the mesh and as such checking our flags is enough.
15713
15714 // verify a case with which we have had
15715 // some difficulty in the past (see the
15716 // deal.II/coarsening_* tests)
15717 if (smooth_grid & limit_level_difference_at_vertices)
15718 Assert(satisfies_level1_at_vertex_rule(*this) == true, ExcInternalError());
15719
15720 // Inform all listeners about beginning of refinement.
15721 signals.pre_refinement();
15722
15723 execute_coarsening();
15724
15725 const DistortedCellList cells_with_distorted_children = execute_refinement();
15726
15727 reset_cell_vertex_indices_cache();
15728
15729 // verify a case with which we have had
15730 // some difficulty in the past (see the
15731 // deal.II/coarsening_* tests)
15732 if (smooth_grid & limit_level_difference_at_vertices)
15733 Assert(satisfies_level1_at_vertex_rule(*this) == true, ExcInternalError());
15734
15735 // finally build up neighbor connectivity information, and set
15736 // active cell indices
15737 this->policy->update_neighbors(*this);
15738 reset_active_cell_indices();
15739
15740 reset_global_cell_indices(); // TODO: better place?
15741
15742 // Inform all listeners about end of refinement.
15743 signals.post_refinement();
15744
15745 AssertThrow(cells_with_distorted_children.distorted_cells.empty(),
15746 cells_with_distorted_children);
15747
15748 update_periodic_face_map();
15749
15750# ifdef DEBUG
15751
15752 // In debug mode, we want to check for some consistency of the
15753 // result of this function. Because there are multiple exit
15754 // paths, put this check into a ScopeExit object that is
15755 // executed on each of the exit paths.
15756 //
15757 // Specifically, check on exit of this function that if a quad
15758 // cell has been refined, all of its children have neighbors
15759 // in all directions in which the parent cell has neighbors as
15760 // well. The children's neighbors are either the parent
15761 // neighbor or the parent neighbor's children, or simply one of
15762 // the other children of the current cell. This check is
15763 // useful because if one creates a triangulation with an
15764 // inconsistently ordered set of cells (e.g., because one has
15765 // forgotten to call GridTools::consistently_order_cells()),
15766 // then this relatively simple invariant is violated -- so the
15767 // check here can be used to catch that case, at least
15768 // sometimes.
15769 //
15770 // In 1d, this situation cannot happen. In 3d, we have explicit
15771 // orientation flags to ensure that it is not necessary to re-orient
15772 // cells at the beginning. But in both cases, the invariant should
15773 // still hold as long as the cell is a hypercube.
15774 for (const auto &cell : cell_iterators())
15775 {
15776 if (cell->has_children() && cell->reference_cell().is_hyper_cube())
15777 for (const unsigned int f : cell->face_indices())
15778 if (cell->at_boundary(f) == false)
15779 {
15780 for (const auto &child : cell->child_iterators())
15781 {
15782 Assert(
15783 child->at_boundary(f) == false,
15784 ExcMessage(
15785 "We ended up with a triangulation whose child cells "
15786 "are not connected to their neighbors as expected. "
15787 "When you created the triangulation, did you forget "
15788 "to call GridTools::consistently_order_cells() "
15789 "before calling Triangulation::create_triangulation()?"));
15790 }
15791 }
15792 }
15793# endif
15794}
15795
15796
15797
15798template <int dim, int spacedim>
15801{
15802 unsigned int active_cell_index = 0;
15803 for (raw_cell_iterator cell = begin_raw(); cell != end(); ++cell)
15804 if ((cell->used() == false) || cell->has_children())
15805 cell->set_active_cell_index(numbers::invalid_unsigned_int);
15806 else
15807 {
15808 cell->set_active_cell_index(active_cell_index);
15809 ++active_cell_index;
15810 }
15811
15812 Assert(active_cell_index == n_active_cells(), ExcInternalError());
15813}
15814
15815
15816
15817template <int dim, int spacedim>
15820{
15821 {
15823 for (const auto &cell : active_cell_iterators())
15824 cell->set_global_active_cell_index(cell_index++);
15825 }
15826
15827 for (unsigned int l = 0; l < levels.size(); ++l)
15828 {
15830 for (const auto &cell : cell_iterators_on_level(l))
15831 cell->set_global_level_cell_index(cell_index++);
15832 }
15833}
15834
15835
15836
15837template <int dim, int spacedim>
15840{
15841 for (unsigned int l = 0; l < levels.size(); ++l)
15842 {
15843 constexpr unsigned int max_vertices_per_cell = 1 << dim;
15844 std::vector<unsigned int> &cache = levels[l]->cell_vertex_indices_cache;
15845 cache.clear();
15846 cache.resize(levels[l]->refine_flags.size() * max_vertices_per_cell,
15848 for (const auto &cell : cell_iterators_on_level(l))
15849 {
15850 const unsigned int my_index = cell->index() * max_vertices_per_cell;
15851
15852 // to reduce the cost of this function when passing down into quads,
15853 // then lines, then vertices, we use a more low-level access method
15854 // for hexahedral cells, where we can streamline most of the logic
15855 const ReferenceCell ref_cell = cell->reference_cell();
15856 if (ref_cell == ReferenceCells::Hexahedron)
15857 for (unsigned int face = 4; face < 6; ++face)
15858 {
15859 const auto face_iter = cell->face(face);
15860 const std::array<bool, 2> line_orientations{
15861 {face_iter->line_orientation(0),
15862 face_iter->line_orientation(1)}};
15863 std::array<unsigned int, 4> raw_vertex_indices{
15864 {face_iter->line(0)->vertex_index(1 - line_orientations[0]),
15865 face_iter->line(1)->vertex_index(1 - line_orientations[1]),
15866 face_iter->line(0)->vertex_index(line_orientations[0]),
15867 face_iter->line(1)->vertex_index(line_orientations[1])}};
15868
15869 const unsigned char combined_orientation =
15870 levels[l]->face_orientations.get_combined_orientation(
15871 cell->index() * GeometryInfo<3>::faces_per_cell + face);
15872 std::array<unsigned int, 4> vertex_order{
15873 {ref_cell.standard_to_real_face_vertex(0,
15874 face,
15875 combined_orientation),
15877 face,
15878 combined_orientation),
15880 face,
15881 combined_orientation),
15883 3, face, combined_orientation)}};
15884
15885 const unsigned int index = my_index + 4 * (face - 4);
15886 for (unsigned int i = 0; i < 4; ++i)
15887 cache[index + i] = raw_vertex_indices[vertex_order[i]];
15888 }
15889 else if (ref_cell == ReferenceCells::Quadrilateral)
15890 {
15891 const std::array<bool, 2> line_orientations{
15892 {cell->line_orientation(0), cell->line_orientation(1)}};
15893 std::array<unsigned int, 4> raw_vertex_indices{
15894 {cell->line(0)->vertex_index(1 - line_orientations[0]),
15895 cell->line(1)->vertex_index(1 - line_orientations[1]),
15896 cell->line(0)->vertex_index(line_orientations[0]),
15897 cell->line(1)->vertex_index(line_orientations[1])}};
15898 for (unsigned int i = 0; i < 4; ++i)
15899 cache[my_index + i] = raw_vertex_indices[i];
15900 }
15901 else
15902 for (const unsigned int i : cell->vertex_indices())
15903 cache[my_index + i] = internal::TriaAccessorImplementation::
15904 Implementation::vertex_index(*cell, i);
15905 }
15906 }
15907}
15908
15909
15910
15911template <int dim, int spacedim>
15914{
15915 // first empty the currently stored objects
15916 periodic_face_map.clear();
15917
15918 typename std::vector<
15920 for (it = periodic_face_pairs_level_0.begin();
15921 it != periodic_face_pairs_level_0.end();
15922 ++it)
15923 {
15924 update_periodic_face_map_recursively<dim, spacedim>(it->cell[0],
15925 it->cell[1],
15926 it->face_idx[0],
15927 it->face_idx[1],
15928 it->orientation,
15929 periodic_face_map);
15930
15931 const auto face_reference_cell =
15932 it->cell[0]->reference_cell().face_reference_cell(it->face_idx[0]);
15933 // for the other way, we need to invert the orientation
15934 update_periodic_face_map_recursively<dim, spacedim>(
15935 it->cell[1],
15936 it->cell[0],
15937 it->face_idx[1],
15938 it->face_idx[0],
15939 face_reference_cell.get_inverse_combined_orientation(it->orientation),
15940 periodic_face_map);
15941 }
15942
15943 // check consistency
15944 typename std::map<std::pair<cell_iterator, unsigned int>,
15945 std::pair<std::pair<cell_iterator, unsigned int>,
15946 unsigned char>>::const_iterator it_test;
15947 for (it_test = periodic_face_map.begin(); it_test != periodic_face_map.end();
15948 ++it_test)
15949 {
15951 it_test->first.first;
15953 it_test->second.first.first;
15954 if (cell_1->level() == cell_2->level())
15955 {
15956 // if both cells have the same neighbor, then the same pair
15957 // order swapped has to be in the map
15958 Assert(periodic_face_map[it_test->second.first].first ==
15959 it_test->first,
15961 }
15962 }
15963}
15964
15965
15966
15967template <int dim, int spacedim>
15970{
15971 std::set<ReferenceCell> reference_cells_set;
15972 for (auto cell : active_cell_iterators())
15973 if (cell->is_locally_owned())
15974 reference_cells_set.insert(cell->reference_cell());
15975
15976 this->reference_cells =
15977 std::vector<ReferenceCell>(reference_cells_set.begin(),
15978 reference_cells_set.end());
15979}
15980
15981
15982
15983template <int dim, int spacedim>
15985const std::vector<ReferenceCell>
15987{
15988 return this->reference_cells;
15989}
15990
15991
15992
15993template <int dim, int spacedim>
15996{
15997 Assert(this->reference_cells.size() > 0,
15998 ExcMessage("You can't ask about the kinds of reference "
15999 "cells used by this triangulation if the "
16000 "triangulation doesn't yet have any cells in it."));
16001 return (this->reference_cells.size() == 1 &&
16002 this->reference_cells[0].is_hyper_cube());
16003}
16004
16005
16006
16007template <int dim, int spacedim>
16010{
16011 Assert(this->reference_cells.size() > 0,
16012 ExcMessage("You can't ask about the kinds of reference "
16013 "cells used by this triangulation if the "
16014 "triangulation doesn't yet have any cells in it."));
16015 return (this->reference_cells.size() == 1 &&
16016 this->reference_cells[0].is_simplex());
16017}
16018
16019
16020
16021template <int dim, int spacedim>
16024{
16025 Assert(this->reference_cells.size() > 0,
16026 ExcMessage("You can't ask about the kinds of reference "
16027 "cells used by this triangulation if the "
16028 "triangulation doesn't yet have any cells in it."));
16029 return reference_cells.size() > 1 ||
16030 ((reference_cells[0].is_hyper_cube() == false) &&
16031 (reference_cells[0].is_simplex() == false));
16032}
16033
16034
16035
16036template <int dim, int spacedim>
16039 const std::function<std::vector<char>(const cell_iterator &,
16040 const ::CellStatus)>
16041 &pack_callback,
16042 const bool returns_variable_size_data)
16043{
16044 unsigned int handle = numbers::invalid_unsigned_int;
16045
16046 // Add new callback function to the corresponding register.
16047 // Encode handles according to returns_variable_size_data.
16048 if (returns_variable_size_data)
16049 {
16050 handle = 2 * this->cell_attached_data.pack_callbacks_variable.size();
16051 this->cell_attached_data.pack_callbacks_variable.push_back(pack_callback);
16052 }
16053 else
16054 {
16055 handle = 2 * this->cell_attached_data.pack_callbacks_fixed.size() + 1;
16056 this->cell_attached_data.pack_callbacks_fixed.push_back(pack_callback);
16057 }
16058
16059 // Increase overall counter.
16060 ++this->cell_attached_data.n_attached_data_sets;
16061
16062 return handle;
16063}
16064
16065
16066
16067template <int dim, int spacedim>
16070 const unsigned int handle,
16071 const std::function<
16072 void(const cell_iterator &,
16073 const ::CellStatus,
16074 const boost::iterator_range<std::vector<char>::const_iterator> &)>
16075 &unpack_callback)
16076{
16077 // perform unpacking
16078 this->data_serializer.unpack_data(this->local_cell_relations,
16079 handle,
16080 unpack_callback);
16081
16082 // decrease counters
16083 --this->cell_attached_data.n_attached_data_sets;
16084 if (this->cell_attached_data.n_attached_deserialize > 0)
16085 --this->cell_attached_data.n_attached_deserialize;
16086
16087 // important: only remove data if we are not in the deserialization
16088 // process. There, each SolutionTransfer registers and unpacks before
16089 // the next one does this, so n_attached_data_sets is only 1 here. This
16090 // would destroy the saved data before the second SolutionTransfer can
16091 // get it. This created a bug that is documented in
16092 // tests/mpi/p4est_save_03 with more than one SolutionTransfer.
16093
16094 if (this->cell_attached_data.n_attached_data_sets == 0 &&
16095 this->cell_attached_data.n_attached_deserialize == 0)
16096 {
16097 // everybody got their data, time for cleanup!
16098 this->cell_attached_data.pack_callbacks_fixed.clear();
16099 this->cell_attached_data.pack_callbacks_variable.clear();
16100 this->data_serializer.clear();
16101
16102 // reset all cell_status entries after coarsening/refinement
16103 for (auto &cell_rel : this->local_cell_relations)
16104 cell_rel.second = ::CellStatus::cell_will_persist;
16105 }
16106}
16107
16108
16109
16110template <int dim, int spacedim>
16113 const unsigned int global_first_cell,
16114 const unsigned int global_num_cells,
16115 const std::string &filename) const
16116{
16117 // cast away constness
16118 auto tria = const_cast<Triangulation<dim, spacedim> *>(this);
16119
16120 if (this->cell_attached_data.n_attached_data_sets > 0)
16121 {
16122 // pack attached data first
16127 this->get_communicator());
16128
16129 // then store buffers in file
16130 tria->data_serializer.save(global_first_cell,
16131 global_num_cells,
16132 filename,
16133 this->get_communicator());
16134
16135 // and release the memory afterwards
16137 }
16138
16139 // clear all of the callback data, as explained in the documentation of
16140 // register_data_attach()
16141 {
16145 }
16146}
16147
16148
16149template <int dim, int spacedim>
16152 const unsigned int global_first_cell,
16153 const unsigned int global_num_cells,
16154 const unsigned int local_num_cells,
16155 const std::string &filename,
16156 const unsigned int n_attached_deserialize_fixed,
16157 const unsigned int n_attached_deserialize_variable)
16158{
16159 // load saved data, if any was stored
16160 if (this->cell_attached_data.n_attached_deserialize > 0)
16161 {
16162 this->data_serializer.load(global_first_cell,
16163 global_num_cells,
16164 local_num_cells,
16165 filename,
16166 n_attached_deserialize_fixed,
16167 n_attached_deserialize_variable,
16168 this->get_communicator());
16169
16170 this->data_serializer.unpack_cell_status(this->local_cell_relations);
16171
16172 // the CellStatus of all stored cells should always be
16173 // CellStatus::cell_will_persist.
16174 for (const auto &cell_rel : this->local_cell_relations)
16175 {
16176 (void)cell_rel;
16177 Assert((cell_rel.second == // cell_status
16180 }
16181 }
16182}
16183
16184
16185template <int dim, int spacedim>
16188{
16189 levels.clear();
16190 faces.reset();
16191
16192 vertices.clear();
16193 vertices_used.clear();
16194
16195 manifolds.clear();
16196
16197 // In 1d, also reset vertex-to-(boundary|manifold) maps to empty maps
16198 if (dim == 1)
16199 {
16200 Assert(vertex_to_boundary_id_map_1d != nullptr, ExcInternalError());
16201 vertex_to_boundary_id_map_1d->clear();
16202
16203 Assert(vertex_to_manifold_id_map_1d != nullptr, ExcInternalError());
16204 vertex_to_manifold_id_map_1d->clear();
16205 }
16206 else
16207 {
16208 // For dim>1, these maps should simply not exist.
16209 Assert(vertex_to_boundary_id_map_1d == nullptr, ExcInternalError());
16210 Assert(vertex_to_manifold_id_map_1d == nullptr, ExcInternalError());
16211 }
16212
16213
16215}
16216
16217
16218
16219template <int dim, int spacedim>
16223{
16224 const DistortedCellList cells_with_distorted_children =
16225 this->policy->execute_refinement(*this, check_for_distorted_cells);
16226
16227
16228
16229 // re-compute number of lines
16231 *this, levels.size(), number_cache);
16232
16233# ifdef DEBUG
16234 for (const auto &level : levels)
16235 monitor_memory(level->cells, dim);
16236
16237 // check whether really all refinement flags are reset (also of
16238 // previously non-active cells which we may not have touched. If the
16239 // refinement flag of a non-active cell is set, something went wrong
16240 // since the cell-accessors should have caught this)
16241 for (const auto &cell : this->cell_iterators())
16242 Assert(!cell->refine_flag_set(), ExcInternalError());
16243# endif
16244
16245 return cells_with_distorted_children;
16246}
16247
16248
16249
16250template <int dim, int spacedim>
16253{
16254 // first find out if there are any cells at all to be coarsened in the
16255 // loop below
16256 const cell_iterator endc = end();
16257 bool do_coarsen = false;
16258 if (levels.size() >= 2)
16259 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
16260 if (!cell->is_active() && cell->child(0)->coarsen_flag_set())
16261 {
16262 do_coarsen = true;
16263 break;
16264 }
16265
16266 if (!do_coarsen)
16267 return;
16268
16269 // create a vector counting for each line and quads how many cells contain
16270 // the respective object. this is used later to decide which lines can be
16271 // deleted after coarsening a cell.
16272 std::vector<unsigned int> line_cell_count(dim > 1 ? this->n_raw_lines() : 0);
16273 std::vector<unsigned int> quad_cell_count(dim > 2 ? this->n_raw_quads() : 0);
16274 if (dim > 1)
16275 for (const auto &cell : this->cell_iterators())
16276 {
16277 if (dim > 2)
16278 {
16279 const auto line_indices = internal::TriaAccessorImplementation::
16280 Implementation::get_line_indices_of_cell(*cell);
16281 // avoid a compiler warning by fixing the max number of
16282 // loop iterations to 12
16283 const unsigned int n_lines = std::min(cell->n_lines(), 12u);
16284 for (unsigned int l = 0; l < n_lines; ++l)
16285 ++line_cell_count[line_indices[l]];
16286 for (const unsigned int q : cell->face_indices())
16287 ++quad_cell_count[cell->face_index(q)];
16288 }
16289 else
16290 for (unsigned int l = 0; l < cell->n_lines(); ++l)
16291 ++line_cell_count[cell->line(l)->index()];
16292 }
16293
16294 // Since the loop goes over used cells we only need not worry about
16295 // deleting some cells since the ++operator will then just hop over them
16296 // if we should hit one. Do the loop in the reverse way since we may
16297 // only delete some cells if their neighbors have already been deleted
16298 // (if the latter are on a higher level for example). In effect, only
16299 // those cells are deleted of which originally all children were flagged
16300 // and for which all children are on the same refinement level. Note
16301 // that because of the effects of
16302 // @p{fix_coarsen_flags}, of a cell either all or no children must be
16303 // flagged for coarsening, so it is ok to only check the first child
16304 //
16305 // since we delete the *children* of cells, we can ignore cells on the
16306 // highest level, i.e., level must be less than or equal to
16307 // n_levels()-2.
16308 if (levels.size() >= 2)
16309 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
16310 if (!cell->is_active() && cell->child(0)->coarsen_flag_set())
16311 {
16312 for (unsigned int child = 0; child < cell->n_children(); ++child)
16313 {
16314 Assert(cell->child(child)->coarsen_flag_set(),
16316 cell->child(child)->clear_coarsen_flag();
16317 }
16318 // inform all listeners that cell coarsening is going to happen
16319 signals.pre_coarsening_on_cell(cell);
16320 // use a separate function, since this is dimension specific
16321 this->policy->delete_children(*this,
16322 cell,
16323 line_cell_count,
16324 quad_cell_count);
16325 }
16326
16327 // re-compute number of lines and quads
16329 *this, levels.size(), number_cache);
16330}
16331
16332
16333
16334template <int dim, int spacedim>
16337{
16338 // copy a piece of code from prepare_coarsening_and_refinement that
16339 // ensures that the level difference at vertices is limited if so
16340 // desired. we need this code here since at least in 1d we don't
16341 // call the dimension-independent version of
16342 // prepare_coarsening_and_refinement function. in 2d and 3d, having
16343 // this hunk here makes our lives a bit easier as well as it takes
16344 // care of these cases earlier than it would otherwise happen.
16345 //
16346 // the main difference to the code in p_c_and_r is that here we
16347 // absolutely have to make sure that we get things right, i.e. that
16348 // in particular we set flags right if
16349 // limit_level_difference_at_vertices is set. to do so we iterate
16350 // until the flags don't change any more
16351 auto previous_coarsen_flags = internal::extract_raw_coarsen_flags(levels);
16352
16353 bool continue_iterating = true;
16354
16355 do
16356 {
16357 if (smooth_grid & limit_level_difference_at_vertices)
16358 {
16359 Assert(!anisotropic_refinement,
16360 ExcMessage("In case of anisotropic refinement the "
16361 "limit_level_difference_at_vertices flag for "
16362 "mesh smoothing must not be set!"));
16363
16364 // store highest level one of the cells adjacent to a vertex
16365 // belongs to
16366 std::vector<int> vertex_level(vertices.size(), 0);
16367 for (const auto &cell : this->active_cell_iterators())
16368 {
16369 if (cell->refine_flag_set())
16370 for (const unsigned int vertex :
16372 vertex_level[cell->vertex_index(vertex)] =
16373 std::max(vertex_level[cell->vertex_index(vertex)],
16374 cell->level() + 1);
16375 else if (!cell->coarsen_flag_set())
16376 for (const unsigned int vertex :
16378 vertex_level[cell->vertex_index(vertex)] =
16379 std::max(vertex_level[cell->vertex_index(vertex)],
16380 cell->level());
16381 else
16382 {
16383 // if coarsen flag is set then tentatively assume
16384 // that the cell will be coarsened. this isn't
16385 // always true (the coarsen flag could be removed
16386 // again) and so we may make an error here. we try
16387 // to correct this by iterating over the entire
16388 // process until we are converged
16389 Assert(cell->coarsen_flag_set(), ExcInternalError());
16390 for (const unsigned int vertex :
16392 vertex_level[cell->vertex_index(vertex)] =
16393 std::max(vertex_level[cell->vertex_index(vertex)],
16394 cell->level() - 1);
16395 }
16396 }
16397
16398
16399 // loop over all cells in reverse order. do so because we
16400 // can then update the vertex levels on the adjacent
16401 // vertices and maybe already flag additional cells in this
16402 // loop
16403 //
16404 // note that not only may we have to add additional
16405 // refinement flags, but we will also have to remove
16406 // coarsening flags on cells adjacent to vertices that will
16407 // see refinement
16408 active_cell_iterator endc = end();
16409 for (active_cell_iterator cell = last_active(); cell != endc; --cell)
16410 if (cell->refine_flag_set() == false)
16411 {
16412 for (const unsigned int vertex :
16414 if (vertex_level[cell->vertex_index(vertex)] >=
16415 cell->level() + 1)
16416 {
16417 // remove coarsen flag...
16418 cell->clear_coarsen_flag();
16419
16420 // ...and if necessary also refine the current
16421 // cell, at the same time updating the level
16422 // information about vertices
16423 if (vertex_level[cell->vertex_index(vertex)] >
16424 cell->level() + 1)
16425 {
16426 cell->set_refine_flag();
16427
16428 for (const unsigned int v :
16430 vertex_level[cell->vertex_index(v)] =
16431 std::max(vertex_level[cell->vertex_index(v)],
16432 cell->level() + 1);
16433 }
16434
16435 // continue and see whether we may, for example,
16436 // go into the inner 'if' above based on a
16437 // different vertex
16438 }
16439 }
16440 }
16441
16442 // loop over all cells and remove the coarsen flags for those cells that
16443 // have sister cells not marked for coarsening, or where some neighbors
16444 // are more refined.
16445
16446 // Coarsen flags of cells with no mother cell, i.e. on the
16447 // coarsest level, are deleted explicitly.
16448 for (const auto &acell : this->active_cell_iterators_on_level(0))
16449 acell->clear_coarsen_flag();
16450
16451 const cell_iterator endc = end();
16452 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
16453 {
16454 // nothing to do if we are already on the finest level
16455 if (cell->is_active())
16456 continue;
16457
16458 const unsigned int n_children = cell->n_children();
16459 unsigned int flagged_children = 0;
16460 for (unsigned int child = 0; child < n_children; ++child)
16461 {
16462 const auto child_cell = cell->child(child);
16463 if (child_cell->is_active() && child_cell->coarsen_flag_set())
16464 {
16465 ++flagged_children;
16466 // clear flag since we don't need it anymore
16467 child_cell->clear_coarsen_flag();
16468 }
16469 }
16470
16471 // flag the children for coarsening again if all children were
16472 // flagged and if the policy allows it
16473 if (flagged_children == n_children &&
16474 this->policy->coarsening_allowed(cell))
16475 for (unsigned int c = 0; c < n_children; ++c)
16476 {
16477 Assert(cell->child(c)->refine_flag_set() == false,
16479
16480 cell->child(c)->set_coarsen_flag();
16481 }
16482 }
16483
16484 // now see if anything has changed in the last iteration of this
16485 // function
16486 auto current_coarsen_flags = internal::extract_raw_coarsen_flags(levels);
16487
16488 continue_iterating = (current_coarsen_flags != previous_coarsen_flags);
16489 previous_coarsen_flags.swap(current_coarsen_flags);
16490 }
16491 while (continue_iterating == true);
16492}
16493
16494#endif
16495
16496// TODO: merge the following 3 functions since they are the same
16497template <>
16498bool
16500{
16501 // save the flags to determine whether something was changed in the
16502 // course of this function
16503 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
16504
16505 // do nothing in 1d, except setting the coarsening flags correctly
16506 fix_coarsen_flags();
16507
16508 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
16509
16510 return (flags_before != flags_after);
16511}
16512
16513
16514
16515template <>
16516bool
16518{
16519 // save the flags to determine whether something was changed in the
16520 // course of this function
16521 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
16522
16523 // do nothing in 1d, except setting the coarsening flags correctly
16524 fix_coarsen_flags();
16525
16526 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
16527
16528 return (flags_before != flags_after);
16529}
16530
16531
16532
16533template <>
16534bool
16536{
16537 // save the flags to determine whether something was changed in the
16538 // course of this function
16539 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
16540
16541 // do nothing in 1d, except setting the coarsening flags correctly
16542 fix_coarsen_flags();
16543
16544 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
16545
16546 return (flags_before != flags_after);
16547}
16548
16549
16550
16551namespace
16552{
16553 // check if the given @param cell marked for coarsening would
16554 // produce an unrefined island. To break up long chains of these
16555 // cells we recursively check our neighbors in case we change this
16556 // cell. This reduces the number of outer iterations dramatically.
16557 template <int dim, int spacedim>
16558 void
16559 possibly_do_not_produce_unrefined_islands(
16561 {
16562 Assert(cell->has_children(), ExcInternalError());
16563
16564 unsigned int n_neighbors = 0;
16565 // count all neighbors that will be refined along the face of our
16566 // cell after the next step
16567 unsigned int count = 0;
16568 for (const unsigned int n : GeometryInfo<dim>::face_indices())
16569 {
16570 const typename Triangulation<dim, spacedim>::cell_iterator neighbor =
16571 cell->neighbor(n);
16572 if (neighbor.state() == IteratorState::valid)
16573 {
16574 ++n_neighbors;
16575 if (face_will_be_refined_by_neighbor(cell, n))
16576 ++count;
16577 }
16578 }
16579 // clear coarsen flags if either all existing neighbors will be
16580 // refined or all but one will be and the cell is in the interior
16581 // of the domain
16582 if (count == n_neighbors ||
16583 (count >= n_neighbors - 1 &&
16584 n_neighbors == GeometryInfo<dim>::faces_per_cell))
16585 {
16586 for (unsigned int c = 0; c < cell->n_children(); ++c)
16587 cell->child(c)->clear_coarsen_flag();
16588
16589 for (const unsigned int face : GeometryInfo<dim>::face_indices())
16590 if (!cell->at_boundary(face) &&
16591 (!cell->neighbor(face)->is_active()) &&
16592 (cell_will_be_coarsened(cell->neighbor(face))))
16593 possibly_do_not_produce_unrefined_islands<dim, spacedim>(
16594 cell->neighbor(face));
16595 }
16596 }
16597
16598
16599 // see if the current cell needs to be refined to avoid unrefined
16600 // islands.
16601 //
16602 // there are sometimes chains of cells that induce refinement of
16603 // each other. to avoid running the loop in
16604 // prepare_coarsening_and_refinement over and over again for each
16605 // one of them, at least for the isotropic refinement case we seek
16606 // to flag neighboring elements as well as necessary. this takes
16607 // care of (slightly pathological) cases like
16608 // deal.II/mesh_smoothing_03
16609 template <int dim, int spacedim>
16610 void
16611 possibly_refine_unrefined_island(
16613 const bool allow_anisotropic_smoothing)
16614 {
16615 Assert(cell->is_active(), ExcInternalError());
16616
16617#ifdef DEBUG
16618 // If this is not a parallel::distributed::Triangulation, then we really
16619 // should only get here if the cell is marked for refinement:
16621 *>(&cell->get_triangulation()) == nullptr)
16622 Assert(cell->refine_flag_set() == false, ExcInternalError());
16623 else
16624 // But if this is a p::d::Triangulation, then we don't have that
16625 // much control and we can get here because mesh smoothing is
16626 // requested but can not be honored because p4est controls
16627 // what gets refined. In that case, we can at least provide
16628 // a better error message.
16629 Assert(cell->refine_flag_set() == false,
16630 ExcMessage(
16631 "The triangulation is trying to avoid unrefined islands "
16632 "during mesh refinement/coarsening, as you had requested "
16633 " by passing the appropriate 'smoothing flags' to the "
16634 "constructor of the triangulation. However, for objects "
16635 "of type parallel::distributed::Triangulation, control "
16636 "over which cells get refined rests with p4est, not the "
16637 "deal.II triangulation, and consequently it is not "
16638 "always possible to avoid unrefined islands in the mesh. "
16639 "Please remove the constructor argument to the triangulation "
16640 "object that requests mesh smoothing."));
16641#endif
16642
16643 // now we provide two algorithms. the first one is the standard
16644 // one, coming from the time, where only isotropic refinement was
16645 // possible. it simply counts the neighbors that are or will be
16646 // refined and compares to the number of other ones. the second
16647 // one does this check independently for each direction: if all
16648 // neighbors in one direction (normally two, at the boundary only
16649 // one) are refined, the current cell is flagged to be refined in
16650 // an according direction.
16651
16652 if (allow_anisotropic_smoothing == false)
16653 {
16654 // use first algorithm
16655 unsigned int refined_neighbors = 0, unrefined_neighbors = 0;
16656 for (const unsigned int face : GeometryInfo<dim>::face_indices())
16657 if (!cell->at_boundary(face))
16658 {
16659 if (face_will_be_refined_by_neighbor(cell, face))
16660 ++refined_neighbors;
16661 else
16662 ++unrefined_neighbors;
16663 }
16664
16665 if (unrefined_neighbors < refined_neighbors)
16666 {
16667 cell->clear_coarsen_flag();
16668 cell->set_refine_flag();
16669
16670 // ok, so now we have flagged this cell. if we know that
16671 // there were any unrefined neighbors at all, see if any
16672 // of those will have to be refined as well
16673 if (unrefined_neighbors > 0)
16674 for (const unsigned int face : GeometryInfo<dim>::face_indices())
16675 if (!cell->at_boundary(face) &&
16676 (face_will_be_refined_by_neighbor(cell, face) == false) &&
16677 (cell->neighbor(face)->has_children() == false) &&
16678 (cell->neighbor(face)->refine_flag_set() == false))
16679 possibly_refine_unrefined_island<dim, spacedim>(
16680 cell->neighbor(face), allow_anisotropic_smoothing);
16681 }
16682 }
16683 else
16684 {
16685 // variable to store the cell refine case needed to fulfill
16686 // all smoothing requirements
16687 RefinementCase<dim> smoothing_cell_refinement_case =
16689
16690 // use second algorithm, do the check individually for each
16691 // direction
16692 for (unsigned int face_pair = 0;
16693 face_pair < GeometryInfo<dim>::faces_per_cell / 2;
16694 ++face_pair)
16695 {
16696 // variable to store the cell refine case needed to refine
16697 // at the current face pair in the same way as the
16698 // neighbors do...
16699 RefinementCase<dim> directional_cell_refinement_case =
16701
16702 for (unsigned int face_index = 0; face_index < 2; ++face_index)
16703 {
16704 unsigned int face = 2 * face_pair + face_index;
16705 // variable to store the refine case (to come) of the
16706 // face under consideration
16707 RefinementCase<dim - 1> expected_face_ref_case =
16708 RefinementCase<dim - 1>::no_refinement;
16709
16710 if (cell->neighbor(face).state() == IteratorState::valid)
16711 face_will_be_refined_by_neighbor<dim, spacedim>(
16712 cell, face, expected_face_ref_case);
16713 // now extract which refine case would be necessary to
16714 // achieve the same face refinement. set the
16715 // intersection with other requirements for the same
16716 // direction.
16717
16718 // note: using the intersection is not an obvious
16719 // decision, we could also argue that it is more
16720 // natural to use the union. however, intersection is
16721 // the less aggressive tactic and favours a smaller
16722 // number of refined cells over an intensive
16723 // smoothing. this way we try not to lose too much of
16724 // the effort we put in anisotropic refinement
16725 // indicators due to overly aggressive smoothing...
16726 directional_cell_refinement_case =
16727 (directional_cell_refinement_case &
16730 expected_face_ref_case,
16731 face,
16732 cell->face_orientation(face),
16733 cell->face_flip(face),
16734 cell->face_rotation(face)));
16735 } // for both face indices
16736 // if both requirements sum up to something useful, add
16737 // this to the refine case for smoothing. note: if
16738 // directional_cell_refinement_case is isotropic still,
16739 // then something went wrong...
16740 Assert(directional_cell_refinement_case <
16743 smoothing_cell_refinement_case =
16744 smoothing_cell_refinement_case | directional_cell_refinement_case;
16745 } // for all face_pairs
16746 // no we collected contributions from all directions. combine
16747 // the new flags with the existing refine case, but only if
16748 // smoothing is required
16749 if (smoothing_cell_refinement_case)
16750 {
16751 cell->clear_coarsen_flag();
16752 cell->set_refine_flag(cell->refine_flag_set() |
16753 smoothing_cell_refinement_case);
16754 }
16755 }
16756 }
16757} // namespace
16758
16759#ifndef DOXYGEN
16760template <int dim, int spacedim>
16763{
16764 // save the flags to determine whether something was changed in the
16765 // course of this function
16766 const auto coarsen_flags_before = internal::extract_raw_coarsen_flags(levels);
16767 const auto refine_flags_before = internal::extract_raw_refine_flags(levels);
16768
16769 // save the flags at the outset of each loop. we do so in order to
16770 // find out whether something was changed in the present loop, in
16771 // which case we would have to re-run the loop. the other
16772 // possibility to find this out would be to set a flag
16773 // @p{something_changed} to true each time we change something.
16774 // however, sometimes one change in one of the parts of the loop is
16775 // undone by another one, so we might end up in an endless loop. we
16776 // could be tempted to break this loop at an arbitrary number of
16777 // runs, but that would not be a clean solution, since we would
16778 // either have to 1/ break the loop too early, in which case the
16779 // promise that a second call to this function immediately after the
16780 // first one does not change anything, would be broken, or 2/ we do
16781 // as many loops as there are levels. we know that information is
16782 // transported over one level in each run of the loop, so this is
16783 // enough. Unfortunately, each loop is rather expensive, so we chose
16784 // the way presented here
16785 auto coarsen_flags_before_loop = coarsen_flags_before;
16786 auto refine_flags_before_loop = refine_flags_before;
16787
16788 // now for what is done in each loop: we have to fulfill several
16789 // tasks at the same time, namely several mesh smoothing algorithms
16790 // and mesh regularization, by which we mean that the next mesh
16791 // fulfills several requirements such as no double refinement at
16792 // each face or line, etc.
16793 //
16794 // since doing these things at once seems almost impossible (in the
16795 // first year of this library, they were done in two functions, one
16796 // for refinement and one for coarsening, and most things within
16797 // these were done at once, so the code was rather impossible to
16798 // join into this, only, function), we do them one after each
16799 // other. the order in which we do them is such that the important
16800 // tasks, namely regularization, are done last and the least
16801 // important things are done the first. the following order is
16802 // chosen:
16803 //
16804 // 0/ Only if coarsest_level_1 or patch_level_1 is set: clear all
16805 // coarsen flags on level 1 to avoid level 0 cells being created
16806 // by coarsening. As coarsen flags will never be added, this can
16807 // be done once and for all before the actual loop starts.
16808 //
16809 // 1/ do not coarsen a cell if 'most of the neighbors' will be
16810 // refined after the step. This is to prevent occurrence of
16811 // unrefined islands.
16812 //
16813 // 2/ eliminate refined islands in the interior and at the
16814 // boundary. since they don't do much harm besides increasing the
16815 // number of degrees of freedom, doing this has a rather low
16816 // priority.
16817 //
16818 // 3/ limit the level difference of neighboring cells at each
16819 // vertex.
16820 //
16821 // 4/ eliminate unrefined islands. this has higher priority since
16822 // this diminishes the approximation properties not only of the
16823 // unrefined island, but also of the surrounding patch.
16824 //
16825 // 5/ ensure patch level 1. Then the triangulation consists of
16826 // patches, i.e. of cells that are refined once. It follows that
16827 // if at least one of the children of a cell is or will be
16828 // refined than all children need to be refined. This step only
16829 // sets refinement flags and does not set coarsening flags. If
16830 // the patch_level_1 flag is set, then
16831 // eliminate_unrefined_islands, eliminate_refined_inner_islands
16832 // and eliminate_refined_boundary_islands will be fulfilled
16833 // automatically and do not need to be enforced separately.
16834 //
16835 // 6/ take care of the requirement that no double refinement is done
16836 // at each face
16837 //
16838 // 7/ take care that no double refinement is done at each line in 3d
16839 // or higher dimensions.
16840 //
16841 // 8/ make sure that all children of each cell are either flagged
16842 // for coarsening or none of the children is
16843 //
16844 // For some of these steps, it is known that they interact. Namely,
16845 // it is not possible to guarantee that after step 6 another step 5
16846 // would have no effect; the same holds for the opposite order and
16847 // also when taking into account step 7. however, it is important to
16848 // guarantee that step five or six do not undo something that step 5
16849 // did, and step 7 not something of step 6, otherwise the
16850 // requirements will not be satisfied even if the loop
16851 // terminates. this is accomplished by the fact that steps 5 and 6
16852 // only *add* refinement flags and delete coarsening flags
16853 // (therefore, step 6 can't undo something that step 4 already did),
16854 // and step 7 only deletes coarsening flags, never adds some. step 7
16855 // needs also take care that it won't tag cells for refinement for
16856 // which some neighbors are more refined or will be refined.
16857
16858 //------------------------------------
16859 // STEP 0:
16860 // Only if coarsest_level_1 or patch_level_1 is set: clear all
16861 // coarsen flags on level 1 to avoid level 0 cells being created
16862 // by coarsening.
16863 if (((smooth_grid & coarsest_level_1) || (smooth_grid & patch_level_1)) &&
16864 n_levels() >= 2)
16865 {
16866 for (const auto &cell : active_cell_iterators_on_level(1))
16867 cell->clear_coarsen_flag();
16868 }
16869
16870 bool mesh_changed_in_this_loop = false;
16871 do
16872 {
16873 //------------------------------------
16874 // STEP 1:
16875 // do not coarsen a cell if 'most of the neighbors' will be
16876 // refined after the step. This is to prevent the occurrence
16877 // of unrefined islands. If patch_level_1 is set, this will
16878 // be automatically fulfilled.
16879 if (smooth_grid & do_not_produce_unrefined_islands &&
16880 !(smooth_grid & patch_level_1))
16881 {
16882 for (const auto &cell : cell_iterators())
16883 {
16884 // only do something if this
16885 // cell will be coarsened
16886 if (!cell->is_active() && cell_will_be_coarsened(cell))
16887 possibly_do_not_produce_unrefined_islands<dim, spacedim>(cell);
16888 }
16889 }
16890
16891
16892 //------------------------------------
16893 // STEP 2:
16894 // eliminate refined islands in the interior and at the
16895 // boundary. since they don't do much harm besides increasing
16896 // the number of degrees of freedom, doing this has a rather
16897 // low priority. If patch_level_1 is set, this will be
16898 // automatically fulfilled.
16899 //
16900 // there is one corner case to consider: if this is a
16901 // distributed triangulation, there may be refined islands on
16902 // the boundary of which we own only part (e.g. a single cell
16903 // in the corner of a domain). the rest of the island is
16904 // ghost cells and it *looks* like the area around it
16905 // (artificial cells) are coarser but this is only because
16906 // they may actually be equally fine on other
16907 // processors. it's hard to detect this case but we can do
16908 // the following: only set coarsen flags to remove this
16909 // refined island if all cells we want to set flags on are
16910 // locally owned
16911 if (smooth_grid & (eliminate_refined_inner_islands |
16912 eliminate_refined_boundary_islands) &&
16913 !(smooth_grid & patch_level_1))
16914 {
16915 for (const auto &cell : cell_iterators())
16916 if (!cell->is_active() ||
16917 (cell->is_active() && cell->refine_flag_set() &&
16918 cell->is_locally_owned()))
16919 {
16920 // check whether all children are active, i.e. not
16921 // refined themselves. This is a precondition that the
16922 // children may be coarsened away. If the cell is only
16923 // flagged for refinement, then all future children
16924 // will be active
16925 bool all_children_active = true;
16926 if (!cell->is_active())
16927 for (unsigned int c = 0; c < cell->n_children(); ++c)
16928 if (!cell->child(c)->is_active() ||
16929 cell->child(c)->is_ghost() ||
16930 cell->child(c)->is_artificial())
16931 {
16932 all_children_active = false;
16933 break;
16934 }
16935
16936 if (all_children_active)
16937 {
16938 // count number of refined and unrefined neighbors
16939 // of cell. neighbors on lower levels are counted
16940 // as unrefined since they can only get to the
16941 // same level as this cell by the next refinement
16942 // cycle
16943 unsigned int unrefined_neighbors = 0, total_neighbors = 0;
16944
16945 // Keep track if this cell is at a periodic
16946 // boundary or not. TODO: We do not currently run
16947 // the algorithm for inner islands at a periodic
16948 // boundary (remains to be implemented), but we
16949 // also don't want to consider them
16950 // boundary_island cells as this can interfere
16951 // with 2:1 refinement across periodic faces.
16952 // Instead: just ignore those cells for this
16953 // smoothing operation below.
16954 bool at_periodic_boundary = false;
16955
16956 for (const unsigned int n :
16957 GeometryInfo<dim>::face_indices())
16958 {
16959 const cell_iterator neighbor = cell->neighbor(n);
16960 if (neighbor.state() == IteratorState::valid)
16961 {
16962 ++total_neighbors;
16963
16964 if (!face_will_be_refined_by_neighbor(cell, n))
16965 ++unrefined_neighbors;
16966 }
16967 else if (cell->has_periodic_neighbor(n))
16968 {
16969 ++total_neighbors;
16970 at_periodic_boundary = true;
16971 }
16972 }
16973
16974 // if all neighbors unrefined: mark this cell for
16975 // coarsening or don't refine if marked for that
16976 //
16977 // also do the distinction between the two
16978 // versions of the eliminate_refined_*_islands
16979 // flag
16980 //
16981 // the last check is whether there are any
16982 // neighbors at all. if not so, then we are (e.g.)
16983 // on the coarsest grid with one cell, for which,
16984 // of course, we do not remove the refine flag.
16985 if ((unrefined_neighbors == total_neighbors) &&
16986 ((!cell->at_boundary() &&
16987 (smooth_grid & eliminate_refined_inner_islands)) ||
16988 (cell->at_boundary() && !at_periodic_boundary &&
16989 (smooth_grid &
16990 eliminate_refined_boundary_islands))) &&
16991 (total_neighbors != 0))
16992 {
16993 if (!cell->is_active())
16994 for (unsigned int c = 0; c < cell->n_children(); ++c)
16995 {
16996 cell->child(c)->clear_refine_flag();
16997 cell->child(c)->set_coarsen_flag();
16998 }
16999 else
17000 cell->clear_refine_flag();
17001 }
17002 }
17003 }
17004 }
17005
17006 //------------------------------------
17007 // STEP 3:
17008 // limit the level difference of neighboring cells at each
17009 // vertex.
17010 //
17011 // in case of anisotropic refinement this does not make
17012 // sense. as soon as one cell is anisotropically refined, an
17013 // Assertion is thrown. therefore we can ignore this problem
17014 // later on
17015 if (smooth_grid & limit_level_difference_at_vertices)
17016 {
17017 Assert(!anisotropic_refinement,
17018 ExcMessage("In case of anisotropic refinement the "
17019 "limit_level_difference_at_vertices flag for "
17020 "mesh smoothing must not be set!"));
17021
17022 // store highest level one of the cells adjacent to a vertex
17023 // belongs to
17024 std::vector<int> vertex_level(vertices.size(), 0);
17025 for (const auto &cell : active_cell_iterators())
17026 {
17027 if (cell->refine_flag_set())
17028 for (const unsigned int vertex :
17030 vertex_level[cell->vertex_index(vertex)] =
17031 std::max(vertex_level[cell->vertex_index(vertex)],
17032 cell->level() + 1);
17033 else if (!cell->coarsen_flag_set())
17034 for (const unsigned int vertex :
17036 vertex_level[cell->vertex_index(vertex)] =
17037 std::max(vertex_level[cell->vertex_index(vertex)],
17038 cell->level());
17039 else
17040 {
17041 // if coarsen flag is set then tentatively assume
17042 // that the cell will be coarsened. this isn't
17043 // always true (the coarsen flag could be removed
17044 // again) and so we may make an error here
17045 Assert(cell->coarsen_flag_set(), ExcInternalError());
17046 for (const unsigned int vertex :
17048 vertex_level[cell->vertex_index(vertex)] =
17049 std::max(vertex_level[cell->vertex_index(vertex)],
17050 cell->level() - 1);
17051 }
17052 }
17053
17054
17055 // loop over all cells in reverse order. do so because we
17056 // can then update the vertex levels on the adjacent
17057 // vertices and maybe already flag additional cells in this
17058 // loop
17059 //
17060 // note that not only may we have to add additional
17061 // refinement flags, but we will also have to remove
17062 // coarsening flags on cells adjacent to vertices that will
17063 // see refinement
17064 for (active_cell_iterator cell = last_active(); cell != end(); --cell)
17065 if (cell->refine_flag_set() == false)
17066 {
17067 for (const unsigned int vertex :
17069 if (vertex_level[cell->vertex_index(vertex)] >=
17070 cell->level() + 1)
17071 {
17072 // remove coarsen flag...
17073 cell->clear_coarsen_flag();
17074
17075 // ...and if necessary also refine the current
17076 // cell, at the same time updating the level
17077 // information about vertices
17078 if (vertex_level[cell->vertex_index(vertex)] >
17079 cell->level() + 1)
17080 {
17081 cell->set_refine_flag();
17082
17083 for (const unsigned int v :
17085 vertex_level[cell->vertex_index(v)] =
17086 std::max(vertex_level[cell->vertex_index(v)],
17087 cell->level() + 1);
17088 }
17089
17090 // continue and see whether we may, for example,
17091 // go into the inner'if'
17092 // above based on a
17093 // different vertex
17094 }
17095 }
17096 }
17097
17098 //-----------------------------------
17099 // STEP 4:
17100 // eliminate unrefined islands. this has higher priority
17101 // since this diminishes the approximation properties not
17102 // only of the unrefined island, but also of the surrounding
17103 // patch.
17104 //
17105 // do the loop from finest to coarsest cells since we may
17106 // trigger a cascade by marking cells for refinement which
17107 // may trigger more cells further down below
17108 if (smooth_grid & eliminate_unrefined_islands)
17109 {
17110 for (active_cell_iterator cell = last_active(); cell != end(); --cell)
17111 // only do something if cell is not already flagged for
17112 // (isotropic) refinement
17113 if (cell->refine_flag_set() !=
17115 possibly_refine_unrefined_island<dim, spacedim>(
17116 cell, (smooth_grid & allow_anisotropic_smoothing) != 0);
17117 }
17118
17119 //-------------------------------
17120 // STEP 5:
17121 // ensure patch level 1.
17122 //
17123 // Introduce some terminology:
17124 // - a cell that is refined
17125 // once is a patch of
17126 // level 1 simply called patch.
17127 // - a cell that is globally
17128 // refined twice is called
17129 // a patch of level 2.
17130 // - patch level n says that
17131 // the triangulation consists
17132 // of patches of level n.
17133 // This makes sense only
17134 // if the grid is already at
17135 // least n times globally
17136 // refined.
17137 //
17138 // E.g. from patch level 1 follows: if at least one of the
17139 // children of a cell is or will be refined than enforce all
17140 // children to be refined.
17141
17142 // This step 4 only sets refinement flags and does not set
17143 // coarsening flags.
17144 if (smooth_grid & patch_level_1)
17145 {
17146 // An important assumption (A) is that before calling this
17147 // function the grid was already of patch level 1.
17148
17149 // loop over all cells whose children are all active. (By
17150 // assumption (A) either all or none of the children are
17151 // active). If the refine flag of at least one of the
17152 // children is set then set_refine_flag and
17153 // clear_coarsen_flag of all children.
17154 for (const auto &cell : cell_iterators())
17155 if (!cell->is_active())
17156 {
17157 // ensure the invariant. we can then check whether all
17158 // of its children are further refined or not by
17159 // simply looking at the first child
17160 Assert(cell_is_patch_level_1(cell), ExcInternalError());
17161 if (cell->child(0)->has_children() == true)
17162 continue;
17163
17164 // cell is found to be a patch. combine the refine
17165 // cases of all children
17166 RefinementCase<dim> combined_ref_case =
17168 for (unsigned int i = 0; i < cell->n_children(); ++i)
17169 combined_ref_case =
17170 combined_ref_case | cell->child(i)->refine_flag_set();
17171 if (combined_ref_case != RefinementCase<dim>::no_refinement)
17172 for (unsigned int i = 0; i < cell->n_children(); ++i)
17173 {
17174 cell_iterator child = cell->child(i);
17175
17176 child->clear_coarsen_flag();
17177 child->set_refine_flag(combined_ref_case);
17178 }
17179 }
17180
17181 // The code above dealt with the case where we may get a
17182 // non-patch_level_1 mesh from refinement. Now also deal
17183 // with the case where we could get such a mesh by
17184 // coarsening. Coarsen the children (and remove the
17185 // grandchildren) only if all cell->grandchild(i)
17186 // ->coarsen_flag_set() are set.
17187 //
17188 // for a case where this is a bit tricky, take a look at the
17189 // mesh_smoothing_0[12] testcases
17190 for (const auto &cell : cell_iterators())
17191 {
17192 // check if this cell has active grandchildren. note
17193 // that we know that it is patch_level_1, i.e. if one of
17194 // its children is active then so are all, and it isn't
17195 // going to have any grandchildren at all:
17196 if (cell->is_active() || cell->child(0)->is_active())
17197 continue;
17198
17199 // cell is not active, and so are none of its
17200 // children. check the grandchildren. note that the
17201 // children are also patch_level_1, and so we only ever
17202 // need to check their first child
17203 const unsigned int n_children = cell->n_children();
17204 bool has_active_grandchildren = false;
17205
17206 for (unsigned int i = 0; i < n_children; ++i)
17207 if (cell->child(i)->child(0)->is_active())
17208 {
17209 has_active_grandchildren = true;
17210 break;
17211 }
17212
17213 if (has_active_grandchildren == false)
17214 continue;
17215
17216
17217 // ok, there are active grandchildren. see if either all
17218 // or none of them are flagged for coarsening
17219 unsigned int n_grandchildren = 0;
17220
17221 // count all coarsen flags of the grandchildren.
17222 unsigned int n_coarsen_flags = 0;
17223
17224 // cell is not a patch (of level 1) as it has a
17225 // grandchild. Is cell a patch of level 2?? Therefore:
17226 // find out whether all cell->child(i) are patches
17227 for (unsigned int c = 0; c < n_children; ++c)
17228 {
17229 // get at the child. by assumption (A), and the
17230 // check by which we got here, the child is not
17231 // active
17232 cell_iterator child = cell->child(c);
17233
17234 const unsigned int nn_children = child->n_children();
17235 n_grandchildren += nn_children;
17236
17237 // if child is found to be a patch of active cells
17238 // itself, then add up how many of its children are
17239 // supposed to be coarsened
17240 if (child->child(0)->is_active())
17241 for (unsigned int cc = 0; cc < nn_children; ++cc)
17242 if (child->child(cc)->coarsen_flag_set())
17243 ++n_coarsen_flags;
17244 }
17245
17246 // if not all grandchildren are supposed to be coarsened
17247 // (e.g. because some simply don't have the flag set, or
17248 // because they are not active and therefore cannot
17249 // carry the flag), then remove the coarsen flag from
17250 // all of the active grandchildren. note that there may
17251 // be coarsen flags on the grandgrandchildren -- we
17252 // don't clear them here, but we'll get to them in later
17253 // iterations if necessary
17254 //
17255 // there is nothing we have to do if no coarsen flags
17256 // have been set at all
17257 if ((n_coarsen_flags != n_grandchildren) && (n_coarsen_flags > 0))
17258 for (unsigned int c = 0; c < n_children; ++c)
17259 {
17260 const cell_iterator child = cell->child(c);
17261 if (child->child(0)->is_active())
17262 for (unsigned int cc = 0; cc < child->n_children(); ++cc)
17263 child->child(cc)->clear_coarsen_flag();
17264 }
17265 }
17266 }
17267
17268 //--------------------------------
17269 //
17270 // at the boundary we could end up with cells with negative
17271 // volume or at least with a part, that is negative, if the
17272 // cell is refined anisotropically. we have to check, whether
17273 // that can happen
17274 this->policy->prevent_distorted_boundary_cells(*this);
17275
17276 //-------------------------------
17277 // STEP 6:
17278 // take care of the requirement that no
17279 // double refinement is done at each face
17280 //
17281 // in case of anisotropic refinement it is only likely, but
17282 // not sure, that the cells, which are more refined along a
17283 // certain face common to two cells are on a higher
17284 // level. therefore we cannot be sure, that the requirement
17285 // of no double refinement is fulfilled after a single pass
17286 // of the following actions. We could just wait for the next
17287 // global loop. when this function terminates, the
17288 // requirement will be fulfilled. However, it might be faster
17289 // to insert an inner loop here.
17290 bool changed = true;
17291 while (changed)
17292 {
17293 changed = false;
17294 active_cell_iterator cell = last_active(), endc = end();
17295
17296 for (; cell != endc; --cell)
17297 if (cell->refine_flag_set())
17298 {
17299 // loop over neighbors of cell
17300 for (const auto i : cell->face_indices())
17301 {
17302 // only do something if the face is not at the
17303 // boundary and if the face will be refined with
17304 // the RefineCase currently flagged for
17305 const bool has_periodic_neighbor =
17306 cell->has_periodic_neighbor(i);
17307 const bool has_neighbor_or_periodic_neighbor =
17308 !cell->at_boundary(i) || has_periodic_neighbor;
17309 if (has_neighbor_or_periodic_neighbor &&
17311 cell->refine_flag_set(), i) !=
17313 {
17314 // 1) if the neighbor has children: nothing to
17315 // worry about. 2) if the neighbor is active
17316 // and a coarser one, ensure, that its
17317 // refine_flag is set 3) if the neighbor is
17318 // active and as refined along the face as our
17319 // current cell, make sure, that no
17320 // coarsen_flag is set. if we remove the
17321 // coarsen flag of our neighbor,
17322 // fix_coarsen_flags() makes sure, that the
17323 // mother cell will not be coarsened
17324 if (cell->neighbor_or_periodic_neighbor(i)->is_active())
17325 {
17326 if ((!has_periodic_neighbor &&
17327 cell->neighbor_is_coarser(i)) ||
17328 (has_periodic_neighbor &&
17329 cell->periodic_neighbor_is_coarser(i)))
17330 {
17331 if (cell->neighbor_or_periodic_neighbor(i)
17332 ->coarsen_flag_set())
17333 cell->neighbor_or_periodic_neighbor(i)
17334 ->clear_coarsen_flag();
17335 // we'll set the refine flag for this
17336 // neighbor below. we note, that we
17337 // have changed something by setting
17338 // the changed flag to true. We do not
17339 // need to do so, if we just removed
17340 // the coarsen flag, as the changed
17341 // flag only indicates the need to
17342 // re-run the inner loop. however, we
17343 // only loop over cells flagged for
17344 // refinement here, so nothing to
17345 // worry about if we remove coarsen
17346 // flags
17347
17348 if (dim == 2)
17349 {
17350 if (smooth_grid &
17351 allow_anisotropic_smoothing)
17352 changed =
17353 has_periodic_neighbor ?
17354 cell->periodic_neighbor(i)
17355 ->flag_for_face_refinement(
17356 cell
17357 ->periodic_neighbor_of_coarser_periodic_neighbor(
17358 i)
17359 .first,
17361 cell->neighbor(i)
17362 ->flag_for_face_refinement(
17363 cell
17364 ->neighbor_of_coarser_neighbor(
17365 i)
17366 .first,
17368 else
17369 {
17370 if (!cell
17371 ->neighbor_or_periodic_neighbor(
17372 i)
17373 ->refine_flag_set())
17374 changed = true;
17375 cell->neighbor_or_periodic_neighbor(i)
17376 ->set_refine_flag();
17377 }
17378 }
17379 else // i.e. if (dim==3)
17380 {
17381 // ugly situations might arise here,
17382 // consider the following situation, which
17383 // shows neighboring cells at the common
17384 // face, where the upper right element is
17385 // coarser at the given face. Now the upper
17386 // child element of the lower left wants to
17387 // refine according to cut_z, such that
17388 // there is a 'horizontal' refinement of the
17389 // face marked with #####
17390 //
17391 // / /
17392 // / /
17393 // *---------------*
17394 // | |
17395 // | |
17396 // | |
17397 // | |
17398 // | |
17399 // | | /
17400 // | |/
17401 // *---------------*
17402 //
17403 //
17404 // *---------------*
17405 // /| /|
17406 // / | ##### / |
17407 // | |
17408 // *---------------*
17409 // /| /|
17410 // / | / |
17411 // | |
17412 // *---------------*
17413 // / /
17414 // / /
17415 //
17416 // this introduces too many hanging nodes
17417 // and the neighboring (coarser) cell (upper
17418 // right) has to be refined. If it is only
17419 // refined according to cut_z, then
17420 // everything is ok:
17421 //
17422 // / /
17423 // / /
17424 // *---------------*
17425 // | |
17426 // | | /
17427 // | |/
17428 // *---------------*
17429 // | |
17430 // | | /
17431 // | |/
17432 // *---------------*
17433 //
17434 //
17435 // *---------------*
17436 // /| /|
17437 // / *---------------*
17438 // /| /|
17439 // *---------------*
17440 // /| /|
17441 // / | / |
17442 // | |
17443 // *---------------*
17444 // / /
17445 // / /
17446 //
17447 // if however the cell wants to refine
17448 // itself in an other way, or if we disallow
17449 // anisotropic smoothing, then simply
17450 // refining the neighbor isotropically is
17451 // not going to work, since this introduces
17452 // a refinement of face ##### with both
17453 // cut_x and cut_y, which is not possible:
17454 //
17455 // / / /
17456 // / / /
17457 // *-------*-------*
17458 // | | |
17459 // | | | /
17460 // | | |/
17461 // *-------*-------*
17462 // | | |
17463 // | | | /
17464 // | | |/
17465 // *-------*-------*
17466 //
17467 //
17468 // *---------------*
17469 // /| /|
17470 // / *---------------*
17471 // /| /|
17472 // *---------------*
17473 // /| /|
17474 // / | / |
17475 // | |
17476 // *---------------*
17477 // / /
17478 // / /
17479 //
17480 // thus, in this case we also need to refine
17481 // our current cell in the new direction:
17482 //
17483 // / / /
17484 // / / /
17485 // *-------*-------*
17486 // | | |
17487 // | | | /
17488 // | | |/
17489 // *-------*-------*
17490 // | | |
17491 // | | | /
17492 // | | |/
17493 // *-------*-------*
17494 //
17495 //
17496 // *-------*-------*
17497 // /| /| /|
17498 // / *-------*-------*
17499 // /| /| /|
17500 // *-------*-------*
17501 // /| / /|
17502 // / | / |
17503 // | |
17504 // *---------------*
17505 // / /
17506 // / /
17507
17508 std::pair<unsigned int, unsigned int>
17509 nb_indices =
17510 has_periodic_neighbor ?
17511 cell
17512 ->periodic_neighbor_of_coarser_periodic_neighbor(
17513 i) :
17514 cell->neighbor_of_coarser_neighbor(i);
17515 unsigned int refined_along_x = 0,
17516 refined_along_y = 0,
17517 to_be_refined_along_x = 0,
17518 to_be_refined_along_y = 0;
17519
17520 const int this_face_index =
17521 cell->face_index(i);
17522
17523 // step 1: detect, along which axis the face
17524 // is currently refined
17525
17526 // first, we need an iterator pointing to
17527 // the parent face. This requires a slight
17528 // detour in case the neighbor is behind a
17529 // periodic face.
17530 const auto parent_face = [&]() {
17531 if (has_periodic_neighbor)
17532 {
17533 const auto neighbor =
17534 cell->periodic_neighbor(i);
17535 const auto parent_face_no =
17536 neighbor
17537 ->periodic_neighbor_of_periodic_neighbor(
17538 nb_indices.first);
17539 auto parent =
17540 neighbor->periodic_neighbor(
17541 nb_indices.first);
17542 return parent->face(parent_face_no);
17543 }
17544 else
17545 return cell->neighbor(i)->face(
17546 nb_indices.first);
17547 }();
17548
17549 if ((this_face_index ==
17550 parent_face->child_index(0)) ||
17551 (this_face_index ==
17552 parent_face->child_index(1)))
17553 {
17554 // this might be an
17555 // anisotropic child. get the
17556 // face refine case of the
17557 // neighbors face and count
17558 // refinements in x and y
17559 // direction.
17560 RefinementCase<dim - 1> frc =
17561 parent_face->refinement_case();
17563 ++refined_along_x;
17565 ++refined_along_y;
17566 }
17567 else
17568 // this has to be an isotropic
17569 // child
17570 {
17571 ++refined_along_x;
17572 ++refined_along_y;
17573 }
17574 // step 2: detect, along which axis the face
17575 // has to be refined given the current
17576 // refine flag
17577 RefinementCase<dim - 1> flagged_frc =
17579 cell->refine_flag_set(),
17580 i,
17581 cell->face_orientation(i),
17582 cell->face_flip(i),
17583 cell->face_rotation(i));
17584 if (flagged_frc &
17586 ++to_be_refined_along_x;
17587 if (flagged_frc &
17589 ++to_be_refined_along_y;
17590
17591 // step 3: set the refine flag of the
17592 // (coarser and active) neighbor.
17593 if ((smooth_grid &
17594 allow_anisotropic_smoothing) ||
17595 cell->neighbor_or_periodic_neighbor(i)
17596 ->refine_flag_set())
17597 {
17598 if (refined_along_x +
17599 to_be_refined_along_x >
17600 1)
17601 changed |=
17602 cell
17603 ->neighbor_or_periodic_neighbor(i)
17604 ->flag_for_face_refinement(
17605 nb_indices.first,
17606 RefinementCase<dim -
17607 1>::cut_axis(0));
17608 if (refined_along_y +
17609 to_be_refined_along_y >
17610 1)
17611 changed |=
17612 cell
17613 ->neighbor_or_periodic_neighbor(i)
17614 ->flag_for_face_refinement(
17615 nb_indices.first,
17616 RefinementCase<dim -
17617 1>::cut_axis(1));
17618 }
17619 else
17620 {
17621 if (cell
17622 ->neighbor_or_periodic_neighbor(i)
17623 ->refine_flag_set() !=
17625 dim>::isotropic_refinement)
17626 changed = true;
17627 cell->neighbor_or_periodic_neighbor(i)
17628 ->set_refine_flag();
17629 }
17630
17631 // step 4: if necessary (see above) add to
17632 // the refine flag of the current cell
17633 cell_iterator nb =
17634 cell->neighbor_or_periodic_neighbor(i);
17635 RefinementCase<dim - 1> nb_frc =
17637 nb->refine_flag_set(),
17638 nb_indices.first,
17639 nb->face_orientation(nb_indices.first),
17640 nb->face_flip(nb_indices.first),
17641 nb->face_rotation(nb_indices.first));
17642 if ((nb_frc & RefinementCase<dim>::cut_x) &&
17643 !((refined_along_x != 0u) ||
17644 (to_be_refined_along_x != 0u)))
17645 changed |= cell->flag_for_face_refinement(
17646 i,
17648 if ((nb_frc & RefinementCase<dim>::cut_y) &&
17649 !((refined_along_y != 0u) ||
17650 (to_be_refined_along_y != 0u)))
17651 changed |= cell->flag_for_face_refinement(
17652 i,
17654 }
17655 } // if neighbor is coarser
17656 else // -> now the neighbor is not coarser
17657 {
17658 cell->neighbor_or_periodic_neighbor(i)
17659 ->clear_coarsen_flag();
17660 const unsigned int nb_nb =
17661 has_periodic_neighbor ?
17662 cell
17663 ->periodic_neighbor_of_periodic_neighbor(
17664 i) :
17665 cell->neighbor_of_neighbor(i);
17666 const cell_iterator neighbor =
17667 cell->neighbor_or_periodic_neighbor(i);
17668 RefinementCase<dim - 1> face_ref_case =
17670 neighbor->refine_flag_set(),
17671 nb_nb,
17672 neighbor->face_orientation(nb_nb),
17673 neighbor->face_flip(nb_nb),
17674 neighbor->face_rotation(nb_nb));
17675 RefinementCase<dim - 1> needed_face_ref_case =
17677 cell->refine_flag_set(),
17678 i,
17679 cell->face_orientation(i),
17680 cell->face_flip(i),
17681 cell->face_rotation(i));
17682 // if the neighbor wants to refine the
17683 // face with cut_x and we want cut_y
17684 // or vice versa, we have to refine
17685 // isotropically at the given face
17686 if ((face_ref_case ==
17688 needed_face_ref_case ==
17690 (face_ref_case ==
17692 needed_face_ref_case ==
17694 {
17695 changed = cell->flag_for_face_refinement(
17696 i, face_ref_case);
17697 neighbor->flag_for_face_refinement(
17698 nb_nb, needed_face_ref_case);
17699 }
17700 }
17701 }
17702 else //-> the neighbor is not active
17703 {
17704 RefinementCase<dim - 1>
17705 face_ref_case = cell->face(i)->refinement_case(),
17706 needed_face_ref_case =
17708 cell->refine_flag_set(),
17709 i,
17710 cell->face_orientation(i),
17711 cell->face_flip(i),
17712 cell->face_rotation(i));
17713 // if the face is refined with cut_x and
17714 // we want cut_y or vice versa, we have to
17715 // refine isotropically at the given face
17716 if ((face_ref_case == RefinementCase<dim>::cut_x &&
17717 needed_face_ref_case ==
17719 (face_ref_case == RefinementCase<dim>::cut_y &&
17720 needed_face_ref_case ==
17722 changed =
17723 cell->flag_for_face_refinement(i,
17724 face_ref_case);
17725 }
17726 }
17727 }
17728 }
17729 }
17730
17731 //------------------------------------
17732 // STEP 7:
17733 // take care that no double refinement is done at each line in 3d or
17734 // higher dimensions.
17735 this->policy->prepare_refinement_dim_dependent(*this);
17736
17737 //------------------------------------
17738 // STEP 8:
17739 // make sure that all children of each cell are either flagged for
17740 // coarsening or none of the children is
17741 fix_coarsen_flags();
17742
17743 // get the refinement and coarsening flags
17744 auto coarsen_flags_after_loop =
17745 internal::extract_raw_coarsen_flags(levels);
17746 auto refine_flags_after_loop = internal::extract_raw_refine_flags(levels);
17747
17748 // find out whether something was changed in this loop
17749 mesh_changed_in_this_loop =
17750 ((coarsen_flags_before_loop != coarsen_flags_after_loop) ||
17751 (refine_flags_before_loop != refine_flags_after_loop));
17752
17753 // set the flags for the next loop already
17754 coarsen_flags_before_loop.swap(coarsen_flags_after_loop);
17755 refine_flags_before_loop.swap(refine_flags_after_loop);
17756 }
17757 while (mesh_changed_in_this_loop);
17758
17759
17760 // find out whether something was really changed in this
17761 // function. Note that @p{..._flags_before_loop} represents the state
17762 // after the last loop, i.e., the present state
17763 return ((coarsen_flags_before != coarsen_flags_before_loop) ||
17764 (refine_flags_before != refine_flags_before_loop));
17765}
17766
17767
17768
17769template <int dim, int spacedim>
17772 const unsigned int magic_number1,
17773 const std::vector<bool> &v,
17774 const unsigned int magic_number2,
17775 std::ostream &out)
17776{
17777 const unsigned int N = v.size();
17778 unsigned char *flags = new unsigned char[N / 8 + 1];
17779 for (unsigned int i = 0; i < N / 8 + 1; ++i)
17780 flags[i] = 0;
17781
17782 for (unsigned int position = 0; position < N; ++position)
17783 flags[position / 8] |= (v[position] ? (1 << (position % 8)) : 0);
17784
17785 AssertThrow(out.fail() == false, ExcIO());
17786
17787 // format:
17788 // 0. magic number
17789 // 1. number of flags
17790 // 2. the flags
17791 // 3. magic number
17792 out << magic_number1 << ' ' << N << std::endl;
17793 for (unsigned int i = 0; i < N / 8 + 1; ++i)
17794 out << static_cast<unsigned int>(flags[i]) << ' ';
17795
17796 out << std::endl << magic_number2 << std::endl;
17797
17798 delete[] flags;
17799
17800 AssertThrow(out.fail() == false, ExcIO());
17801}
17802
17803
17804template <int dim, int spacedim>
17807 const unsigned int magic_number1,
17808 std::vector<bool> &v,
17809 const unsigned int magic_number2,
17810 std::istream &in)
17811{
17812 AssertThrow(in.fail() == false, ExcIO());
17813
17814 unsigned int magic_number;
17815 in >> magic_number;
17816 AssertThrow(magic_number == magic_number1, ExcGridReadError());
17817
17818 unsigned int N;
17819 in >> N;
17820 v.resize(N);
17821
17822 unsigned char *flags = new unsigned char[N / 8 + 1];
17823 unsigned short int tmp;
17824 for (unsigned int i = 0; i < N / 8 + 1; ++i)
17825 {
17826 in >> tmp;
17827 flags[i] = tmp;
17828 }
17829
17830 for (unsigned int position = 0; position != N; ++position)
17831 v[position] = ((flags[position / 8] & (1 << (position % 8))) != 0);
17832
17833 in >> magic_number;
17834 AssertThrow(magic_number == magic_number2, ExcGridReadError());
17835
17836 delete[] flags;
17837
17838 AssertThrow(in.fail() == false, ExcIO());
17839}
17840
17841
17842
17843template <int dim, int spacedim>
17846{
17847 std::size_t mem = 0;
17848 mem += sizeof(MeshSmoothing);
17849 mem += MemoryConsumption::memory_consumption(reference_cells);
17850 mem += MemoryConsumption::memory_consumption(periodic_face_pairs_level_0);
17852 for (const auto &level : levels)
17855 mem += MemoryConsumption::memory_consumption(vertices_used);
17856 mem += sizeof(manifolds);
17857 mem += sizeof(smooth_grid);
17858 mem += MemoryConsumption::memory_consumption(number_cache);
17859 mem += sizeof(faces);
17860 if (faces)
17862
17863 return mem;
17864}
17865
17866
17867
17868template <int dim, int spacedim>
17871 default;
17872
17873#endif
17874
17875// explicit instantiations
17876#include "tria.inst"
17877
ArrayView< typename std::remove_reference< typename std::iterator_traits< Iterator >::reference >::type, MemorySpaceType > make_array_view(const Iterator begin, const Iterator end)
Definition array_view.h:949
CellStatus
Definition cell_status.h:31
@ cell_will_be_refined
@ children_will_be_coarsened
types::coarse_cell_id get_coarse_cell_id() const
Definition cell_id.h:393
virtual std::unique_ptr< Manifold< dim, spacedim > > clone() const =0
Definition point.h:111
numbers::NumberTraits< Number >::real_type distance(const Point< dim, Number > &p) const
static constexpr unsigned char default_combined_face_orientation()
unsigned int standard_to_real_face_vertex(const unsigned int vertex, const unsigned int face, const unsigned char face_orientation) const
static constexpr unsigned char reversed_combined_line_orientation()
unsigned int n_lines() const
unsigned char get_combined_orientation(const ArrayView< const T > &vertices_0, const ArrayView< const T > &vertices_1) const
Subscriptor & operator=(const Subscriptor &)
constexpr void clear()
void join() const
IteratorState::IteratorStates state() const
virtual void add_periodicity(const std::vector< GridTools::PeriodicFacePair< cell_iterator > > &)
virtual types::global_cell_index n_global_active_cells() const
quad_iterator begin_quad(const unsigned int level=0) const
typename IteratorSelector::raw_line_iterator raw_line_iterator
Definition tria.h:4088
active_vertex_iterator begin_active_vertex() const
virtual MPI_Comm get_communicator() const
void load_user_indices_quad(const std::vector< unsigned int > &v)
unsigned int n_quads() const
Triangulation & operator=(Triangulation< dim, spacedim > &&tria) noexcept
void load_user_indices(const std::vector< unsigned int > &v)
std::vector< bool > vertices_used
Definition tria.h:4464
virtual void clear()
bool anisotropic_refinement
Definition tria.h:4476
std::map< std::pair< cell_iterator, unsigned int >, std::pair< std::pair< cell_iterator, unsigned int >, unsigned char > > periodic_face_map
Definition tria.h:4073
active_quad_iterator begin_active_quad(const unsigned int level=0) const
bool get_anisotropic_refinement_flag() const
virtual const MeshSmoothing & get_mesh_smoothing() const
virtual void copy_triangulation(const Triangulation< dim, spacedim > &other_tria)
virtual types::coarse_cell_id n_global_coarse_cells() const
std::unique_ptr< std::map< unsigned int, types::manifold_id > > vertex_to_manifold_id_map_1d
Definition tria.h:4534
void save_user_pointers_quad(std::vector< void * > &v) const
void save_user_flags_hex(std::ostream &out) const
void clear_user_flags_quad()
unsigned int n_faces() const
active_hex_iterator begin_active_hex(const unsigned int level=0) const
static void read_bool_vector(const unsigned int magic_number1, std::vector< bool > &v, const unsigned int magic_number2, std::istream &in)
virtual std::weak_ptr< const Utilities::MPI::Partitioner > global_active_cell_index_partitioner() const
bool all_reference_cells_are_hyper_cube() const
void load_user_flags_line(std::istream &in)
void clear_user_data()
raw_hex_iterator begin_raw_hex(const unsigned int level=0) const
const std::map< std::pair< cell_iterator, unsigned int >, std::pair< std::pair< cell_iterator, unsigned int >, unsigned char > > & get_periodic_face_map() const
void save_user_flags_line(std::ostream &out) const
active_cell_iterator last_active() const
void save(Archive &ar, const unsigned int version) const
std::vector< typename internal::CellAttachedDataSerializer< dim, spacedim >::cell_relation_t > local_cell_relations
Definition tria.h:3906
void reset_global_cell_indices()
face_iterator end_face() const
void reset_active_cell_indices()
cell_iterator create_cell_iterator(const CellId &cell_id) const
cell_iterator begin(const unsigned int level=0) const
void fix_coarsen_flags()
void save_user_pointers_line(std::vector< void * > &v) const
void load_refine_flags(std::istream &in)
void save_user_indices_line(std::vector< unsigned int > &v) const
raw_cell_iterator begin_raw(const unsigned int level=0) const
unsigned int n_lines() const
virtual void set_mesh_smoothing(const MeshSmoothing mesh_smoothing)
unsigned int n_raw_lines() const
virtual std::size_t memory_consumption() const
std::vector< Point< spacedim > > vertices
Definition tria.h:4459
raw_quad_iterator begin_raw_quad(const unsigned int level=0) const
virtual types::subdomain_id locally_owned_subdomain() const
unsigned int n_raw_faces() const
unsigned int n_active_faces() const
virtual void create_triangulation(const std::vector< Point< spacedim > > &vertices, const std::vector< CellData< dim > > &cells, const SubCellData &subcelldata)
const bool check_for_distorted_cells
Definition tria.h:4483
raw_cell_iterator end_raw(const unsigned int level) const
line_iterator end_line() const
std::unique_ptr< std::map< unsigned int, types::boundary_id > > vertex_to_boundary_id_map_1d
Definition tria.h:4511
void load_user_flags_quad(std::istream &in)
unsigned int n_active_cells() const
virtual void update_reference_cells()
std::vector< ReferenceCell > reference_cells
Definition tria.h:4004
void update_periodic_face_map()
void clear_despite_subscriptions()
void coarsen_global(const unsigned int times=1)
Triangulation(const MeshSmoothing smooth_grid=none, const bool check_for_distorted_cells=false)
void save_user_flags(std::ostream &out) const
void refine_global(const unsigned int times=1)
virtual std::weak_ptr< const Utilities::MPI::Partitioner > global_level_cell_index_partitioner(const unsigned int level) const
void load_user_flags_hex(std::istream &in)
void load_user_pointers_quad(const std::vector< void * > &v)
std::unique_ptr<::internal::TriangulationImplementation::TriaFaces > faces
Definition tria.h:4453
unsigned int n_used_vertices() const
void reset_cell_vertex_indices_cache()
unsigned int n_active_lines() const
void load_user_indices_line(const std::vector< unsigned int > &v)
void clear_user_flags_hex()
void save_user_pointers_hex(std::vector< void * > &v) const
const std::vector< ReferenceCell > & get_reference_cells() const
typename IteratorSelector::raw_quad_iterator raw_quad_iterator
Definition tria.h:4089
void load_user_pointers(const std::vector< void * > &v)
unsigned int register_data_attach(const std::function< std::vector< char >(const cell_iterator &, const ::CellStatus)> &pack_callback, const bool returns_variable_size_data)
::internal::TriangulationImplementation::NumberCache< dim > number_cache
Definition tria.h:4494
void save_user_indices_hex(std::vector< unsigned int > &v) const
DistortedCellList execute_refinement()
active_line_iterator begin_active_line(const unsigned int level=0) const
void save_user_indices_quad(std::vector< unsigned int > &v) const
void load_user_pointers_hex(const std::vector< void * > &v)
cell_iterator end() const
virtual bool has_hanging_nodes() const
std::vector< GridTools::PeriodicFacePair< cell_iterator > > periodic_face_pairs_level_0
Definition tria.h:4065
unsigned int n_raw_cells(const unsigned int level) const
bool contains_cell(const CellId &cell_id) const
internal::CellAttachedData< dim, spacedim > cell_attached_data
Definition tria.h:3856
void load_coarsen_flags(std::istream &out)
quad_iterator end_quad() const
line_iterator begin_line(const unsigned int level=0) const
unsigned int max_adjacent_cells() const
vertex_iterator begin_vertex() const
void save_attached_data(const unsigned int global_first_cell, const unsigned int global_num_cells, const std::string &filename) const
void clear_user_flags()
unsigned int n_hexs() const
vertex_iterator end_vertex() const
void load_user_pointers_line(const std::vector< void * > &v)
hex_iterator end_hex() const
hex_iterator begin_hex(const unsigned int level=0) const
virtual void execute_coarsening_and_refinement()
active_cell_iterator end_active(const unsigned int level) const
bool is_mixed_mesh() const
cell_iterator last() const
unsigned int n_active_quads() const
void load_user_indices_hex(const std::vector< unsigned int > &v)
unsigned int n_raw_quads() const
void save_user_pointers(std::vector< void * > &v) const
face_iterator begin_face() const
unsigned int n_cells() const
virtual bool prepare_coarsening_and_refinement()
const std::vector< bool > & get_used_vertices() const
typename IteratorSelector::raw_hex_iterator raw_hex_iterator
Definition tria.h:4090
std::map< types::manifold_id, std::unique_ptr< const Manifold< dim, spacedim > > > manifolds
Definition tria.h:4471
MeshSmoothing smooth_grid
Definition tria.h:3998
void save_refine_flags(std::ostream &out) const
std::unique_ptr< ::internal::TriangulationImplementation::Policy< dim, spacedim > > policy
Definition tria.h:4056
Triangulation< dim, spacedim > & get_triangulation()
void save_user_flags_quad(std::ostream &out) const
Signals signals
Definition tria.h:2509
internal::CellAttachedDataSerializer< dim, spacedim > data_serializer
Definition tria.h:3908
virtual ~Triangulation() override
unsigned int n_vertices() const
void load(Archive &ar, const unsigned int version)
void save_user_indices(std::vector< unsigned int > &v) const
void notify_ready_to_unpack(const unsigned int handle, const std::function< void(const cell_iterator &, const ::CellStatus, const boost::iterator_range< std::vector< char >::const_iterator > &)> &unpack_callback)
bool all_reference_cells_are_simplex() const
std::vector< std::unique_ptr<::internal::TriangulationImplementation::TriaLevel > > levels
Definition tria.h:4445
unsigned int n_raw_hexs(const unsigned int level) const
void set_all_refine_flags()
unsigned int n_active_hexs() const
virtual std::vector< types::boundary_id > get_boundary_ids() const
void load_user_flags(std::istream &in)
void reset_policy()
void save_coarsen_flags(std::ostream &out) const
active_face_iterator begin_active_face() const
void clear_user_flags_line()
raw_line_iterator begin_raw_line(const unsigned int level=0) const
static void write_bool_vector(const unsigned int magic_number1, const std::vector< bool > &v, const unsigned int magic_number2, std::ostream &out)
void flip_all_direction_flags()
active_cell_iterator begin_active(const unsigned int level=0) const
void execute_coarsening()
void load_attached_data(const unsigned int global_first_cell, const unsigned int global_num_cells, const unsigned int local_num_cells, const std::string &filename, const unsigned int n_attached_deserialize_fixed, const unsigned int n_attached_deserialize_variable)
void save(const unsigned int global_first_cell, const unsigned int global_num_cells, const std::string &filename, const MPI_Comm &mpi_communicator) const
Definition tria.cc:672
void pack_data(const std::vector< cell_relation_t > &cell_relations, const std::vector< typename internal::CellAttachedData< dim, spacedim >::pack_callback_t > &pack_callbacks_fixed, const std::vector< typename internal::CellAttachedData< dim, spacedim >::pack_callback_t > &pack_callbacks_variable, const MPI_Comm &mpi_communicator)
Definition tria.cc:141
typename std::pair< cell_iterator, CellStatus > cell_relation_t
Definition tria.h:387
void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation) override
Definition tria.cc:2549
void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation) override
Definition tria.cc:2556
void delete_children(Triangulation< dim, spacedim > &tria, typename Triangulation< dim, spacedim >::cell_iterator &cell, std::vector< unsigned int > &line_cell_count, std::vector< unsigned int > &quad_cell_count) override
Definition tria.cc:2532
void update_neighbors(Triangulation< dim, spacedim > &tria) override
Definition tria.cc:2526
bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell) override
Definition tria.cc:2563
Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells) override
Definition tria.cc:2542
std::unique_ptr< Policy< dim, spacedim > > clone() override
Definition tria.cc:2571
virtual std::unique_ptr< Policy< dim, spacedim > > clone()=0
virtual void update_neighbors(Triangulation< dim, spacedim > &tria)=0
virtual void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation)=0
virtual void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation)=0
virtual Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells)=0
virtual bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell)=0
virtual void delete_children(Triangulation< dim, spacedim > &triangulation, typename Triangulation< dim, spacedim >::cell_iterator &cell, std::vector< unsigned int > &line_cell_count, std::vector< unsigned int > &quad_cell_count)=0
std::vector< std::pair< int, int > > neighbors
std::vector< types::global_cell_index > global_active_cell_indices
std::vector< types::global_cell_index > global_level_cell_indices
std::vector< ReferenceCell > reference_cell
std::vector< types::subdomain_id > level_subdomain_ids
std::vector< types::subdomain_id > subdomain_ids
std::vector< unsigned int > active_cell_indices
std::vector< types::manifold_id > manifold_id
std::vector< BoundaryOrMaterialId > boundary_or_material_id
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:502
#define DEAL_II_CXX20_REQUIRES(condition)
Definition config.h:177
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:503
Point< 3 > vertices[4]
Point< 2 > second
Definition grid_out.cc:4624
Point< 2 > first
Definition grid_out.cc:4623
unsigned int level
Definition grid_out.cc:4626
AdjacentCell adjacent_cells[2]
unsigned int vertex_indices[2]
unsigned int cell_index
IteratorRange< active_cell_iterator > active_cell_iterators_on_level(const unsigned int level) const
IteratorRange< active_face_iterator > active_face_iterators() const
IteratorRange< active_cell_iterator > active_cell_iterators() const
IteratorRange< cell_iterator > cell_iterators_on_level(const unsigned int level) const
IteratorRange< cell_iterator > cell_iterators() const
static ::ExceptionBase & ExcInternalErrorOnCell(int arg1)
static ::ExceptionBase & ExcIO()
static ::ExceptionBase & ExcInteriorQuadCantBeBoundary(int arg1, int arg2, int arg3, int arg4, types::boundary_id arg5)
static ::ExceptionBase & ExcNotImplemented()
static ::ExceptionBase & ExcInconsistentLineInfoOfLine(int arg1, int arg2, std::string arg3)
static ::ExceptionBase & ExcCellHasNegativeMeasure(int arg1)
#define Assert(cond, exc)
static ::ExceptionBase & ExcImpossibleInDim(int arg1)
static ::ExceptionBase & ExcMemoryInexact(int arg1, int arg2)
#define DeclException2(Exception2, type1, type2, outsequence)
Definition exceptions.h:539
#define AssertDimension(dim1, dim2)
#define AssertThrowMPI(error_code)
static ::ExceptionBase & ExcGridHasInvalidCell(int arg1)
static ::ExceptionBase & ExcMultiplySetLineInfoOfLine(int arg1, int arg2)
#define AssertNothrow(cond, exc)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcInteriorLineCantBeBoundary(int arg1, int arg2, types::boundary_id arg3)
#define DeclException3(Exception3, type1, type2, type3, outsequence)
Definition exceptions.h:562
#define DeclException1(Exception1, type1, outsequence)
Definition exceptions.h:516
static ::ExceptionBase & ExcInvalidVertexIndex(int arg1, int arg2, int arg3)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define DeclException5( Exception5, type1, type2, type3, type4, type5, outsequence)
Definition exceptions.h:611
#define AssertThrow(cond, exc)
static ::ExceptionBase & ExcInconsistentQuadInfoOfQuad(int arg1, int arg2, int arg3, int arg4, std::string arg5)
typename IteratorSelector::hex_iterator hex_iterator
Definition tria.h:1685
typename IteratorSelector::active_quad_iterator active_quad_iterator
Definition tria.h:1676
typename IteratorSelector::active_hex_iterator active_hex_iterator
Definition tria.h:1696
typename IteratorSelector::quad_iterator quad_iterator
Definition tria.h:1661
typename IteratorSelector::line_iterator line_iterator
Definition tria.h:1637
TriaIterator< CellAccessor< dim, spacedim > > cell_iterator
Definition tria.h:1550
typename IteratorSelector::active_line_iterator active_line_iterator
Definition tria.h:1652
void set_all_manifold_ids_on_boundary(const types::manifold_id number)
const Manifold< dim, spacedim > & get_manifold(const types::manifold_id number) const
virtual std::vector< types::manifold_id > get_manifold_ids() const
void reset_manifold(const types::manifold_id manifold_number)
void set_manifold(const types::manifold_id number, const Manifold< dim, spacedim > &manifold_object)
void reset_all_manifolds()
void set_all_manifold_ids(const types::manifold_id number)
Task< RT > new_task(const std::function< RT()> &function)
#define AssertIsNotUsed(obj)
#define DEAL_II_ASSERT_UNREACHABLE()
#define DEAL_II_NOT_IMPLEMENTED()
const unsigned int mn_tria_refine_flags_end
const unsigned int mn_tria_coarsen_flags_end
const unsigned int mn_tria_refine_flags_begin
const unsigned int mn_tria_hex_user_flags_end
const unsigned int mn_tria_line_user_flags_begin
const unsigned int mn_tria_line_user_flags_end
const unsigned int mn_tria_quad_user_flags_end
const unsigned int mn_tria_coarsen_flags_begin
const unsigned int mn_tria_hex_user_flags_begin
const unsigned int mn_tria_quad_user_flags_begin
const Mapping< dim, spacedim > & get_default_linear_mapping(const Triangulation< dim, spacedim > &triangulation)
Definition mapping.cc:294
void create_triangulation(Triangulation< dim, dim > &tria, const AdditionalData &additional_data=AdditionalData())
spacedim MeshType< dim - 1, spacedim > const std::set< types::boundary_id > & boundary_ids
void reference_cell(Triangulation< dim, spacedim > &tria, const ReferenceCell &reference_cell)
spacedim const Point< spacedim > & p
Definition grid_tools.h:990
const Triangulation< dim, spacedim > & tria
double diameter(const Triangulation< dim, spacedim > &tria)
if(marked_vertices.size() !=0) for(auto it
for(unsigned int j=best_vertex+1;j< vertices.size();++j) if(vertices_to_use[j])
@ valid
Iterator points to a valid object.
std::enable_if_t< std::is_fundamental_v< T >, std::size_t > memory_consumption(const T &t)
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
Tensor< 2, dim, Number > l(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
constexpr const ReferenceCell Tetrahedron
constexpr const ReferenceCell Quadrilateral
constexpr const ReferenceCell Invalid
constexpr const ReferenceCell Triangle
constexpr const ReferenceCell Hexahedron
constexpr const ReferenceCell Line
int File_write_at_c(MPI_File fh, MPI_Offset offset, const void *buf, MPI_Count count, MPI_Datatype datatype, MPI_Status *status)
int File_read_at_c(MPI_File fh, MPI_Offset offset, void *buf, MPI_Count count, MPI_Datatype datatype, MPI_Status *status)
unsigned int n_mpi_processes(const MPI_Comm mpi_communicator)
Definition mpi.cc:92
T max(const T &t, const MPI_Comm mpi_communicator)
unsigned int this_mpi_process(const MPI_Comm mpi_communicator)
Definition mpi.cc:107
size_t pack(const T &object, std::vector< char > &dest_buffer, const bool allow_compression=true)
Definition utilities.h:1381
constexpr T fixed_power(const T t)
Definition utilities.h:942
unsigned int n_active_cells(const internal::TriangulationImplementation::NumberCache< 1 > &c)
Definition tria.cc:14958
const Manifold< dim, spacedim > & get_default_flat_manifold()
Definition tria.cc:12128
unsigned int n_cells(const internal::TriangulationImplementation::NumberCache< 1 > &c)
Definition tria.cc:14951
void reserve_space(TriaFaces &tria_faces, const unsigned int new_quads_in_pairs, const unsigned int new_quads_single)
Definition tria.cc:1995
void monitor_memory(const TriaLevel &tria_level, const unsigned int true_dimension)
Definition tria.cc:2187
std::tuple< bool, bool, bool > split_face_orientation(const unsigned char combined_face_orientation)
const types::boundary_id internal_face_boundary_id
Definition types.h:312
const types::subdomain_id invalid_subdomain_id
Definition types.h:341
static const unsigned int invalid_unsigned_int
Definition types.h:220
const types::manifold_id flat_manifold_id
Definition types.h:325
const types::global_dof_index invalid_dof_index
Definition types.h:252
const InputIterator OutputIterator out
Definition parallel.h:167
const Iterator const std_cxx20::type_identity_t< Iterator > & end
Definition parallel.h:610
const Iterator & begin
Definition parallel.h:609
STL namespace.
::VectorizedArray< Number, width > min(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > abs(const ::VectorizedArray< Number, width > &)
unsigned int manifold_id
Definition types.h:156
unsigned int boundary_id
Definition types.h:144
const ::parallel::distributed::Triangulation< dim, spacedim > * triangulation
static unsigned int child_cell_on_face(const RefinementCase< dim > &ref_case, const unsigned int face, const unsigned int subface, const bool face_orientation=true, const bool face_flip=false, const bool face_rotation=false, const RefinementCase< dim - 1 > &face_refinement_case=RefinementCase< dim - 1 >::isotropic_refinement)
static RefinementCase< dim - 1 > face_refinement_case(const RefinementCase< dim > &cell_refinement_case, const unsigned int face_no, const bool face_orientation=true, const bool face_flip=false, const bool face_rotation=false)
static std_cxx20::ranges::iota_view< unsigned int, unsigned int > face_indices()
static RefinementCase< dim > min_cell_refinement_case_for_face_refinement(const RefinementCase< dim - 1 > &face_refinement_case, const unsigned int face_no, const bool face_orientation=true, const bool face_flip=false, const bool face_rotation=false)
static unsigned int n_children(const RefinementCase< dim > &refinement_case)
static void alternating_form_at_vertices(const Point< spacedim >(&vertices)[vertices_per_cell], Tensor< spacedim - dim, spacedim >(&forms)[vertices_per_cell])
bool check_consistency(const unsigned int dim) const
std::vector< std::vector< CellData< dim > > > cell_infos
std::vector<::CellData< dim > > coarse_cells
std::vector< Point< spacedim > > coarse_cell_vertices
virtual ~DistortedCellList() noexcept override
std::list< typename Triangulation< dim, spacedim >::cell_iterator > distorted_cells
Definition tria.h:1731
boost::signals2::signal< void(const Triangulation< dim, spacedim > &destination_tria)> copy
Definition tria.h:2355
std::vector< pack_callback_t > pack_callbacks_variable
Definition tria.h:362
std::vector< pack_callback_t > pack_callbacks_fixed
Definition tria.h:361
unsigned int n_attached_data_sets
Definition tria.h:346
static void update_neighbors(Triangulation< 1, spacedim > &)
Definition tria.cc:12005
static Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:12090
static bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &)
Definition tria.cc:12116
static void update_neighbors(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:12009
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:12075
static void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:12108
static void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:12099
static void reserve_space_(TriaObjects &obj, const unsigned int size)
Definition tria.cc:3615
static void reserve_space_(TriaFaces &faces, const unsigned structdim, const unsigned int size)
Definition tria.cc:3555
static void compute_number_cache_dim(const Triangulation< dim, spacedim > &triangulation, const unsigned int level_objects, internal::TriangulationImplementation::NumberCache< 2 > &number_cache)
Definition tria.cc:2777
static void prevent_distorted_boundary_cells(Triangulation< 1, spacedim > &)
Definition tria.cc:11612
static void update_neighbors(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:3005
static void prepare_refinement_dim_dependent(const Triangulation< dim, spacedim > &)
Definition tria.cc:11700
static void delete_children(Triangulation< 3, spacedim > &triangulation, typename Triangulation< 3, spacedim >::cell_iterator &cell, std::vector< unsigned int > &line_cell_count, std::vector< unsigned int > &quad_cell_count)
Definition tria.cc:3910
static void reserve_space_(TriaLevel &level, const unsigned int spacedim, const unsigned int size, const bool orientation_needed)
Definition tria.cc:3577
static void update_neighbors(Triangulation< 1, spacedim > &)
Definition tria.cc:2999
static Triangulation< 3, spacedim >::DistortedCellList execute_refinement(Triangulation< 3, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:7251
static Triangulation< dim, spacedim >::DistortedCellList execute_refinement_isotropic(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:4905
static void compute_number_cache(const Triangulation< dim, spacedim > &triangulation, const unsigned int level_objects, internal::TriangulationImplementation::NumberCache< dim > &number_cache)
Definition tria.cc:2977
static void create_children(Triangulation< 2, spacedim > &triangulation, unsigned int &next_unused_vertex, typename Triangulation< 2, spacedim >::raw_line_iterator &next_unused_line, typename Triangulation< 2, spacedim >::raw_cell_iterator &next_unused_cell, const typename Triangulation< 2, spacedim >::cell_iterator &cell)
Definition tria.cc:4538
static void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:11619
static bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell)
Definition tria.cc:11933
static void compute_number_cache_dim(const Triangulation< dim, spacedim > &triangulation, const unsigned int level_objects, internal::TriangulationImplementation::NumberCache< 3 > &number_cache)
Definition tria.cc:2884
static void delete_children(Triangulation< 1, spacedim > &triangulation, typename Triangulation< 1, spacedim >::cell_iterator &cell, std::vector< unsigned int > &, std::vector< unsigned int > &)
Definition tria.cc:3668
static void prepare_refinement_dim_dependent(Triangulation< 3, spacedim > &triangulation)
Definition tria.cc:11710
static void delete_children(Triangulation< 2, spacedim > &triangulation, typename Triangulation< 2, spacedim >::cell_iterator &cell, std::vector< unsigned int > &line_cell_count, std::vector< unsigned int > &)
Definition tria.cc:3772
static void compute_number_cache_dim(const Triangulation< dim, spacedim > &triangulation, const unsigned int level_objects, internal::TriangulationImplementation::NumberCache< 1 > &number_cache)
Definition tria.cc:2689
static Triangulation< 1, spacedim >::DistortedCellList execute_refinement(Triangulation< 1, spacedim > &triangulation, const bool)
Definition tria.cc:5362
static Triangulation< 3, spacedim >::DistortedCellList execute_refinement_isotropic(Triangulation< 3, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:5907
static void create_triangulation(const std::vector< Point< spacedim > > &vertices, const std::vector< CellData< dim > > &cells, const SubCellData &subcelldata, Triangulation< dim, spacedim > &tria)
Definition tria.cc:3184
static Triangulation< 2, spacedim >::DistortedCellList execute_refinement(Triangulation< 2, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:5597
static void process_subcelldata(const CRS< T > &crs, TriaObjects &obj, const std::vector< CellData< structdim > > &boundary_objects_in, const std::vector< Point< spacedim > > &vertex_locations)
Definition tria.cc:3447
std::vector< std::vector< CellData< dim > > > cell_infos