Reference documentation for deal.II version 9.6.0
\(\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)
396 int variable_data_size_on_cell = 0;
397
398 for (const auto &data : data_cell)
399 variable_data_size_on_cell += data.size();
400
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))
433 {
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 }
457 }
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,
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 }
481
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
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 &file_basename,
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 unsigned int myrank =
687 Utilities::MPI::this_mpi_process(mpi_communicator);
688 const unsigned int mpisize =
689 Utilities::MPI::n_mpi_processes(mpi_communicator);
690
691 if (mpisize > 1)
692 {
693 const unsigned int bytes_per_cell = sizes_fixed_cumulative.back();
694
695 //
696 // ---------- Fixed size data ----------
697 //
698 {
699 const std::string fname_fixed =
700 std::string(file_basename) + "_fixed.data";
701
702 MPI_Info info;
703 int ierr = MPI_Info_create(&info);
704 AssertThrowMPI(ierr);
705
706 MPI_File fh;
707 ierr = MPI_File_open(mpi_communicator,
708 fname_fixed.c_str(),
709 MPI_MODE_CREATE | MPI_MODE_WRONLY,
710 info,
711 &fh);
712 AssertThrowMPI(ierr);
713
714 ierr = MPI_File_set_size(fh, 0); // delete the file contents
715 AssertThrowMPI(ierr);
716 // this barrier is necessary, because otherwise others might already
717 // write while one core is still setting the size to zero.
718 ierr = MPI_Barrier(mpi_communicator);
719 AssertThrowMPI(ierr);
720 ierr = MPI_Info_free(&info);
721 AssertThrowMPI(ierr);
722 // ------------------
723
724 // Write cumulative sizes to file.
725 // Since each processor owns the same information about the data
726 // sizes, it is sufficient to let only the first processor perform
727 // this task.
728 if (myrank == 0)
729 {
731 fh,
732 0,
733 sizes_fixed_cumulative.data(),
734 sizes_fixed_cumulative.size(),
735 MPI_UNSIGNED,
736 MPI_STATUS_IGNORE);
737 AssertThrowMPI(ierr);
738 }
739
740 // Write packed data to file simultaneously.
741 const MPI_Offset size_header =
742 sizes_fixed_cumulative.size() * sizeof(unsigned int);
743
744 // Make sure we do the following computation in 64bit integers to be
745 // able to handle 4GB+ files:
746 const MPI_Offset my_global_file_position =
747 size_header +
748 static_cast<MPI_Offset>(global_first_cell) * bytes_per_cell;
749
750 ierr =
752 my_global_file_position,
753 src_data_fixed.data(),
754 src_data_fixed.size(),
755 MPI_BYTE,
756 MPI_STATUS_IGNORE);
757 AssertThrowMPI(ierr);
758
759 ierr = MPI_File_close(&fh);
760 AssertThrowMPI(ierr);
761 }
762
763
764
765 //
766 // ---------- Variable size data ----------
767 //
768 if (variable_size_data_stored)
769 {
770 const std::string fname_variable =
771 std::string(file_basename) + "_variable.data";
772
773 MPI_Info info;
774 int ierr = MPI_Info_create(&info);
775 AssertThrowMPI(ierr);
776
777 MPI_File fh;
778 ierr = MPI_File_open(mpi_communicator,
779 fname_variable.c_str(),
780 MPI_MODE_CREATE | MPI_MODE_WRONLY,
781 info,
782 &fh);
783 AssertThrowMPI(ierr);
784
785 ierr = MPI_File_set_size(fh, 0); // delete the file contents
786 AssertThrowMPI(ierr);
787 // this barrier is necessary, because otherwise others might already
788 // write while one core is still setting the size to zero.
789 ierr = MPI_Barrier(mpi_communicator);
790 AssertThrowMPI(ierr);
791 ierr = MPI_Info_free(&info);
792 AssertThrowMPI(ierr);
793
794 // Write sizes of each cell into file simultaneously.
795 {
796 const MPI_Offset my_global_file_position =
797 static_cast<MPI_Offset>(global_first_cell) *
798 sizeof(unsigned int);
799
800 // It is very unlikely that a single process has more than
801 // 2 billion cells, but we might as well check.
802 AssertThrow(src_sizes_variable.size() <
803 static_cast<std::size_t>(
804 std::numeric_limits<int>::max()),
806
808 fh,
809 my_global_file_position,
810 src_sizes_variable.data(),
811 src_sizes_variable.size(),
812 MPI_INT,
813 MPI_STATUS_IGNORE);
814 AssertThrowMPI(ierr);
815 }
816
817 // Gather size of data in bytes we want to store from this
818 // processor and compute the prefix sum. We do this in 64 bit
819 // to avoid overflow for files larger than 4GB:
820 const std::uint64_t size_on_proc = src_data_variable.size();
821 std::uint64_t prefix_sum = 0;
822 ierr = MPI_Exscan(&size_on_proc,
823 &prefix_sum,
824 1,
825 MPI_UINT64_T,
826 MPI_SUM,
827 mpi_communicator);
828 AssertThrowMPI(ierr);
829
830 const MPI_Offset my_global_file_position =
831 static_cast<MPI_Offset>(global_num_cells) * sizeof(unsigned int) +
832 prefix_sum;
833
834 // Write data consecutively into file.
836 fh,
837 my_global_file_position,
838 src_data_variable.data(),
839 src_data_variable.size(),
840 MPI_BYTE,
841 MPI_STATUS_IGNORE);
842 AssertThrowMPI(ierr);
843
844
845 ierr = MPI_File_close(&fh);
846 AssertThrowMPI(ierr);
847 }
848 } // if (mpisize > 1)
849 else
850#endif
851 {
852 (void)global_first_cell;
853 (void)global_num_cells;
854 (void)mpi_communicator;
855
856 //
857 // ---------- Fixed size data ----------
858 //
859 {
860 const std::string fname_fixed =
861 std::string(file_basename) + "_fixed.data";
862
863 std::ofstream file(fname_fixed, std::ios::binary | std::ios::out);
864 AssertThrow(file.fail() == false, ExcIO());
865
866 // Write header data.
867 file.write(reinterpret_cast<const char *>(
868 sizes_fixed_cumulative.data()),
869 sizes_fixed_cumulative.size() * sizeof(unsigned int));
870
871 // Write packed data.
872 file.write(reinterpret_cast<const char *>(src_data_fixed.data()),
873 src_data_fixed.size() * sizeof(char));
874 }
875
876 //
877 // ---------- Variable size data ----------
878 //
879 if (variable_size_data_stored)
880 {
881 const std::string fname_variable =
882 std::string(file_basename) + "_variable.data";
883
884 std::ofstream file(fname_variable,
885 std::ios::binary | std::ios::out);
886 AssertThrow(file.fail() == false, ExcIO());
887
888 // Write header data.
889 file.write(reinterpret_cast<const char *>(
890 src_sizes_variable.data()),
891 src_sizes_variable.size() * sizeof(int));
892
893 // Write packed data.
894 file.write(reinterpret_cast<const char *>(src_data_variable.data()),
895 src_data_variable.size() * sizeof(char));
896 }
897 }
898 }
899
900
901 template <int dim, int spacedim>
903 void CellAttachedDataSerializer<dim, spacedim>::load(
904 const unsigned int global_first_cell,
905 const unsigned int global_num_cells,
906 const unsigned int local_num_cells,
907 const std::string &file_basename,
908 const unsigned int n_attached_deserialize_fixed,
909 const unsigned int n_attached_deserialize_variable,
910 const MPI_Comm &mpi_communicator)
911 {
912 Assert(dest_data_fixed.empty(),
913 ExcMessage("Previously loaded data has not been released yet!"));
914
915 variable_size_data_stored = (n_attached_deserialize_variable > 0);
916
917#ifdef DEAL_II_WITH_MPI
918 // Large fractions of this function have been copied from
919 // DataOutInterface::write_vtu_in_parallel.
920 // TODO: Write general MPIIO interface.
921
922 const unsigned int mpisize =
923 Utilities::MPI::n_mpi_processes(mpi_communicator);
924
925 if (mpisize > 1)
926 {
927 //
928 // ---------- Fixed size data ----------
929 //
930 {
931 const std::string fname_fixed =
932 std::string(file_basename) + "_fixed.data";
933
934 MPI_Info info;
935 int ierr = MPI_Info_create(&info);
936 AssertThrowMPI(ierr);
937
938 MPI_File fh;
939 ierr = MPI_File_open(
940 mpi_communicator, fname_fixed.c_str(), MPI_MODE_RDONLY, info, &fh);
941 AssertThrowMPI(ierr);
942
943 ierr = MPI_Info_free(&info);
944 AssertThrowMPI(ierr);
945
946 // Read cumulative sizes from file.
947 // Since all processors need the same information about the data
948 // sizes, let each of them retrieve it by reading from the same
949 // location in the file.
950 sizes_fixed_cumulative.resize(1 + n_attached_deserialize_fixed +
951 (variable_size_data_stored ? 1 : 0));
953 fh,
954 0,
955 sizes_fixed_cumulative.data(),
956 sizes_fixed_cumulative.size(),
957 MPI_UNSIGNED,
958 MPI_STATUS_IGNORE);
959 AssertThrowMPI(ierr);
960
961 // Allocate sufficient memory.
962 const unsigned int bytes_per_cell = sizes_fixed_cumulative.back();
963 dest_data_fixed.resize(static_cast<size_t>(local_num_cells) *
964 bytes_per_cell);
965
966 // Read packed data from file simultaneously.
967 const MPI_Offset size_header =
968 sizes_fixed_cumulative.size() * sizeof(unsigned int);
969
970 // Make sure we do the following computation in 64bit integers to be
971 // able to handle 4GB+ files:
972 const MPI_Offset my_global_file_position =
973 size_header +
974 static_cast<MPI_Offset>(global_first_cell) * bytes_per_cell;
975
976 ierr =
978 my_global_file_position,
979 dest_data_fixed.data(),
980 dest_data_fixed.size(),
981 MPI_BYTE,
982 MPI_STATUS_IGNORE);
983 AssertThrowMPI(ierr);
984
985
986 ierr = MPI_File_close(&fh);
987 AssertThrowMPI(ierr);
988 }
989
990 //
991 // ---------- Variable size data ----------
992 //
993 if (variable_size_data_stored)
994 {
995 const std::string fname_variable =
996 std::string(file_basename) + "_variable.data";
997
998 MPI_Info info;
999 int ierr = MPI_Info_create(&info);
1000 AssertThrowMPI(ierr);
1001
1002 MPI_File fh;
1003 ierr = MPI_File_open(mpi_communicator,
1004 fname_variable.c_str(),
1005 MPI_MODE_RDONLY,
1006 info,
1007 &fh);
1008 AssertThrowMPI(ierr);
1009
1010 ierr = MPI_Info_free(&info);
1011 AssertThrowMPI(ierr);
1012
1013 // Read sizes of all locally owned cells.
1014 dest_sizes_variable.resize(local_num_cells);
1015
1016 const MPI_Offset my_global_file_position_sizes =
1017 static_cast<MPI_Offset>(global_first_cell) * sizeof(unsigned int);
1018
1020 fh,
1021 my_global_file_position_sizes,
1022 dest_sizes_variable.data(),
1023 dest_sizes_variable.size(),
1024 MPI_INT,
1025 MPI_STATUS_IGNORE);
1026 AssertThrowMPI(ierr);
1027
1028
1029 // Compute my data size in bytes and compute prefix sum. We do this
1030 // in 64 bit to avoid overflow for files larger than 4 GB:
1031 const std::uint64_t size_on_proc =
1032 std::accumulate(dest_sizes_variable.begin(),
1033 dest_sizes_variable.end(),
1034 0ULL);
1035
1036 std::uint64_t prefix_sum = 0;
1037 ierr = MPI_Exscan(&size_on_proc,
1038 &prefix_sum,
1039 1,
1040 MPI_UINT64_T,
1041 MPI_SUM,
1042 mpi_communicator);
1043 AssertThrowMPI(ierr);
1044
1045 const MPI_Offset my_global_file_position =
1046 static_cast<MPI_Offset>(global_num_cells) * sizeof(unsigned int) +
1047 prefix_sum;
1048
1049 dest_data_variable.resize(size_on_proc);
1050
1052 fh,
1053 my_global_file_position,
1054 dest_data_variable.data(),
1055 dest_data_variable.size(),
1056 MPI_BYTE,
1057 MPI_STATUS_IGNORE);
1058 AssertThrowMPI(ierr);
1059
1060 ierr = MPI_File_close(&fh);
1061 AssertThrowMPI(ierr);
1062 }
1063 }
1064 else // if (mpisize > 1)
1065#endif
1066 {
1067 (void)global_first_cell;
1068 (void)global_num_cells;
1069 (void)mpi_communicator;
1070
1071 //
1072 // ---------- Fixed size data ----------
1073 //
1074 {
1075 const std::string fname_fixed =
1076 std::string(file_basename) + "_fixed.data";
1077
1078 std::ifstream file(fname_fixed, std::ios::binary | std::ios::in);
1079 AssertThrow(file.fail() == false, ExcIO());
1080
1081 sizes_fixed_cumulative.resize(1 + n_attached_deserialize_fixed +
1082 (variable_size_data_stored ? 1 : 0));
1083
1084 // Read header data.
1085 file.read(reinterpret_cast<char *>(sizes_fixed_cumulative.data()),
1086 sizes_fixed_cumulative.size() * sizeof(unsigned int));
1087
1088 const unsigned int bytes_per_cell = sizes_fixed_cumulative.back();
1089 dest_data_fixed.resize(static_cast<size_t>(local_num_cells) *
1090 bytes_per_cell);
1091
1092 // Read packed data.
1093 file.read(reinterpret_cast<char *>(dest_data_fixed.data()),
1094 dest_data_fixed.size() * sizeof(char));
1095 }
1096
1097 //
1098 // ---------- Variable size data ----------
1099 //
1100 if (variable_size_data_stored)
1101 {
1102 const std::string fname_variable =
1103 std::string(file_basename) + "_variable.data";
1104
1105 std::ifstream file(fname_variable, std::ios::binary | std::ios::in);
1106 AssertThrow(file.fail() == false, ExcIO());
1107
1108 // Read header data.
1109 dest_sizes_variable.resize(local_num_cells);
1110 file.read(reinterpret_cast<char *>(dest_sizes_variable.data()),
1111 dest_sizes_variable.size() * sizeof(int));
1112
1113 // Read packed data.
1114 const std::uint64_t size =
1115 std::accumulate(dest_sizes_variable.begin(),
1116 dest_sizes_variable.end(),
1117 0ULL);
1118 dest_data_variable.resize(size);
1119 file.read(reinterpret_cast<char *>(dest_data_variable.data()),
1120 dest_data_variable.size() * sizeof(char));
1121 }
1122 }
1123 }
1124
1125
1126 template <int dim, int spacedim>
1128 void CellAttachedDataSerializer<dim, spacedim>::clear()
1129 {
1130 variable_size_data_stored = false;
1131
1132 // free information about data sizes
1133 sizes_fixed_cumulative.clear();
1134 sizes_fixed_cumulative.shrink_to_fit();
1135
1136 // free fixed size transfer data
1137 src_data_fixed.clear();
1138 src_data_fixed.shrink_to_fit();
1139
1140 dest_data_fixed.clear();
1141 dest_data_fixed.shrink_to_fit();
1142
1143 // free variable size transfer data
1144 src_sizes_variable.clear();
1145 src_sizes_variable.shrink_to_fit();
1146
1147 src_data_variable.clear();
1148 src_data_variable.shrink_to_fit();
1149
1150 dest_sizes_variable.clear();
1151 dest_sizes_variable.shrink_to_fit();
1152
1153 dest_data_variable.clear();
1154 dest_data_variable.shrink_to_fit();
1155 }
1156
1157} // namespace internal
1158
1159// anonymous namespace for internal helper functions
1160namespace
1161{
1162 // return whether the given cell is
1163 // patch_level_1, i.e. determine
1164 // whether either all or none of
1165 // its children are further
1166 // refined. this function can only
1167 // be called for non-active cells.
1168 template <int dim, int spacedim>
1169 bool
1170 cell_is_patch_level_1(
1172 {
1173 Assert(cell->is_active() == false, ExcInternalError());
1174
1175 unsigned int n_active_children = 0;
1176 for (unsigned int i = 0; i < cell->n_children(); ++i)
1177 if (cell->child(i)->is_active())
1178 ++n_active_children;
1179
1180 return (n_active_children == 0) ||
1181 (n_active_children == cell->n_children());
1182 }
1183
1184
1185
1186 // return, whether a given @p cell will be
1187 // coarsened, which is the case if all
1188 // children are active and have their coarsen
1189 // flag set. In case only part of the coarsen
1190 // flags are set, remove them.
1191 template <int dim, int spacedim>
1192 bool
1193 cell_will_be_coarsened(
1195 {
1196 // only cells with children should be
1197 // considered for coarsening
1198
1199 if (cell->has_children())
1200 {
1201 unsigned int children_to_coarsen = 0;
1202 const unsigned int n_children = cell->n_children();
1203
1204 for (unsigned int c = 0; c < n_children; ++c)
1205 if (cell->child(c)->is_active() && cell->child(c)->coarsen_flag_set())
1206 ++children_to_coarsen;
1207 if (children_to_coarsen == n_children)
1208 return true;
1209 else
1210 for (unsigned int c = 0; c < n_children; ++c)
1211 if (cell->child(c)->is_active())
1212 cell->child(c)->clear_coarsen_flag();
1213 }
1214 // no children, so no coarsening
1215 // possible. however, no children also
1216 // means that this cell will be in the same
1217 // state as if it had children and was
1218 // coarsened. So, what should we return -
1219 // false or true?
1220 // make sure we do not have to do this at
1221 // all...
1222 Assert(cell->has_children(), ExcInternalError());
1223 // ... and then simply return false
1224 return false;
1225 }
1226
1227
1228 // return, whether the face @p face_no of the
1229 // given @p cell will be refined after the
1230 // current refinement step, considering
1231 // refine and coarsen flags and considering
1232 // only those refinemnts that will be caused
1233 // by the neighboring cell.
1234
1235 // this function is used on both active cells
1236 // and cells with children. on cells with
1237 // children it also of interest to know 'how'
1238 // the face will be refined. thus there is an
1239 // additional third argument @p
1240 // expected_face_ref_case returning just
1241 // that. be aware, that this variable will
1242 // only contain useful information if this
1243 // function is called for an active cell.
1244 //
1245 // thus, this is an internal function, users
1246 // should call one of the two alternatives
1247 // following below.
1248 template <int dim, int spacedim>
1249 bool
1250 face_will_be_refined_by_neighbor_internal(
1252 const unsigned int face_no,
1253 RefinementCase<dim - 1> &expected_face_ref_case)
1254 {
1255 // first of all: set the default value for
1256 // expected_face_ref_case, which is no
1257 // refinement at all
1258 expected_face_ref_case = RefinementCase<dim - 1>::no_refinement;
1259
1260 const typename Triangulation<dim, spacedim>::cell_iterator neighbor =
1261 cell->neighbor(face_no);
1262
1263 // If we are at the boundary, there is no
1264 // neighbor which could refine the face
1265 if (neighbor.state() != IteratorState::valid)
1266 return false;
1267
1268 if (neighbor->has_children())
1269 {
1270 // if the neighbor is refined, it may be
1271 // coarsened. if so, then it won't refine
1272 // the face, no matter what else happens
1273 if (cell_will_be_coarsened(neighbor))
1274 return false;
1275 else
1276 // if the neighbor is refined, then it
1277 // is also refined at our current
1278 // face. It will stay so without
1279 // coarsening, so return true in that
1280 // case.
1281 {
1282 expected_face_ref_case = cell->face(face_no)->refinement_case();
1283 return true;
1284 }
1285 }
1286
1287 // now, the neighbor is not refined, but
1288 // perhaps it will be
1289 const RefinementCase<dim> nb_ref_flag = neighbor->refine_flag_set();
1290 if (nb_ref_flag != RefinementCase<dim>::no_refinement)
1291 {
1292 // now we need to know, which of the
1293 // neighbors faces points towards us
1294 const unsigned int neighbor_neighbor = cell->neighbor_face_no(face_no);
1295 // check, whether the cell will be
1296 // refined in a way that refines our
1297 // face
1298 const RefinementCase<dim - 1> face_ref_case =
1300 nb_ref_flag,
1301 neighbor_neighbor,
1302 neighbor->face_orientation(neighbor_neighbor),
1303 neighbor->face_flip(neighbor_neighbor),
1304 neighbor->face_rotation(neighbor_neighbor));
1305 if (face_ref_case != RefinementCase<dim - 1>::no_refinement)
1306 {
1308 neighbor_face = neighbor->face(neighbor_neighbor);
1309 const int this_face_index = cell->face_index(face_no);
1310
1311 // there are still two basic
1312 // possibilities here: the neighbor
1313 // might be coarser or as coarse
1314 // as we are
1315 if (neighbor_face->index() == this_face_index)
1316 // the neighbor is as coarse as
1317 // we are and will be refined at
1318 // the face of consideration, so
1319 // return true
1320 {
1321 expected_face_ref_case = face_ref_case;
1322 return true;
1323 }
1324 else
1325 {
1326 // the neighbor is coarser.
1327 // this is the most complicated
1328 // case. It might be, that the
1329 // neighbor's face will be
1330 // refined, but that we will
1331 // not see this, as we are
1332 // refined in a similar way.
1333
1334 // so, the neighbor's face must
1335 // have children. check, if our
1336 // cell's face is one of these
1337 // (it could also be a
1338 // grand_child)
1339 for (unsigned int c = 0; c < neighbor_face->n_children(); ++c)
1340 if (neighbor_face->child_index(c) == this_face_index)
1341 {
1342 // if the flagged refine
1343 // case of the face is a
1344 // subset or the same as
1345 // the current refine case,
1346 // then the face, as seen
1347 // from our cell, won't be
1348 // refined by the neighbor
1349 if ((neighbor_face->refinement_case() | face_ref_case) ==
1350 neighbor_face->refinement_case())
1351 return false;
1352 else
1353 {
1354 // if we are active, we
1355 // must be an
1356 // anisotropic child
1357 // and the coming
1358 // face_ref_case is
1359 // isotropic. Thus,
1360 // from our cell we
1361 // will see exactly the
1362 // opposite refine case
1363 // that the face has
1364 // now...
1365 Assert(
1366 face_ref_case ==
1369 expected_face_ref_case =
1370 ~neighbor_face->refinement_case();
1371 return true;
1372 }
1373 }
1374
1375 // so, obviously we were not
1376 // one of the children, but a
1377 // grandchild. This is only
1378 // possible in 3d.
1379 Assert(dim == 3, ExcInternalError());
1380 // In that case, however, no
1381 // matter what the neighbor
1382 // does, it won't be finer
1383 // after the next refinement
1384 // step.
1385 return false;
1386 }
1387 } // if face will be refined
1388 } // if neighbor is flagged for refinement
1389
1390 // no cases left, so the neighbor will not
1391 // refine the face
1392 return false;
1393 }
1394
1395 // version of above function for both active
1396 // and non-active cells
1397 template <int dim, int spacedim>
1398 bool
1399 face_will_be_refined_by_neighbor(
1401 const unsigned int face_no)
1402 {
1403 RefinementCase<dim - 1> dummy = RefinementCase<dim - 1>::no_refinement;
1404 return face_will_be_refined_by_neighbor_internal(cell, face_no, dummy);
1405 }
1406
1407 // version of above function for active cells
1408 // only. Additionally returning the refine
1409 // case (to come) of the face under
1410 // consideration
1411 template <int dim, int spacedim>
1412 bool
1413 face_will_be_refined_by_neighbor(
1415 const unsigned int face_no,
1416 RefinementCase<dim - 1> &expected_face_ref_case)
1417 {
1418 return face_will_be_refined_by_neighbor_internal(cell,
1419 face_no,
1420 expected_face_ref_case);
1421 }
1422
1423
1424
1425 template <int dim, int spacedim>
1426 bool
1427 satisfies_level1_at_vertex_rule(
1429 {
1430 std::vector<unsigned int> min_adjacent_cell_level(
1432 std::vector<unsigned int> max_adjacent_cell_level(
1434
1435 for (const auto &cell : triangulation.active_cell_iterators())
1436 for (const unsigned int v : cell->vertex_indices())
1437 {
1438 min_adjacent_cell_level[cell->vertex_index(v)] =
1440 min_adjacent_cell_level[cell->vertex_index(v)], cell->level());
1441 max_adjacent_cell_level[cell->vertex_index(v)] =
1443 min_adjacent_cell_level[cell->vertex_index(v)], cell->level());
1444 }
1445
1446 for (unsigned int k = 0; k < triangulation.n_vertices(); ++k)
1448 if (max_adjacent_cell_level[k] - min_adjacent_cell_level[k] > 1)
1449 return false;
1450 return true;
1451 }
1452
1453
1454
1472 template <int dim, int spacedim>
1473 unsigned int
1474 middle_vertex_index(
1476 {
1477 if (line->has_children())
1478 return line->child(0)->vertex_index(1);
1480 }
1481
1482
1483 template <int dim, int spacedim>
1484 unsigned int
1485 middle_vertex_index(
1487 {
1488 switch (static_cast<unsigned char>(quad->refinement_case()))
1489 {
1491 return middle_vertex_index<dim, spacedim>(quad->child(0)->line(1));
1492 break;
1494 return middle_vertex_index<dim, spacedim>(quad->child(0)->line(3));
1495 break;
1497 return quad->child(0)->vertex_index(3);
1498 break;
1499 default:
1500 break;
1501 }
1503 }
1504
1505
1506 template <int dim, int spacedim>
1507 unsigned int
1508 middle_vertex_index(
1510 {
1511 switch (static_cast<unsigned char>(hex->refinement_case()))
1512 {
1514 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(1));
1515 break;
1517 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(3));
1518 break;
1520 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(5));
1521 break;
1523 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(11));
1524 break;
1526 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(5));
1527 break;
1529 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(7));
1530 break;
1532 return hex->child(0)->vertex_index(7);
1533 break;
1534 default:
1535 break;
1536 }
1538 }
1539
1540
1553 template <class TRIANGULATION>
1554 inline typename TRIANGULATION::DistortedCellList
1555 collect_distorted_coarse_cells(const TRIANGULATION &)
1556 {
1557 return typename TRIANGULATION::DistortedCellList();
1558 }
1559
1560
1561
1570 template <int dim>
1572 collect_distorted_coarse_cells(const Triangulation<dim, dim> &triangulation)
1573 {
1574 typename Triangulation<dim, dim>::DistortedCellList distorted_cells;
1575 for (const auto &cell : triangulation.cell_iterators_on_level(0))
1576 {
1578 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1579 vertices[i] = cell->vertex(i);
1580
1583
1584 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1585 if (determinants[i] <=
1586 1e-9 * Utilities::fixed_power<dim>(cell->diameter()))
1587 {
1588 distorted_cells.distorted_cells.push_back(cell);
1589 break;
1590 }
1591 }
1592
1593 return distorted_cells;
1594 }
1595
1596
1603 template <int dim>
1604 bool
1605 has_distorted_children(
1606 const typename Triangulation<dim, dim>::cell_iterator &cell)
1607 {
1608 Assert(cell->has_children(), ExcInternalError());
1609
1610 for (unsigned int c = 0; c < cell->n_children(); ++c)
1611 {
1613 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1614 vertices[i] = cell->child(c)->vertex(i);
1615
1618
1619 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1620 if (determinants[i] <=
1621 1e-9 * Utilities::fixed_power<dim>(cell->child(c)->diameter()))
1622 return true;
1623 }
1624
1625 return false;
1626 }
1627
1628
1636 template <int dim, int spacedim>
1637 bool
1638 has_distorted_children(
1640 {
1641 return false;
1642 }
1643
1644
1645 template <int dim, int spacedim>
1646 void
1647 update_periodic_face_map_recursively(
1648 const typename Triangulation<dim, spacedim>::cell_iterator &cell_1,
1649 const typename Triangulation<dim, spacedim>::cell_iterator &cell_2,
1650 unsigned int n_face_1,
1651 unsigned int n_face_2,
1652 const unsigned char orientation,
1653 typename std::map<
1655 unsigned int>,
1656 std::pair<std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
1657 unsigned int>,
1658 unsigned char>> &periodic_face_map)
1659 {
1660 using FaceIterator = typename Triangulation<dim, spacedim>::face_iterator;
1661 const FaceIterator face_1 = cell_1->face(n_face_1);
1662 const FaceIterator face_2 = cell_2->face(n_face_2);
1663
1664 const unsigned char inverse_orientation =
1665 face_1->reference_cell().get_inverse_combined_orientation(orientation);
1666
1667#ifdef DEBUG
1668 const auto [face_orientation, face_rotation, face_flip] =
1670
1671 Assert((dim != 1) || (face_orientation == true && face_flip == false &&
1672 face_rotation == false),
1673 ExcMessage("The supplied orientation "
1674 "(face_orientation, face_flip, face_rotation) "
1675 "is invalid for 1d"));
1676
1677 Assert((dim != 2) || (face_flip == false && face_rotation == false),
1678 ExcMessage("The supplied orientation "
1679 "(face_orientation, face_flip, face_rotation) "
1680 "is invalid for 2d"));
1681#endif
1682
1683 Assert(face_1 != face_2, ExcMessage("face_1 and face_2 are equal!"));
1684
1685 Assert(face_1->at_boundary() && face_2->at_boundary(),
1686 ExcMessage("Periodic faces must be on the boundary"));
1687
1688 // Check if the requirement that each edge can only have at most one hanging
1689 // node, and as a consequence neighboring cells can differ by at most
1690 // one refinement level is enforced. In 1d, there are no hanging nodes and
1691 // so neighboring cells can differ by more than one refinement level.
1692 Assert(dim == 1 || std::abs(cell_1->level() - cell_2->level()) < 2,
1694
1695 // insert periodic face pair for both cells
1696 using CellFace =
1697 std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
1698 unsigned int>;
1699 const CellFace cell_face_1(cell_1, n_face_1);
1700 const CellFace cell_face_2(cell_2, n_face_2);
1701 const std::pair<CellFace, unsigned char> cell_face_orientation_2(
1702 cell_face_2, orientation);
1703
1704 const std::pair<CellFace, std::pair<CellFace, unsigned char>>
1705 periodic_faces(cell_face_1, cell_face_orientation_2);
1706
1707 // Only one periodic neighbor is allowed
1708 Assert(periodic_face_map.count(cell_face_1) == 0, ExcInternalError());
1709 periodic_face_map.insert(periodic_faces);
1710
1711 if (dim == 1)
1712 {
1713 if (cell_1->has_children())
1714 {
1715 if (cell_2->has_children())
1716 {
1717 update_periodic_face_map_recursively<dim, spacedim>(
1718 cell_1->child(n_face_1),
1719 cell_2->child(n_face_2),
1720 n_face_1,
1721 n_face_2,
1722 orientation,
1723 periodic_face_map);
1724 }
1725 else // only face_1 has children
1726 {
1727 update_periodic_face_map_recursively<dim, spacedim>(
1728 cell_1->child(n_face_1),
1729 cell_2,
1730 n_face_1,
1731 n_face_2,
1732 orientation,
1733 periodic_face_map);
1734 }
1735 }
1736 }
1737 else // dim == 2 || dim == 3
1738 {
1739 if (cell_1->has_children())
1740 {
1741 if (cell_2->has_children())
1742 {
1743 // In the case that both faces have children, we loop over all
1744 // children and apply update_periodic_face_map_recursively
1745 // recursively:
1746
1747 Assert(face_1->n_children() ==
1749 face_2->n_children() ==
1752
1753 const auto reference_cell = cell_1->reference_cell();
1754
1755 for (unsigned int i = 0;
1756 i < GeometryInfo<dim>::max_children_per_face;
1757 ++i)
1758 {
1759 // Lookup the index for the second face
1760 const unsigned int j =
1761 reference_cell.standard_to_real_face_vertex(
1762 i, n_face_1, inverse_orientation);
1763
1764 // find subcell ids that belong to the subface indices
1765 unsigned int child_cell_1 =
1767 cell_1->refinement_case(),
1768 n_face_1,
1769 i,
1770 cell_1->face_orientation(n_face_1),
1771 cell_1->face_flip(n_face_1),
1772 cell_1->face_rotation(n_face_1),
1773 face_1->refinement_case());
1774 unsigned int child_cell_2 =
1776 cell_2->refinement_case(),
1777 n_face_2,
1778 j,
1779 cell_2->face_orientation(n_face_2),
1780 cell_2->face_flip(n_face_2),
1781 cell_2->face_rotation(n_face_2),
1782 face_2->refinement_case());
1783
1784 Assert(cell_1->child(child_cell_1)->face(n_face_1) ==
1785 face_1->child(i),
1787 Assert(cell_2->child(child_cell_2)->face(n_face_2) ==
1788 face_2->child(j),
1790
1791 // precondition: subcell has the same orientation as cell
1792 // (so that the face numbers coincide) recursive call
1793 update_periodic_face_map_recursively<dim, spacedim>(
1794 cell_1->child(child_cell_1),
1795 cell_2->child(child_cell_2),
1796 n_face_1,
1797 n_face_2,
1798 orientation,
1799 periodic_face_map);
1800 }
1801 }
1802 else // only face_1 has children
1803 {
1804 for (unsigned int i = 0;
1805 i < GeometryInfo<dim>::max_children_per_face;
1806 ++i)
1807 {
1808 // find subcell ids that belong to the subface indices
1809 unsigned int child_cell_1 =
1811 cell_1->refinement_case(),
1812 n_face_1,
1813 i,
1814 cell_1->face_orientation(n_face_1),
1815 cell_1->face_flip(n_face_1),
1816 cell_1->face_rotation(n_face_1),
1817 face_1->refinement_case());
1818
1819 // recursive call
1820 update_periodic_face_map_recursively<dim, spacedim>(
1821 cell_1->child(child_cell_1),
1822 cell_2,
1823 n_face_1,
1824 n_face_2,
1825 orientation,
1826 periodic_face_map);
1827 }
1828 }
1829 }
1830 }
1831 }
1832
1833
1834} // end of anonymous namespace
1835
1836
1837namespace internal
1838{
1839 namespace TriangulationImplementation
1840 {
1841 // make sure that if in the following we
1842 // write Triangulation<dim,spacedim>
1843 // we mean the *class*
1844 // ::Triangulation, not the
1845 // enclosing namespace
1846 // internal::TriangulationImplementation
1847 using ::Triangulation;
1848
1854 int,
1855 << "Something went wrong upon construction of cell "
1856 << arg1);
1867 int,
1868 << "Cell " << arg1
1869 << " has negative measure. This typically "
1870 << "indicates some distortion in the cell, or a mistakenly "
1871 << "swapped pair of vertices in the input to "
1872 << "Triangulation::create_triangulation().");
1881 int,
1882 int,
1883 int,
1884 << "Error while creating cell " << arg1
1885 << ": the vertex index " << arg2 << " must be between 0 and "
1886 << arg3 << '.');
1893 int,
1894 int,
1896 << "The input data for creating a triangulation contained "
1897 << "information about a line with indices " << arg1 << " and " << arg2
1898 << " that is described to have boundary indicator "
1899 << static_cast<int>(arg3)
1900 << ". However, this is an internal line not located on the "
1901 << "boundary. You cannot assign a boundary indicator to it." << std::endl
1902 << std::endl
1903 << "If this happened at a place where you call "
1904 << "Triangulation::create_triangulation() yourself, you need "
1905 << "to check the SubCellData object you pass to this function."
1906 << std::endl
1907 << std::endl
1908 << "If this happened in a place where you are reading a mesh "
1909 << "from a file, then you need to investigate why such a line "
1910 << "ended up in the input file. A typical case is a geometry "
1911 << "that consisted of multiple parts and for which the mesh "
1912 << "generator program assumes that the interface between "
1913 << "two parts is a boundary when that isn't supposed to be "
1914 << "the case, or where the mesh generator simply assigns "
1915 << "'geometry indicators' to lines at the perimeter of "
1916 << "a part that are not supposed to be interpreted as "
1917 << "'boundary indicators'.");
1924 int,
1925 int,
1926 int,
1927 int,
1929 << "The input data for creating a triangulation contained "
1930 << "information about a quad with indices " << arg1 << ", " << arg2
1931 << ", " << arg3 << ", and " << arg4
1932 << " that is described to have boundary indicator "
1933 << static_cast<int>(arg5)
1934 << ". However, this is an internal quad not located on the "
1935 << "boundary. You cannot assign a boundary indicator to it." << std::endl
1936 << std::endl
1937 << "If this happened at a place where you call "
1938 << "Triangulation::create_triangulation() yourself, you need "
1939 << "to check the SubCellData object you pass to this function."
1940 << std::endl
1941 << std::endl
1942 << "If this happened in a place where you are reading a mesh "
1943 << "from a file, then you need to investigate why such a quad "
1944 << "ended up in the input file. A typical case is a geometry "
1945 << "that consisted of multiple parts and for which the mesh "
1946 << "generator program assumes that the interface between "
1947 << "two parts is a boundary when that isn't supposed to be "
1948 << "the case, or where the mesh generator simply assigns "
1949 << "'geometry indicators' to quads at the surface of "
1950 << "a part that are not supposed to be interpreted as "
1951 << "'boundary indicators'.");
1958 int,
1959 int,
1960 << "In SubCellData the line info of the line with vertex indices " << arg1
1961 << " and " << arg2 << " appears more than once. "
1962 << "This is not allowed.");
1969 int,
1970 int,
1971 std::string,
1972 << "In SubCellData the line info of the line with vertex indices " << arg1
1973 << " and " << arg2 << " appears multiple times with different (valid) "
1974 << arg3 << ". This is not allowed.");
1981 int,
1982 int,
1983 int,
1984 int,
1985 std::string,
1986 << "In SubCellData the quad info of the quad with line indices " << arg1
1987 << ", " << arg2 << ", " << arg3 << " and " << arg4
1988 << " appears multiple times with different (valid) " << arg5
1989 << ". This is not allowed.");
1990
1991 /*
1992 * Reserve space for TriaFaces. Details:
1993 *
1994 * Reserve space for line_orientations.
1995 *
1996 * @note Used only for dim=3.
1997 */
1998 void
2000 const unsigned int new_quads_in_pairs,
2001 const unsigned int new_quads_single)
2002 {
2003 AssertDimension(tria_faces.dim, 3);
2004
2005 Assert(new_quads_in_pairs % 2 == 0, ExcInternalError());
2006
2007 unsigned int next_free_single = 0;
2008 unsigned int next_free_pair = 0;
2009
2010 // count the number of objects, of unused single objects and of
2011 // unused pairs of objects
2012 unsigned int n_quads = 0;
2013 unsigned int n_unused_pairs = 0;
2014 unsigned int n_unused_singles = 0;
2015 for (unsigned int i = 0; i < tria_faces.quads.used.size(); ++i)
2016 {
2017 if (tria_faces.quads.used[i])
2018 ++n_quads;
2019 else if (i + 1 < tria_faces.quads.used.size())
2020 {
2021 if (tria_faces.quads.used[i + 1])
2022 {
2023 ++n_unused_singles;
2024 if (next_free_single == 0)
2025 next_free_single = i;
2026 }
2027 else
2028 {
2029 ++n_unused_pairs;
2030 if (next_free_pair == 0)
2031 next_free_pair = i;
2032 ++i;
2033 }
2034 }
2035 else
2036 ++n_unused_singles;
2037 }
2038 Assert(n_quads + 2 * n_unused_pairs + n_unused_singles ==
2039 tria_faces.quads.used.size(),
2041 (void)n_quads;
2042
2043 // how many single quads are needed in addition to n_unused_quads?
2044 const int additional_single_quads = new_quads_single - n_unused_singles;
2045
2046 unsigned int new_size =
2047 tria_faces.quads.used.size() + new_quads_in_pairs - 2 * n_unused_pairs;
2048 if (additional_single_quads > 0)
2049 new_size += additional_single_quads;
2050
2051 // see above...
2052 if (new_size > tria_faces.quads.n_objects())
2053 {
2054 // reserve the field of the derived class
2055 tria_faces.quads_line_orientations.resize(
2056 new_size * GeometryInfo<3>::lines_per_face, true);
2057
2058 auto &q_is_q = tria_faces.quad_is_quadrilateral;
2059 q_is_q.reserve(new_size);
2060 q_is_q.insert(q_is_q.end(), new_size - q_is_q.size(), true);
2061 }
2062 }
2063
2064
2065
2079 void
2081 const unsigned int total_cells,
2082 const unsigned int dimension,
2083 const unsigned int space_dimension,
2084 const bool tetraheder_in_mesh = false)
2085 {
2086 // we need space for total_cells cells. Maybe we have more already
2087 // with those cells which are unused, so only allocate new space if
2088 // needed.
2089 //
2090 // note that all arrays should have equal sizes (checked by
2091 // @p{monitor_memory}
2092 if (total_cells > tria_level.refine_flags.size())
2093 {
2094 tria_level.refine_flags.reserve(total_cells);
2095 tria_level.refine_flags.insert(tria_level.refine_flags.end(),
2096 total_cells -
2097 tria_level.refine_flags.size(),
2098 /*RefinementCase::no_refinement=*/0);
2099
2100 if (tetraheder_in_mesh)
2101 {
2102 tria_level.refine_choice.reserve(total_cells);
2103 tria_level.refine_choice.insert(
2104 tria_level.refine_choice.end(),
2105 total_cells - tria_level.refine_choice.size(),
2106 static_cast<char>(
2108 }
2109
2110 tria_level.coarsen_flags.reserve(total_cells);
2111 tria_level.coarsen_flags.insert(tria_level.coarsen_flags.end(),
2112 total_cells -
2113 tria_level.coarsen_flags.size(),
2114 false);
2115
2116 tria_level.active_cell_indices.reserve(total_cells);
2117 tria_level.active_cell_indices.insert(
2118 tria_level.active_cell_indices.end(),
2119 total_cells - tria_level.active_cell_indices.size(),
2121
2122 tria_level.subdomain_ids.reserve(total_cells);
2123 tria_level.subdomain_ids.insert(tria_level.subdomain_ids.end(),
2124 total_cells -
2125 tria_level.subdomain_ids.size(),
2126 0);
2127
2128 tria_level.level_subdomain_ids.reserve(total_cells);
2129 tria_level.level_subdomain_ids.insert(
2130 tria_level.level_subdomain_ids.end(),
2131 total_cells - tria_level.level_subdomain_ids.size(),
2132 0);
2133
2134 tria_level.global_active_cell_indices.reserve(total_cells);
2135 tria_level.global_active_cell_indices.insert(
2136 tria_level.global_active_cell_indices.end(),
2137 total_cells - tria_level.global_active_cell_indices.size(),
2139
2140 tria_level.global_level_cell_indices.reserve(total_cells);
2141 tria_level.global_level_cell_indices.insert(
2142 tria_level.global_level_cell_indices.end(),
2143 total_cells - tria_level.global_level_cell_indices.size(),
2145
2146 if (dimension == space_dimension - 1)
2147 {
2148 tria_level.direction_flags.reserve(total_cells);
2149 tria_level.direction_flags.insert(
2150 tria_level.direction_flags.end(),
2151 total_cells - tria_level.direction_flags.size(),
2152 true);
2153 }
2154 else
2155 tria_level.direction_flags.clear();
2156
2157 tria_level.parents.reserve((total_cells + 1) / 2);
2158 tria_level.parents.insert(tria_level.parents.end(),
2159 (total_cells + 1) / 2 -
2160 tria_level.parents.size(),
2161 -1);
2162
2163 tria_level.neighbors.reserve(total_cells * (2 * dimension));
2164 tria_level.neighbors.insert(tria_level.neighbors.end(),
2165 total_cells * (2 * dimension) -
2166 tria_level.neighbors.size(),
2167 std::make_pair(-1, -1));
2168
2169 if (tria_level.dim == 2 || tria_level.dim == 3)
2170 {
2171 const unsigned int max_faces_per_cell = 2 * dimension;
2172 tria_level.face_orientations.resize(total_cells *
2173 max_faces_per_cell);
2174
2175 tria_level.reference_cell.reserve(total_cells);
2176 tria_level.reference_cell.insert(
2177 tria_level.reference_cell.end(),
2178 total_cells - tria_level.reference_cell.size(),
2179 tria_level.dim == 2 ? ReferenceCells::Quadrilateral :
2181 }
2182 }
2183 }
2184
2185
2186
2191 int,
2192 int,
2193 << "The containers have sizes " << arg1 << " and " << arg2
2194 << ", which is not as expected.");
2195
2201 void
2202 monitor_memory(const TriaLevel &tria_level,
2203 const unsigned int true_dimension)
2204 {
2205 (void)tria_level;
2206 (void)true_dimension;
2207 Assert(2 * true_dimension * tria_level.refine_flags.size() ==
2208 tria_level.neighbors.size(),
2209 ExcMemoryInexact(tria_level.refine_flags.size(),
2210 tria_level.neighbors.size()));
2211 Assert(2 * true_dimension * tria_level.coarsen_flags.size() ==
2212 tria_level.neighbors.size(),
2213 ExcMemoryInexact(tria_level.coarsen_flags.size(),
2214 tria_level.neighbors.size()));
2215 }
2216
2217
2218
2231 void
2233 const unsigned int new_objects_in_pairs,
2234 const unsigned int new_objects_single = 0)
2235 {
2236 if (tria_objects.structdim <= 2)
2237 {
2238 Assert(new_objects_in_pairs % 2 == 0, ExcInternalError());
2239
2240 tria_objects.next_free_single = 0;
2241 tria_objects.next_free_pair = 0;
2242 tria_objects.reverse_order_next_free_single = false;
2243
2244 // count the number of objects, of unused single objects and of
2245 // unused pairs of objects
2246 unsigned int n_objects = 0;
2247 unsigned int n_unused_pairs = 0;
2248 unsigned int n_unused_singles = 0;
2249 for (unsigned int i = 0; i < tria_objects.used.size(); ++i)
2250 {
2251 if (tria_objects.used[i])
2252 ++n_objects;
2253 else if (i + 1 < tria_objects.used.size())
2254 {
2255 if (tria_objects.used[i + 1])
2256 {
2257 ++n_unused_singles;
2258 if (tria_objects.next_free_single == 0)
2259 tria_objects.next_free_single = i;
2260 }
2261 else
2262 {
2263 ++n_unused_pairs;
2264 if (tria_objects.next_free_pair == 0)
2265 tria_objects.next_free_pair = i;
2266 ++i;
2267 }
2268 }
2269 else
2270 ++n_unused_singles;
2271 }
2272 Assert(n_objects + 2 * n_unused_pairs + n_unused_singles ==
2273 tria_objects.used.size(),
2275 (void)n_objects;
2276
2277 // how many single objects are needed in addition to
2278 // n_unused_objects?
2279 const int additional_single_objects =
2280 new_objects_single - n_unused_singles;
2281
2282 unsigned int new_size = tria_objects.used.size() +
2283 new_objects_in_pairs - 2 * n_unused_pairs;
2284 if (additional_single_objects > 0)
2285 new_size += additional_single_objects;
2286
2287 // only allocate space if necessary
2288 if (new_size > tria_objects.n_objects())
2289 {
2290 const unsigned int max_faces_per_cell =
2291 2 * tria_objects.structdim;
2292 const unsigned int max_children_per_cell =
2293 1 << tria_objects.structdim;
2294
2295 tria_objects.cells.reserve(new_size * max_faces_per_cell);
2296 tria_objects.cells.insert(tria_objects.cells.end(),
2297 (new_size - tria_objects.n_objects()) *
2298 max_faces_per_cell,
2299 -1);
2300
2301 tria_objects.used.reserve(new_size);
2302 tria_objects.used.insert(tria_objects.used.end(),
2303 new_size - tria_objects.used.size(),
2304 false);
2305
2306 tria_objects.user_flags.reserve(new_size);
2307 tria_objects.user_flags.insert(tria_objects.user_flags.end(),
2308 new_size -
2309 tria_objects.user_flags.size(),
2310 false);
2311
2312 const unsigned int factor = max_children_per_cell / 2;
2313 tria_objects.children.reserve(factor * new_size);
2314 tria_objects.children.insert(tria_objects.children.end(),
2315 factor * new_size -
2316 tria_objects.children.size(),
2317 -1);
2318
2319 if (tria_objects.structdim > 1)
2320 {
2321 tria_objects.refinement_cases.reserve(new_size);
2322 tria_objects.refinement_cases.insert(
2323 tria_objects.refinement_cases.end(),
2324 new_size - tria_objects.refinement_cases.size(),
2325 /*RefinementCase::no_refinement=*/0);
2326 }
2327
2328 // first reserve, then resize. Otherwise the std library can
2329 // decide to allocate more entries.
2330 tria_objects.boundary_or_material_id.reserve(new_size);
2331 tria_objects.boundary_or_material_id.resize(new_size);
2332
2333 tria_objects.user_data.reserve(new_size);
2334 tria_objects.user_data.resize(new_size);
2335
2336 tria_objects.manifold_id.reserve(new_size);
2337 tria_objects.manifold_id.insert(tria_objects.manifold_id.end(),
2338 new_size -
2339 tria_objects.manifold_id.size(),
2341 }
2342
2343 if (n_unused_singles == 0)
2344 {
2345 tria_objects.next_free_single = new_size - 1;
2346 tria_objects.reverse_order_next_free_single = true;
2347 }
2348 }
2349 else
2350 {
2351 const unsigned int new_hexes = new_objects_in_pairs;
2352
2353 const unsigned int new_size =
2354 new_hexes + std::count(tria_objects.used.begin(),
2355 tria_objects.used.end(),
2356 true);
2357
2358 // see above...
2359 if (new_size > tria_objects.n_objects())
2360 {
2361 const unsigned int max_faces_per_cell =
2362 2 * tria_objects.structdim;
2363
2364 tria_objects.cells.reserve(new_size * max_faces_per_cell);
2365 tria_objects.cells.insert(tria_objects.cells.end(),
2366 (new_size - tria_objects.n_objects()) *
2367 max_faces_per_cell,
2368 -1);
2369
2370 tria_objects.used.reserve(new_size);
2371 tria_objects.used.insert(tria_objects.used.end(),
2372 new_size - tria_objects.used.size(),
2373 false);
2374
2375 tria_objects.user_flags.reserve(new_size);
2376 tria_objects.user_flags.insert(tria_objects.user_flags.end(),
2377 new_size -
2378 tria_objects.user_flags.size(),
2379 false);
2380
2381 tria_objects.children.reserve(4 * new_size);
2382 tria_objects.children.insert(tria_objects.children.end(),
2383 4 * new_size -
2384 tria_objects.children.size(),
2385 -1);
2386
2387 // for the following fields, we know exactly how many elements
2388 // we need, so first reserve then resize (resize itself, at least
2389 // with some compiler libraries, appears to round up the size it
2390 // actually reserves)
2391 tria_objects.boundary_or_material_id.reserve(new_size);
2392 tria_objects.boundary_or_material_id.resize(new_size);
2393
2394 tria_objects.manifold_id.reserve(new_size);
2395 tria_objects.manifold_id.insert(tria_objects.manifold_id.end(),
2396 new_size -
2397 tria_objects.manifold_id.size(),
2399
2400 tria_objects.user_data.reserve(new_size);
2401 tria_objects.user_data.resize(new_size);
2402
2403 tria_objects.refinement_cases.reserve(new_size);
2404 tria_objects.refinement_cases.insert(
2405 tria_objects.refinement_cases.end(),
2406 new_size - tria_objects.refinement_cases.size(),
2407 /*RefinementCase::no_refinement=*/0);
2408 }
2409 tria_objects.next_free_single = tria_objects.next_free_pair = 0;
2410 }
2411 }
2412
2413
2414
2420 void
2421 monitor_memory(const TriaObjects &tria_object, const unsigned int)
2422 {
2423 Assert(tria_object.n_objects() == tria_object.used.size(),
2424 ExcMemoryInexact(tria_object.n_objects(),
2425 tria_object.used.size()));
2426 Assert(tria_object.n_objects() == tria_object.user_flags.size(),
2427 ExcMemoryInexact(tria_object.n_objects(),
2428 tria_object.user_flags.size()));
2429 Assert(tria_object.n_objects() ==
2430 tria_object.boundary_or_material_id.size(),
2431 ExcMemoryInexact(tria_object.n_objects(),
2432 tria_object.boundary_or_material_id.size()));
2433 Assert(tria_object.n_objects() == tria_object.manifold_id.size(),
2434 ExcMemoryInexact(tria_object.n_objects(),
2435 tria_object.manifold_id.size()));
2436 Assert(tria_object.n_objects() == tria_object.user_data.size(),
2437 ExcMemoryInexact(tria_object.n_objects(),
2438 tria_object.user_data.size()));
2439
2440 if (tria_object.structdim == 1)
2441 {
2442 Assert(1 * tria_object.n_objects() == tria_object.children.size(),
2443 ExcMemoryInexact(tria_object.n_objects(),
2444 tria_object.children.size()));
2445 }
2446 else if (tria_object.structdim == 2)
2447 {
2448 Assert(2 * tria_object.n_objects() == tria_object.children.size(),
2449 ExcMemoryInexact(tria_object.n_objects(),
2450 tria_object.children.size()));
2451 }
2452 else if (tria_object.structdim == 3)
2453 {
2454 Assert(4 * tria_object.n_objects() == tria_object.children.size(),
2455 ExcMemoryInexact(tria_object.n_objects(),
2456 tria_object.children.size()));
2457 }
2458 }
2459
2460
2461
2466 template <int dim, int spacedim>
2468 {
2469 public:
2473 virtual ~Policy() = default;
2474
2478 virtual void
2480
2484 virtual void
2488 std::vector<unsigned int> &line_cell_count,
2489 std::vector<unsigned int> &quad_cell_count) = 0;
2490
2496 const bool check_for_distorted_cells) = 0;
2497
2501 virtual void
2504
2508 virtual void
2511
2515 virtual bool
2517 const typename Triangulation<dim, spacedim>::cell_iterator &cell) = 0;
2518
2525 virtual std::unique_ptr<Policy<dim, spacedim>>
2526 clone() = 0;
2527 };
2528
2529
2530
2536 template <int dim, int spacedim, typename T>
2537 class PolicyWrapper : public Policy<dim, spacedim>
2538 {
2539 public:
2540 void
2542 {
2543 T::update_neighbors(tria);
2544 }
2545
2546 void
2550 std::vector<unsigned int> &line_cell_count,
2551 std::vector<unsigned int> &quad_cell_count) override
2552 {
2553 T::delete_children(tria, cell, line_cell_count, quad_cell_count);
2554 }
2555
2558 const bool check_for_distorted_cells) override
2559 {
2560 return T::execute_refinement(triangulation, check_for_distorted_cells);
2561 }
2562
2563 void
2566 {
2567 T::prevent_distorted_boundary_cells(triangulation);
2568 }
2569
2570 void
2573 {
2574 T::prepare_refinement_dim_dependent(triangulation);
2575 }
2576
2577 bool
2580 override
2581 {
2582 return T::template coarsening_allowed<dim, spacedim>(cell);
2583 }
2584
2585 std::unique_ptr<Policy<dim, spacedim>>
2586 clone() override
2587 {
2588 return std::make_unique<PolicyWrapper<dim, spacedim, T>>();
2589 }
2590 };
2591
2592
2593
2690 {
2702 template <int dim, int spacedim>
2703 static void
2706 const unsigned int level_objects,
2708 {
2709 using line_iterator =
2711
2712 number_cache.n_levels = 0;
2713 if (level_objects > 0)
2714 // find the last level on which there are used cells
2715 for (unsigned int level = 0; level < level_objects; ++level)
2717 number_cache.n_levels = level + 1;
2718
2719 // no cells at all?
2720 Assert(number_cache.n_levels > 0, ExcInternalError());
2721
2722 //---------------------------------
2723 // update the number of lines on the different levels in the
2724 // cache
2725 number_cache.n_lines = 0;
2726 number_cache.n_active_lines = 0;
2727
2728 // for 1d, lines have levels so take count the objects per
2729 // level and globally
2730 if (dim == 1)
2731 {
2732 number_cache.n_lines_level.resize(number_cache.n_levels);
2733 number_cache.n_active_lines_level.resize(number_cache.n_levels);
2734
2735 for (unsigned int level = 0; level < number_cache.n_levels; ++level)
2736 {
2737 // count lines on this level
2738 number_cache.n_lines_level[level] = 0;
2739 number_cache.n_active_lines_level[level] = 0;
2740
2741 line_iterator line = triangulation.begin_line(level),
2742 endc =
2743 (level == number_cache.n_levels - 1 ?
2744 line_iterator(triangulation.end_line()) :
2746 for (; line != endc; ++line)
2747 {
2748 ++number_cache.n_lines_level[level];
2749 if (line->has_children() == false)
2750 ++number_cache.n_active_lines_level[level];
2751 }
2752
2753 // update total number of lines
2754 number_cache.n_lines += number_cache.n_lines_level[level];
2755 number_cache.n_active_lines +=
2756 number_cache.n_active_lines_level[level];
2757 }
2758 }
2759 else
2760 {
2761 // for dim>1, there are no levels for lines
2762 number_cache.n_lines_level.clear();
2763 number_cache.n_active_lines_level.clear();
2764
2765 line_iterator line = triangulation.begin_line(),
2766 endc = triangulation.end_line();
2767 for (; line != endc; ++line)
2768 {
2769 ++number_cache.n_lines;
2770 if (line->has_children() == false)
2771 ++number_cache.n_active_lines;
2772 }
2773 }
2774 }
2775
2790 template <int dim, int spacedim>
2791 static void
2794 const unsigned int level_objects,
2796 {
2797 // update lines and n_levels in number_cache. since we don't
2798 // access any of these numbers, we can do this in the
2799 // background
2801 static_cast<
2802 void (*)(const Triangulation<dim, spacedim> &,
2803 const unsigned int,
2807 level_objects,
2809 number_cache));
2810
2811 using quad_iterator =
2813
2814 //---------------------------------
2815 // update the number of quads on the different levels in the
2816 // cache
2817 number_cache.n_quads = 0;
2818 number_cache.n_active_quads = 0;
2819
2820 // for 2d, quads have levels so take count the objects per
2821 // level and globally
2822 if (dim == 2)
2823 {
2824 // count the number of levels; the function we called above
2825 // on a separate Task for lines also does this and puts it into
2826 // number_cache.n_levels, but this datum may not yet be
2827 // available as we call the function on a separate task
2828 unsigned int n_levels = 0;
2829 if (level_objects > 0)
2830 // find the last level on which there are used cells
2831 for (unsigned int level = 0; level < level_objects; ++level)
2833 n_levels = level + 1;
2834
2835 number_cache.n_quads_level.resize(n_levels);
2836 number_cache.n_active_quads_level.resize(n_levels);
2837
2838 for (unsigned int level = 0; level < n_levels; ++level)
2839 {
2840 // count quads on this level
2841 number_cache.n_quads_level[level] = 0;
2842 number_cache.n_active_quads_level[level] = 0;
2843
2844 quad_iterator quad = triangulation.begin_quad(level),
2845 endc =
2846 (level == n_levels - 1 ?
2847 quad_iterator(triangulation.end_quad()) :
2849 for (; quad != endc; ++quad)
2850 {
2851 ++number_cache.n_quads_level[level];
2852 if (quad->has_children() == false)
2853 ++number_cache.n_active_quads_level[level];
2854 }
2855
2856 // update total number of quads
2857 number_cache.n_quads += number_cache.n_quads_level[level];
2858 number_cache.n_active_quads +=
2859 number_cache.n_active_quads_level[level];
2860 }
2861 }
2862 else
2863 {
2864 // for dim>2, there are no levels for quads
2865 number_cache.n_quads_level.clear();
2866 number_cache.n_active_quads_level.clear();
2867
2868 quad_iterator quad = triangulation.begin_quad(),
2869 endc = triangulation.end_quad();
2870 for (; quad != endc; ++quad)
2871 {
2872 ++number_cache.n_quads;
2873 if (quad->has_children() == false)
2874 ++number_cache.n_active_quads;
2875 }
2876 }
2877
2878 // wait for the background computation for lines
2879 update_lines.join();
2880 }
2881
2897 template <int dim, int spacedim>
2898 static void
2901 const unsigned int level_objects,
2903 {
2904 // update quads, lines and n_levels in number_cache. since we
2905 // don't access any of these numbers, we can do this in the
2906 // background
2907 Threads::Task<void> update_quads_and_lines = Threads::new_task(
2908 static_cast<
2909 void (*)(const Triangulation<dim, spacedim> &,
2910 const unsigned int,
2914 level_objects,
2916 number_cache));
2917
2918 using hex_iterator =
2920
2921 //---------------------------------
2922 // update the number of hexes on the different levels in the
2923 // cache
2924 number_cache.n_hexes = 0;
2925 number_cache.n_active_hexes = 0;
2926
2927 // for 3d, hexes have levels so take count the objects per
2928 // level and globally
2929 if (dim == 3)
2930 {
2931 // count the number of levels; the function we called
2932 // above on a separate Task for quads (recursively, via
2933 // the lines function) also does this and puts it into
2934 // number_cache.n_levels, but this datum may not yet be
2935 // available as we call the function on a separate task
2936 unsigned int n_levels = 0;
2937 if (level_objects > 0)
2938 // find the last level on which there are used cells
2939 for (unsigned int level = 0; level < level_objects; ++level)
2941 n_levels = level + 1;
2942
2943 number_cache.n_hexes_level.resize(n_levels);
2944 number_cache.n_active_hexes_level.resize(n_levels);
2945
2946 for (unsigned int level = 0; level < n_levels; ++level)
2947 {
2948 // count hexes on this level
2949 number_cache.n_hexes_level[level] = 0;
2950 number_cache.n_active_hexes_level[level] = 0;
2951
2952 hex_iterator hex = triangulation.begin_hex(level),
2953 endc = (level == n_levels - 1 ?
2954 hex_iterator(triangulation.end_hex()) :
2956 for (; hex != endc; ++hex)
2957 {
2958 ++number_cache.n_hexes_level[level];
2959 if (hex->has_children() == false)
2960 ++number_cache.n_active_hexes_level[level];
2961 }
2962
2963 // update total number of hexes
2964 number_cache.n_hexes += number_cache.n_hexes_level[level];
2965 number_cache.n_active_hexes +=
2966 number_cache.n_active_hexes_level[level];
2967 }
2968 }
2969 else
2970 {
2971 // for dim>3, there are no levels for hexes
2972 number_cache.n_hexes_level.clear();
2973 number_cache.n_active_hexes_level.clear();
2974
2975 hex_iterator hex = triangulation.begin_hex(),
2976 endc = triangulation.end_hex();
2977 for (; hex != endc; ++hex)
2978 {
2979 ++number_cache.n_hexes;
2980 if (hex->has_children() == false)
2981 ++number_cache.n_active_hexes;
2982 }
2983 }
2984
2985 // wait for the background computation for quads
2986 update_quads_and_lines.join();
2987 }
2988
2989
2990 template <int dim, int spacedim>
2991 static void
2994 const unsigned int level_objects,
2996 {
2997 compute_number_cache_dim(triangulation, level_objects, number_cache);
2998
2999 number_cache.active_cell_index_partitioner =
3000 std::make_shared<const Utilities::MPI::Partitioner>(
3002
3003 number_cache.level_cell_index_partitioners.resize(
3005 for (unsigned int level = 0; level < triangulation.n_levels(); ++level)
3006 number_cache.level_cell_index_partitioners[level] =
3007 std::make_shared<const Utilities::MPI::Partitioner>(
3009 }
3010
3011
3012 template <int spacedim>
3013 static void
3016
3017
3018 template <int dim, int spacedim>
3019 static void
3021 {
3022 // each face can be neighbored on two sides
3023 // by cells. according to the face's
3024 // intrinsic normal we define the left
3025 // neighbor as the one for which the face
3026 // normal points outward, and store that
3027 // one first; the second one is then
3028 // the right neighbor for which the
3029 // face normal points inward. This
3030 // information depends on the type of cell
3031 // and local number of face for the
3032 // 'standard ordering and orientation' of
3033 // faces and then on the face_orientation
3034 // information for the real mesh. Set up a
3035 // table to have fast access to those
3036 // offsets (0 for left and 1 for
3037 // right). Some of the values are invalid
3038 // as they reference too large face
3039 // numbers, but we just leave them at a
3040 // zero value.
3041 //
3042 // Note, that in 2d for lines as faces the
3043 // normal direction given in the
3044 // GeometryInfo class is not consistent. We
3045 // thus define here that the normal for a
3046 // line points to the right if the line
3047 // points upwards.
3048 //
3049 // There is one more point to
3050 // consider, however: if we have
3051 // dim<spacedim, then we may have
3052 // cases where cells are
3053 // inverted. In effect, both
3054 // cells think they are the left
3055 // neighbor of an edge, for
3056 // example, which leads us to
3057 // forget neighborship
3058 // information (a case that shows
3059 // this is
3060 // codim_one/hanging_nodes_02). We
3061 // store whether a cell is
3062 // inverted using the
3063 // direction_flag, so if a cell
3064 // has a false direction_flag,
3065 // then we need to invert our
3066 // selection whether we are a
3067 // left or right neighbor in all
3068 // following computations.
3069 //
3070 // first index: dimension (minus 2)
3071 // second index: local face index
3072 // third index: face_orientation (false and true)
3073 static const unsigned int left_right_offset[2][6][2] = {
3074 // quadrilateral
3075 {{0, 1}, // face 0, face_orientation = false and true
3076 {1, 0}, // face 1, face_orientation = false and true
3077 {1, 0}, // face 2, face_orientation = false and true
3078 {0, 1}, // face 3, face_orientation = false and true
3079 {0, 0}, // face 4, invalid face
3080 {0, 0}}, // face 5, invalid face
3081 // hexahedron
3082 {{0, 1}, {1, 0}, {0, 1}, {1, 0}, {0, 1}, {1, 0}}};
3083
3084 // now create a vector of the two active
3085 // neighbors (left and right) for each face
3086 // and fill it by looping over all cells. For
3087 // cases with anisotropic refinement and more
3088 // then one cell neighboring at a given side
3089 // of the face we will automatically get the
3090 // active one on the highest level as we loop
3091 // over cells from lower levels first.
3093 std::vector<typename Triangulation<dim, spacedim>::cell_iterator>
3095
3096 for (const auto &cell : triangulation.cell_iterators())
3097 for (auto f : cell->face_indices())
3098 {
3100 cell->face(f);
3101
3102 const unsigned int offset =
3103 (cell->direction_flag() ?
3104 left_right_offset[dim - 2][f][cell->face_orientation(f)] :
3105 1 -
3106 left_right_offset[dim - 2][f][cell->face_orientation(f)]);
3107
3108 adjacent_cells[2 * face->index() + offset] = cell;
3109
3110 // if this cell is not refined, but the
3111 // face is, then we'll have to set our
3112 // cell as neighbor for the child faces
3113 // as well. Fortunately the normal
3114 // orientation of children will be just
3115 // the same.
3116 if (dim == 2)
3117 {
3118 if (cell->is_active() && face->has_children())
3119 {
3120 adjacent_cells[2 * face->child(0)->index() + offset] =
3121 cell;
3122 adjacent_cells[2 * face->child(1)->index() + offset] =
3123 cell;
3124 }
3125 }
3126 else // -> dim == 3
3127 {
3128 // We need the same as in 2d
3129 // here. Furthermore, if the face is
3130 // refined with cut_x or cut_y then
3131 // those children again in the other
3132 // direction, and if this cell is
3133 // refined isotropically (along the
3134 // face) then the neighbor will
3135 // (probably) be refined as cut_x or
3136 // cut_y along the face. For those
3137 // neighboring children cells, their
3138 // neighbor will be the current,
3139 // inactive cell, as our children are
3140 // too fine to be neighbors. Catch that
3141 // case by also acting on inactive
3142 // cells with isotropic refinement
3143 // along the face. If the situation
3144 // described is not present, the data
3145 // will be overwritten later on when we
3146 // visit cells on finer levels, so no
3147 // harm will be done.
3148 if (face->has_children() &&
3149 (cell->is_active() ||
3151 cell->refinement_case(), f) ==
3153 {
3154 for (unsigned int c = 0; c < face->n_children(); ++c)
3155 adjacent_cells[2 * face->child(c)->index() + offset] =
3156 cell;
3157 if (face->child(0)->has_children())
3158 {
3159 adjacent_cells[2 * face->child(0)->child(0)->index() +
3160 offset] = cell;
3161 adjacent_cells[2 * face->child(0)->child(1)->index() +
3162 offset] = cell;
3163 }
3164 if (face->child(1)->has_children())
3165 {
3166 adjacent_cells[2 * face->child(1)->child(0)->index() +
3167 offset] = cell;
3168 adjacent_cells[2 * face->child(1)->child(1)->index() +
3169 offset] = cell;
3170 }
3171 } // if cell active and face refined
3172 } // else -> dim==3
3173 } // for all faces of all cells
3174
3175 // now loop again over all cells and set the
3176 // corresponding neighbor cell. Note, that we
3177 // have to use the opposite of the
3178 // left_right_offset in this case as we want
3179 // the offset of the neighbor, not our own.
3180 for (const auto &cell : triangulation.cell_iterators())
3181 for (auto f : cell->face_indices())
3182 {
3183 const unsigned int offset =
3184 (cell->direction_flag() ?
3185 left_right_offset[dim - 2][f][cell->face_orientation(f)] :
3186 1 -
3187 left_right_offset[dim - 2][f][cell->face_orientation(f)]);
3188 cell->set_neighbor(
3189 f, adjacent_cells[2 * cell->face(f)->index() + 1 - offset]);
3190 }
3191 }
3192
3193
3197 template <int dim, int spacedim>
3198 static void
3200 const std::vector<CellData<dim>> &cells,
3201 const SubCellData &subcelldata,
3203 {
3204 AssertThrow(vertices.size() > 0, ExcMessage("No vertices given"));
3205 AssertThrow(cells.size() > 0, ExcMessage("No cells given"));
3206
3207 // Check that all cells have positive volume.
3208#ifndef _MSC_VER
3209 // TODO: The following code does not compile with MSVC. Find a way
3210 // around it
3211 if (dim == spacedim)
3212 for (unsigned int cell_no = 0; cell_no < cells.size(); ++cell_no)
3213 {
3214 // If we should check for distorted cells, then we permit them
3215 // to exist. If a cell has negative measure, then it must be
3216 // distorted (the converse is not necessarily true); hence
3217 // throw an exception if no such cells should exist.
3219 {
3220 const double cell_measure = GridTools::cell_measure<spacedim>(
3221 vertices,
3222 ArrayView<const unsigned int>(cells[cell_no].vertices));
3223 AssertThrow(cell_measure > 0, ExcGridHasInvalidCell(cell_no));
3224 }
3225 }
3226#endif
3227
3228 // clear old content
3229 tria.levels.clear();
3230 tria.levels.push_back(
3231 std::make_unique<
3233
3234 if (dim > 1)
3235 tria.faces = std::make_unique<
3237
3238 // copy vertices
3239 tria.vertices = vertices;
3240 tria.vertices_used.assign(vertices.size(), true);
3241
3242 // compute connectivity
3243 const auto connectivity = build_connectivity<unsigned int>(cells);
3244 const unsigned int n_cell = cells.size();
3245
3246 // TriaObjects: lines
3247 if (dim >= 2)
3248 {
3249 auto &lines_0 = tria.faces->lines; // data structure to be filled
3250
3251 // get connectivity between quads and lines
3252 const auto &crs = connectivity.entity_to_entities(1, 0);
3253 const unsigned int n_lines = crs.ptr.size() - 1;
3254
3255 // allocate memory
3256 reserve_space_(lines_0, n_lines);
3257
3258 // loop over lines
3259 for (unsigned int line = 0; line < n_lines; ++line)
3260 for (unsigned int i = crs.ptr[line], j = 0; i < crs.ptr[line + 1];
3261 ++i, ++j)
3262 lines_0.cells[line * GeometryInfo<1>::faces_per_cell + j] =
3263 crs.col[i]; // set vertex indices
3264 }
3265
3266 // TriaObjects: quads
3267 if (dim == 3)
3268 {
3269 auto &quads_0 = tria.faces->quads; // data structures to be filled
3270 auto &faces = *tria.faces;
3271
3272 // get connectivity between quads and lines
3273 const auto &crs = connectivity.entity_to_entities(2, 1);
3274 const unsigned int n_quads = crs.ptr.size() - 1;
3275
3276 // allocate memory
3277 reserve_space_(quads_0, n_quads);
3278 reserve_space_(faces, 2 /*structdim*/, n_quads);
3279
3280 // loop over all quads -> entity type, line indices/orientations
3281 for (unsigned int q = 0, k = 0; q < n_quads; ++q)
3282 {
3283 // set entity type of quads
3284 faces.set_quad_type(q, connectivity.entity_types(2)[q]);
3285
3286 // loop over all its lines
3287 for (unsigned int i = crs.ptr[q], j = 0; i < crs.ptr[q + 1];
3288 ++i, ++j, ++k)
3289 {
3290 // set line index
3291 quads_0.cells[q * GeometryInfo<3>::lines_per_face + j] =
3292 crs.col[i];
3293
3294 // set line orientations
3295 const unsigned char combined_orientation =
3296 connectivity.entity_orientations(1)
3297 .get_combined_orientation(k);
3298 // it doesn't make sense to set any flags except
3299 // orientation for a line
3300 Assert(
3301 combined_orientation ==
3303 combined_orientation ==
3306 faces.quads_line_orientations
3308 combined_orientation ==
3310 }
3311 }
3312 }
3313
3314 // TriaObjects/TriaLevel: cell
3315 {
3316 auto &cells_0 = tria.levels[0]->cells; // data structure to be filled
3317 auto &level = *tria.levels[0];
3318
3319 // get connectivity between cells/faces and cells/cells
3320 const auto &crs = connectivity.entity_to_entities(dim, dim - 1);
3321 const auto &nei = connectivity.entity_to_entities(dim, dim);
3322
3323 // in 2d optional: since in in pure QUAD meshes same line
3324 // orientations can be guaranteed
3325 bool orientation_needed = false;
3326 if (dim == 3)
3327 orientation_needed = true;
3328 else if (dim == 2)
3329 {
3330 const auto &orientations = connectivity.entity_orientations(1);
3331 for (unsigned int i = 0; i < orientations.n_objects(); ++i)
3332 if (orientations.get_combined_orientation(i) !=
3334 {
3335 orientation_needed = true;
3336 break;
3337 }
3338 }
3339
3340 // allocate memory
3341 reserve_space_(cells_0, n_cell);
3342 reserve_space_(level, spacedim, n_cell, orientation_needed);
3343
3344 // loop over all cells
3345 for (unsigned int cell = 0; cell < n_cell; ++cell)
3346 {
3347 // set material ids
3348 cells_0.boundary_or_material_id[cell].material_id =
3349 cells[cell].material_id;
3350
3351 // set manifold ids
3352 cells_0.manifold_id[cell] = cells[cell].manifold_id;
3353
3354 // set entity types
3355 level.reference_cell[cell] = connectivity.entity_types(dim)[cell];
3356
3357 // loop over faces
3358 for (unsigned int i = crs.ptr[cell], j = 0; i < crs.ptr[cell + 1];
3359 ++i, ++j)
3360 {
3361 // set neighbor if not at boundary
3362 if (nei.col[i] != static_cast<unsigned int>(-1))
3363 level.neighbors[cell * GeometryInfo<dim>::faces_per_cell +
3364 j] = {0, nei.col[i]};
3365
3366 // set face indices
3367 cells_0.cells[cell * GeometryInfo<dim>::faces_per_cell + j] =
3368 crs.col[i];
3369
3370 // set face orientation if needed
3371 if (orientation_needed)
3372 {
3373 level.face_orientations.set_combined_orientation(
3375 connectivity.entity_orientations(dim - 1)
3376 .get_combined_orientation(i));
3377 }
3378 }
3379 }
3380 }
3381
3382 // TriaFaces: boundary id of boundary faces
3383 if (dim > 1)
3384 {
3385 auto &bids_face = dim == 3 ?
3386 tria.faces->quads.boundary_or_material_id :
3387 tria.faces->lines.boundary_or_material_id;
3388
3389 // count number of cells a face is belonging to
3390 std::vector<unsigned int> count(bids_face.size(), 0);
3391
3392 // get connectivity between cells/faces
3393 const auto &crs = connectivity.entity_to_entities(dim, dim - 1);
3394
3395 // count how many cells are adjacent to the same face
3396 for (unsigned int cell = 0; cell < cells.size(); ++cell)
3397 for (unsigned int i = crs.ptr[cell]; i < crs.ptr[cell + 1]; ++i)
3398 count[crs.col[i]]++;
3399
3400 // loop over all faces
3401 for (unsigned int face = 0; face < count.size(); ++face)
3402 {
3403 if (count[face] != 1) // inner face
3404 continue;
3405
3406 // boundary faces ...
3407 bids_face[face].boundary_id = 0;
3408
3409 if (dim != 3)
3410 continue;
3411
3412 // ... and the lines of quads in 3d
3413 const auto &crs = connectivity.entity_to_entities(2, 1);
3414 for (unsigned int i = crs.ptr[face]; i < crs.ptr[face + 1]; ++i)
3415 tria.faces->lines.boundary_or_material_id[crs.col[i]]
3416 .boundary_id = 0;
3417 }
3418 }
3419 else // 1d
3420 {
3421 static const unsigned int t_tba = static_cast<unsigned int>(-1);
3422 static const unsigned int t_inner = static_cast<unsigned int>(-2);
3423
3424 std::vector<unsigned int> type(vertices.size(), t_tba);
3425
3426 const auto &crs = connectivity.entity_to_entities(1, 0);
3427
3428 for (unsigned int cell = 0; cell < cells.size(); ++cell)
3429 for (unsigned int i = crs.ptr[cell], j = 0; i < crs.ptr[cell + 1];
3430 ++i, ++j)
3431 if (type[crs.col[i]] != t_inner)
3432 type[crs.col[i]] = type[crs.col[i]] == t_tba ? j : t_inner;
3433
3434 for (unsigned int face = 0; face < type.size(); ++face)
3435 {
3436 // note: we also treat manifolds here!?
3437 (*tria.vertex_to_manifold_id_map_1d)[face] =
3439 if (type[face] != t_inner && type[face] != t_tba)
3440 (*tria.vertex_to_boundary_id_map_1d)[face] = type[face];
3441 }
3442 }
3443
3444 // SubCellData: line
3445 if (dim >= 2)
3446 process_subcelldata(connectivity.entity_to_entities(1, 0),
3447 tria.faces->lines,
3448 subcelldata.boundary_lines,
3449 vertices);
3450
3451 // SubCellData: quad
3452 if (dim == 3)
3453 process_subcelldata(connectivity.entity_to_entities(2, 0),
3454 tria.faces->quads,
3455 subcelldata.boundary_quads,
3456 vertices);
3457 }
3458
3459
3460 template <int structdim, int spacedim, typename T>
3461 static void
3463 const CRS<T> &crs,
3464 TriaObjects &obj,
3465 const std::vector<CellData<structdim>> &boundary_objects_in,
3466 const std::vector<Point<spacedim>> &vertex_locations)
3467 {
3468 AssertDimension(obj.structdim, structdim);
3469
3470 if (boundary_objects_in.empty())
3471 return; // empty subcelldata -> nothing to do
3472
3473 // pre-sort subcelldata
3474 auto boundary_objects = boundary_objects_in;
3475
3476 // ... sort vertices
3477 for (auto &boundary_object : boundary_objects)
3478 std::sort(boundary_object.vertices.begin(),
3479 boundary_object.vertices.end());
3480
3481 // ... sort cells
3482 std::sort(boundary_objects.begin(),
3483 boundary_objects.end(),
3484 [](const auto &a, const auto &b) {
3485 return a.vertices < b.vertices;
3486 });
3487
3488 unsigned int counter = 0;
3489
3490 std::vector<unsigned int> key;
3492
3493 for (unsigned int o = 0; o < obj.n_objects(); ++o)
3494 {
3495 auto &boundary_id = obj.boundary_or_material_id[o].boundary_id;
3496 auto &manifold_id = obj.manifold_id[o];
3497
3498 // assert that object has not been visited yet and its value
3499 // has not been modified yet
3500 AssertThrow(boundary_id == 0 ||
3505
3506 // create key
3507 key.assign(crs.col.data() + crs.ptr[o],
3508 crs.col.data() + crs.ptr[o + 1]);
3509 std::sort(key.begin(), key.end());
3510
3511 // is subcelldata provided? -> binary search
3512 const auto subcell_object =
3513 std::lower_bound(boundary_objects.begin(),
3514 boundary_objects.end(),
3515 key,
3516 [&](const auto &cell, const auto &key) {
3517 return cell.vertices < key;
3518 });
3519
3520 // no subcelldata provided for this object
3521 if (subcell_object == boundary_objects.end() ||
3522 subcell_object->vertices != key)
3523 continue;
3524
3525 ++counter;
3526
3527 // set manifold id
3528 manifold_id = subcell_object->manifold_id;
3529
3530 // set boundary id
3531 if (subcell_object->boundary_id !=
3533 {
3534 (void)vertex_locations;
3537 ExcMessage(
3538 "The input arguments for creating a triangulation "
3539 "specified a boundary id for an internal face. This "
3540 "is not allowed."
3541 "\n\n"
3542 "The object in question has vertex indices " +
3543 [subcell_object]() {
3544 std::string s;
3545 for (const auto v : subcell_object->vertices)
3546 s += std::to_string(v) + ',';
3547 return s;
3548 }() +
3549 " which are located at positions " +
3550 [vertex_locations, subcell_object]() {
3551 std::ostringstream s;
3552 for (const auto v : subcell_object->vertices)
3553 s << '(' << vertex_locations[v] << ')';
3554 return s.str();
3555 }() +
3556 "."));
3557 boundary_id = subcell_object->boundary_id;
3558 }
3559 }
3560
3561 // make sure that all subcelldata entries have been processed
3562 // TODO: this is not guaranteed, why?
3563 // AssertDimension(counter, boundary_objects_in.size());
3564 (void)counter;
3565 }
3566
3567
3568
3569 static void
3571 const unsigned structdim,
3572 const unsigned int size)
3573 {
3574 const unsigned int dim = faces.dim;
3575
3576 const unsigned int max_lines_per_face = 2 * structdim;
3577
3578 if (dim == 3 && structdim == 2)
3579 {
3580 // quad entity types
3581 faces.quad_is_quadrilateral.assign(size, true);
3582
3583 // quad line orientations
3584 faces.quads_line_orientations.assign(size * max_lines_per_face,
3585 true);
3586 }
3587 }
3588
3589
3590
3591 static void
3593 const unsigned int spacedim,
3594 const unsigned int size,
3595 const bool orientation_needed)
3596 {
3597 const unsigned int dim = level.dim;
3598
3599 const unsigned int max_faces_per_cell = 2 * dim;
3600
3601 level.active_cell_indices.assign(size, numbers::invalid_unsigned_int);
3602 level.subdomain_ids.assign(size, 0);
3603 level.level_subdomain_ids.assign(size, 0);
3604
3605 level.refine_flags.assign(size, 0u);
3606 level.refine_choice.assign(size, 0u);
3607 level.coarsen_flags.assign(size, false);
3608
3609 level.parents.assign((size + 1) / 2, -1);
3610
3611 if (dim == spacedim - 1)
3612 level.direction_flags.assign(size, true);
3613
3614 level.neighbors.assign(size * max_faces_per_cell, {-1, -1});
3615
3616 level.reference_cell.assign(size, ReferenceCells::Invalid);
3617
3618 if (orientation_needed)
3619 level.face_orientations.reinit(size * max_faces_per_cell);
3620
3621
3622 level.global_active_cell_indices.assign(size,
3624 level.global_level_cell_indices.assign(size,
3626 }
3627
3628
3629
3630 static void
3631 reserve_space_(TriaObjects &obj, const unsigned int size)
3632 {
3633 const unsigned int structdim = obj.structdim;
3634
3635 const unsigned int max_children_per_cell = 1 << structdim;
3636 const unsigned int max_faces_per_cell = 2 * structdim;
3637
3638 obj.used.assign(size, true);
3639 obj.boundary_or_material_id.assign(
3640 size,
3642 BoundaryOrMaterialId());
3643 obj.manifold_id.assign(size, -1);
3644 obj.user_flags.assign(size, false);
3645 obj.user_data.resize(size);
3646
3647 if (structdim > 1) // TODO: why?
3648 obj.refinement_cases.assign(size, 0);
3649
3650 obj.children.assign(max_children_per_cell / 2 * size, -1);
3651
3652 obj.cells.assign(max_faces_per_cell * size, -1);
3653
3654 if (structdim <= 2)
3655 {
3656 obj.next_free_single = size - 1;
3657 obj.next_free_pair = 0;
3659 }
3660 else
3661 {
3662 obj.next_free_single = obj.next_free_pair = 0;
3663 }
3664 }
3665
3666
3682 template <int spacedim>
3683 static void
3686 std::vector<unsigned int> &,
3687 std::vector<unsigned int> &)
3688 {
3689 const unsigned int dim = 1;
3690
3691 // first we need to reset the
3692 // neighbor pointers of the
3693 // neighbors of this cell's
3694 // children to this cell. This is
3695 // different for one dimension,
3696 // since there neighbors can have a
3697 // refinement level differing from
3698 // that of this cell's children by
3699 // more than one level.
3700
3701 Assert(!cell->child(0)->has_children() &&
3702 !cell->child(1)->has_children(),
3704
3705 // first do it for the cells to the
3706 // left
3707 if (cell->neighbor(0).state() == IteratorState::valid)
3708 if (cell->neighbor(0)->has_children())
3709 {
3711 cell->neighbor(0);
3712 Assert(neighbor->level() == cell->level(), ExcInternalError());
3713
3714 // right child
3715 neighbor = neighbor->child(1);
3716 while (true)
3717 {
3718 Assert(neighbor->neighbor(1) == cell->child(0),
3720 neighbor->set_neighbor(1, cell);
3721
3722 // move on to further
3723 // children on the
3724 // boundary between this
3725 // cell and its neighbor
3726 if (neighbor->has_children())
3727 neighbor = neighbor->child(1);
3728 else
3729 break;
3730 }
3731 }
3732
3733 // now do it for the cells to the
3734 // left
3735 if (cell->neighbor(1).state() == IteratorState::valid)
3736 if (cell->neighbor(1)->has_children())
3737 {
3739 cell->neighbor(1);
3740 Assert(neighbor->level() == cell->level(), ExcInternalError());
3741
3742 // left child
3743 neighbor = neighbor->child(0);
3744 while (true)
3745 {
3746 Assert(neighbor->neighbor(0) == cell->child(1),
3748 neighbor->set_neighbor(0, cell);
3749
3750 // move on to further
3751 // children on the
3752 // boundary between this
3753 // cell and its neighbor
3754 if (neighbor->has_children())
3755 neighbor = neighbor->child(0);
3756 else
3757 break;
3758 }
3759 }
3760
3761
3762 // delete the vertex which will not
3763 // be needed anymore. This vertex
3764 // is the second of the first child
3765 triangulation.vertices_used[cell->child(0)->vertex_index(1)] = false;
3766
3767 // invalidate children. clear user
3768 // pointers, to avoid that they may
3769 // appear at unwanted places later
3770 // on...
3771 for (unsigned int child = 0; child < cell->n_children(); ++child)
3772 {
3773 cell->child(child)->clear_user_data();
3774 cell->child(child)->clear_user_flag();
3775 cell->child(child)->clear_used_flag();
3776 }
3777
3778
3779 // delete pointer to children
3780 cell->clear_children();
3781 cell->clear_user_flag();
3782 }
3783
3784
3785
3786 template <int spacedim>
3787 static void
3790 std::vector<unsigned int> &line_cell_count,
3791 std::vector<unsigned int> &)
3792 {
3793 const unsigned int dim = 2;
3794 const RefinementCase<dim> ref_case = cell->refinement_case();
3795
3796 Assert(line_cell_count.size() == triangulation.n_raw_lines(),
3798
3799 // vectors to hold all lines which
3800 // may be deleted
3801 std::vector<typename Triangulation<dim, spacedim>::line_iterator>
3802 lines_to_delete(0);
3803
3804 lines_to_delete.reserve(4 * 2 + 4);
3805
3806 // now we decrease the counters for
3807 // lines contained in the child
3808 // cells
3809 for (unsigned int c = 0; c < cell->n_children(); ++c)
3810 {
3812 cell->child(c);
3813 for (unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++l)
3814 --line_cell_count[child->line_index(l)];
3815 }
3816
3817
3818 // delete the vertex which will not
3819 // be needed anymore. This vertex
3820 // is the second of the second line
3821 // of the first child, if the cell
3822 // is refined with cut_xy, else there
3823 // is no inner vertex.
3824 // additionally delete unneeded inner
3825 // lines
3826 if (ref_case == RefinementCase<dim>::cut_xy)
3827 {
3829 .vertices_used[cell->child(0)->line(1)->vertex_index(1)] = false;
3830
3831 lines_to_delete.push_back(cell->child(0)->line(1));
3832 lines_to_delete.push_back(cell->child(0)->line(3));
3833 lines_to_delete.push_back(cell->child(3)->line(0));
3834 lines_to_delete.push_back(cell->child(3)->line(2));
3835 }
3836 else
3837 {
3838 unsigned int inner_face_no =
3839 ref_case == RefinementCase<dim>::cut_x ? 1 : 3;
3840
3841 // the inner line will not be
3842 // used any more
3843 lines_to_delete.push_back(cell->child(0)->line(inner_face_no));
3844 }
3845
3846 // invalidate children
3847 for (unsigned int child = 0; child < cell->n_children(); ++child)
3848 {
3849 cell->child(child)->clear_user_data();
3850 cell->child(child)->clear_user_flag();
3851 cell->child(child)->clear_used_flag();
3852 }
3853
3854
3855 // delete pointer to children
3856 cell->clear_children();
3857 cell->clear_refinement_case();
3858 cell->clear_user_flag();
3859
3860 // look at the refinement of outer
3861 // lines. if nobody needs those
3862 // anymore we can add them to the
3863 // list of lines to be deleted.
3864 for (unsigned int line_no = 0;
3865 line_no < GeometryInfo<dim>::lines_per_cell;
3866 ++line_no)
3867 {
3869 cell->line(line_no);
3870
3871 if (line->has_children())
3872 {
3873 // if one of the cell counters is
3874 // zero, the other has to be as well
3875
3876 Assert((line_cell_count[line->child_index(0)] == 0 &&
3877 line_cell_count[line->child_index(1)] == 0) ||
3878 (line_cell_count[line->child_index(0)] > 0 &&
3879 line_cell_count[line->child_index(1)] > 0),
3881
3882 if (line_cell_count[line->child_index(0)] == 0)
3883 {
3884 for (unsigned int c = 0; c < 2; ++c)
3885 Assert(!line->child(c)->has_children(),
3887
3888 // we may delete the line's
3889 // children and the middle vertex
3890 // as no cell references them
3891 // anymore
3893 .vertices_used[line->child(0)->vertex_index(1)] = false;
3894
3895 lines_to_delete.push_back(line->child(0));
3896 lines_to_delete.push_back(line->child(1));
3897
3898 line->clear_children();
3899 }
3900 }
3901 }
3902
3903 // finally, delete unneeded lines
3904
3905 // clear user pointers, to avoid that
3906 // they may appear at unwanted places
3907 // later on...
3908 // same for user flags, then finally
3909 // delete the lines
3910 typename std::vector<
3912 line = lines_to_delete.begin(),
3913 endline = lines_to_delete.end();
3914 for (; line != endline; ++line)
3915 {
3916 (*line)->clear_user_data();
3917 (*line)->clear_user_flag();
3918 (*line)->clear_used_flag();
3919 }
3920 }
3921
3922
3923
3924 template <int spacedim>
3925 static void
3928 std::vector<unsigned int> &line_cell_count,
3929 std::vector<unsigned int> &quad_cell_count)
3930 {
3931 const unsigned int dim = 3;
3932
3933 Assert(line_cell_count.size() == triangulation.n_raw_lines(),
3935 Assert(quad_cell_count.size() == triangulation.n_raw_quads(),
3937
3938 // first of all, we store the RefineCase of
3939 // this cell
3940 const RefinementCase<dim> ref_case = cell->refinement_case();
3941 // vectors to hold all lines and quads which
3942 // may be deleted
3943 std::vector<typename Triangulation<dim, spacedim>::line_iterator>
3944 lines_to_delete(0);
3945 std::vector<typename Triangulation<dim, spacedim>::quad_iterator>
3946 quads_to_delete(0);
3947
3948 lines_to_delete.reserve(12 * 2 + 6 * 4 + 6);
3949 quads_to_delete.reserve(6 * 4 + 12);
3950
3951 // now we decrease the counters for lines and
3952 // quads contained in the child cells
3953 for (unsigned int c = 0; c < cell->n_children(); ++c)
3954 {
3956 cell->child(c);
3957 const auto line_indices = TriaAccessorImplementation::
3958 Implementation::get_line_indices_of_cell(*child);
3959 for (const unsigned int l : cell->line_indices())
3960 --line_cell_count[line_indices[l]];
3961 for (auto f : GeometryInfo<dim>::face_indices())
3962 --quad_cell_count[child->quad_index(f)];
3963 }
3964
3965 //-------------------------------------
3966 // delete interior quads and lines and the
3967 // interior vertex, depending on the
3968 // refinement case of the cell
3969 //
3970 // for append quads and lines: only append
3971 // them to the list of objects to be deleted
3972
3973 switch (ref_case)
3974 {
3976 quads_to_delete.push_back(cell->child(0)->face(1));
3977 break;
3979 quads_to_delete.push_back(cell->child(0)->face(3));
3980 break;
3982 quads_to_delete.push_back(cell->child(0)->face(5));
3983 break;
3985 quads_to_delete.push_back(cell->child(0)->face(1));
3986 quads_to_delete.push_back(cell->child(0)->face(3));
3987 quads_to_delete.push_back(cell->child(3)->face(0));
3988 quads_to_delete.push_back(cell->child(3)->face(2));
3989
3990 lines_to_delete.push_back(cell->child(0)->line(11));
3991 break;
3993 quads_to_delete.push_back(cell->child(0)->face(1));
3994 quads_to_delete.push_back(cell->child(0)->face(5));
3995 quads_to_delete.push_back(cell->child(3)->face(0));
3996 quads_to_delete.push_back(cell->child(3)->face(4));
3997
3998 lines_to_delete.push_back(cell->child(0)->line(5));
3999 break;
4001 quads_to_delete.push_back(cell->child(0)->face(3));
4002 quads_to_delete.push_back(cell->child(0)->face(5));
4003 quads_to_delete.push_back(cell->child(3)->face(2));
4004 quads_to_delete.push_back(cell->child(3)->face(4));
4005
4006 lines_to_delete.push_back(cell->child(0)->line(7));
4007 break;
4009 quads_to_delete.push_back(cell->child(0)->face(1));
4010 quads_to_delete.push_back(cell->child(2)->face(1));
4011 quads_to_delete.push_back(cell->child(4)->face(1));
4012 quads_to_delete.push_back(cell->child(6)->face(1));
4013
4014 quads_to_delete.push_back(cell->child(0)->face(3));
4015 quads_to_delete.push_back(cell->child(1)->face(3));
4016 quads_to_delete.push_back(cell->child(4)->face(3));
4017 quads_to_delete.push_back(cell->child(5)->face(3));
4018
4019 quads_to_delete.push_back(cell->child(0)->face(5));
4020 quads_to_delete.push_back(cell->child(1)->face(5));
4021 quads_to_delete.push_back(cell->child(2)->face(5));
4022 quads_to_delete.push_back(cell->child(3)->face(5));
4023
4024 lines_to_delete.push_back(cell->child(0)->line(5));
4025 lines_to_delete.push_back(cell->child(0)->line(7));
4026 lines_to_delete.push_back(cell->child(0)->line(11));
4027 lines_to_delete.push_back(cell->child(7)->line(0));
4028 lines_to_delete.push_back(cell->child(7)->line(2));
4029 lines_to_delete.push_back(cell->child(7)->line(8));
4030 // delete the vertex which will not
4031 // be needed anymore. This vertex
4032 // is the vertex at the heart of
4033 // this cell, which is the sixth of
4034 // the first child
4035 triangulation.vertices_used[cell->child(0)->vertex_index(7)] =
4036 false;
4037 break;
4038 default:
4039 // only remaining case is
4040 // no_refinement, thus an error
4042 break;
4043 }
4044
4045
4046 // invalidate children
4047 for (unsigned int child = 0; child < cell->n_children(); ++child)
4048 {
4049 cell->child(child)->clear_user_data();
4050 cell->child(child)->clear_user_flag();
4051
4052 for (auto f : GeometryInfo<dim>::face_indices())
4053 // set flags denoting deviations from standard orientation of
4054 // faces back to initialization values
4055 cell->child(child)->set_combined_face_orientation(
4057
4058 cell->child(child)->clear_used_flag();
4059 }
4060
4061
4062 // delete pointer to children
4063 cell->clear_children();
4064 cell->clear_refinement_case();
4065 cell->clear_user_flag();
4066
4067 // so far we only looked at inner quads,
4068 // lines and vertices. Now we have to
4069 // consider outer ones as well. here, we have
4070 // to check, whether there are other cells
4071 // still needing these objects. otherwise we
4072 // can delete them. first for quads (and
4073 // their inner lines).
4074
4075 for (const unsigned int quad_no : GeometryInfo<dim>::face_indices())
4076 {
4078 cell->face(quad_no);
4079
4080 Assert(
4081 (GeometryInfo<dim>::face_refinement_case(ref_case, quad_no) &&
4082 quad->has_children()) ||
4083 GeometryInfo<dim>::face_refinement_case(ref_case, quad_no) ==
4086
4087 switch (quad->refinement_case())
4088 {
4089 case RefinementCase<dim - 1>::no_refinement:
4090 // nothing to do as the quad
4091 // is not refined
4092 break;
4093 case RefinementCase<dim - 1>::cut_x:
4094 case RefinementCase<dim - 1>::cut_y:
4095 {
4096 // if one of the cell counters is
4097 // zero, the other has to be as
4098 // well
4099 Assert((quad_cell_count[quad->child_index(0)] == 0 &&
4100 quad_cell_count[quad->child_index(1)] == 0) ||
4101 (quad_cell_count[quad->child_index(0)] > 0 &&
4102 quad_cell_count[quad->child_index(1)] > 0),
4104 // it might be, that the quad is
4105 // refined twice anisotropically,
4106 // first check, whether we may
4107 // delete possible grand_children
4108 unsigned int deleted_grandchildren = 0;
4109 unsigned int number_of_child_refinements = 0;
4110
4111 for (unsigned int c = 0; c < 2; ++c)
4112 if (quad->child(c)->has_children())
4113 {
4114 ++number_of_child_refinements;
4115 // if one of the cell counters is
4116 // zero, the other has to be as
4117 // well
4118 Assert(
4119 (quad_cell_count[quad->child(c)->child_index(0)] ==
4120 0 &&
4121 quad_cell_count[quad->child(c)->child_index(1)] ==
4122 0) ||
4123 (quad_cell_count[quad->child(c)->child_index(0)] >
4124 0 &&
4125 quad_cell_count[quad->child(c)->child_index(1)] >
4126 0),
4128 if (quad_cell_count[quad->child(c)->child_index(0)] ==
4129 0)
4130 {
4131 // Assert, that the two
4132 // anisotropic
4133 // refinements add up to
4134 // isotropic refinement
4135 Assert(quad->refinement_case() +
4136 quad->child(c)->refinement_case() ==
4139 // we may delete the
4140 // quad's children and
4141 // the inner line as no
4142 // cell references them
4143 // anymore
4144 quads_to_delete.push_back(
4145 quad->child(c)->child(0));
4146 quads_to_delete.push_back(
4147 quad->child(c)->child(1));
4148 if (quad->child(c)->refinement_case() ==
4150 lines_to_delete.push_back(
4151 quad->child(c)->child(0)->line(1));
4152 else
4153 lines_to_delete.push_back(
4154 quad->child(c)->child(0)->line(3));
4155 quad->child(c)->clear_children();
4156 quad->child(c)->clear_refinement_case();
4157 ++deleted_grandchildren;
4158 }
4159 }
4160 // if no grandchildren are left, we
4161 // may as well delete the
4162 // refinement of the inner line
4163 // between our children and the
4164 // corresponding vertex
4165 if (number_of_child_refinements > 0 &&
4166 deleted_grandchildren == number_of_child_refinements)
4167 {
4169 middle_line;
4170 if (quad->refinement_case() == RefinementCase<2>::cut_x)
4171 middle_line = quad->child(0)->line(1);
4172 else
4173 middle_line = quad->child(0)->line(3);
4174
4175 lines_to_delete.push_back(middle_line->child(0));
4176 lines_to_delete.push_back(middle_line->child(1));
4178 .vertices_used[middle_vertex_index<dim, spacedim>(
4179 middle_line)] = false;
4180 middle_line->clear_children();
4181 }
4182
4183 // now consider the direct children
4184 // of the given quad
4185 if (quad_cell_count[quad->child_index(0)] == 0)
4186 {
4187 // we may delete the quad's
4188 // children and the inner line
4189 // as no cell references them
4190 // anymore
4191 quads_to_delete.push_back(quad->child(0));
4192 quads_to_delete.push_back(quad->child(1));
4193 if (quad->refinement_case() == RefinementCase<2>::cut_x)
4194 lines_to_delete.push_back(quad->child(0)->line(1));
4195 else
4196 lines_to_delete.push_back(quad->child(0)->line(3));
4197
4198 // if the counters just dropped
4199 // to zero, otherwise the
4200 // children would have been
4201 // deleted earlier, then this
4202 // cell's children must have
4203 // contained the anisotropic
4204 // quad children. thus, if
4205 // those have again anisotropic
4206 // children, which are in
4207 // effect isotropic children of
4208 // the original quad, those are
4209 // still needed by a
4210 // neighboring cell and we
4211 // cannot delete them. instead,
4212 // we have to reset this quad's
4213 // refine case to isotropic and
4214 // set the children
4215 // accordingly.
4216 if (quad->child(0)->has_children())
4217 if (quad->refinement_case() ==
4219 {
4220 // now evereything is
4221 // quite complicated. we
4222 // have the children
4223 // numbered according to
4224 //
4225 // *---*---*
4226 // |n+1|m+1|
4227 // *---*---*
4228 // | n | m |
4229 // *---*---*
4230 //
4231 // from the original
4232 // anisotropic
4233 // refinement. we have to
4234 // reorder them as
4235 //
4236 // *---*---*
4237 // | m |m+1|
4238 // *---*---*
4239 // | n |n+1|
4240 // *---*---*
4241 //
4242 // for isotropic refinement.
4243 //
4244 // this is a bit ugly, of
4245 // course: loop over all
4246 // cells on all levels
4247 // and look for faces n+1
4248 // (switch_1) and m
4249 // (switch_2).
4250 const typename Triangulation<dim, spacedim>::
4251 quad_iterator switch_1 =
4252 quad->child(0)->child(1),
4253 switch_2 =
4254 quad->child(1)->child(0);
4255
4256 Assert(!switch_1->has_children(),
4258 Assert(!switch_2->has_children(),
4260
4261 const int switch_1_index = switch_1->index();
4262 const int switch_2_index = switch_2->index();
4263 for (unsigned int l = 0;
4264 l < triangulation.levels.size();
4265 ++l)
4266 for (unsigned int h = 0;
4267 h <
4268 triangulation.levels[l]->cells.n_objects();
4269 ++h)
4270 for (const unsigned int q :
4272 {
4273 const int index =
4275 ->cells.get_bounding_object_indices(
4276 h)[q];
4277 if (index == switch_1_index)
4279 ->cells.get_bounding_object_indices(
4280 h)[q] = switch_2_index;
4281 else if (index == switch_2_index)
4283 ->cells.get_bounding_object_indices(
4284 h)[q] = switch_1_index;
4285 }
4286 // now we have to copy
4287 // all information of the
4288 // two quads
4289 const int switch_1_lines[4] = {
4290 static_cast<signed int>(
4291 switch_1->line_index(0)),
4292 static_cast<signed int>(
4293 switch_1->line_index(1)),
4294 static_cast<signed int>(
4295 switch_1->line_index(2)),
4296 static_cast<signed int>(
4297 switch_1->line_index(3))};
4298 const bool switch_1_line_orientations[4] = {
4299 switch_1->line_orientation(0),
4300 switch_1->line_orientation(1),
4301 switch_1->line_orientation(2),
4302 switch_1->line_orientation(3)};
4303 const types::boundary_id switch_1_boundary_id =
4304 switch_1->boundary_id();
4305 const unsigned int switch_1_user_index =
4306 switch_1->user_index();
4307 const bool switch_1_user_flag =
4308 switch_1->user_flag_set();
4309
4310 switch_1->set_bounding_object_indices(
4311 {switch_2->line_index(0),
4312 switch_2->line_index(1),
4313 switch_2->line_index(2),
4314 switch_2->line_index(3)});
4315 switch_1->set_line_orientation(
4316 0, switch_2->line_orientation(0));
4317 switch_1->set_line_orientation(
4318 1, switch_2->line_orientation(1));
4319 switch_1->set_line_orientation(
4320 2, switch_2->line_orientation(2));
4321 switch_1->set_line_orientation(
4322 3, switch_2->line_orientation(3));
4323 switch_1->set_boundary_id_internal(
4324 switch_2->boundary_id());
4325 switch_1->set_manifold_id(
4326 switch_2->manifold_id());
4327 switch_1->set_user_index(switch_2->user_index());
4328 if (switch_2->user_flag_set())
4329 switch_1->set_user_flag();
4330 else
4331 switch_1->clear_user_flag();
4332
4333 switch_2->set_bounding_object_indices(
4334 {switch_1_lines[0],
4335 switch_1_lines[1],
4336 switch_1_lines[2],
4337 switch_1_lines[3]});
4338 switch_2->set_line_orientation(
4339 0, switch_1_line_orientations[0]);
4340 switch_2->set_line_orientation(
4341 1, switch_1_line_orientations[1]);
4342 switch_2->set_line_orientation(
4343 2, switch_1_line_orientations[2]);
4344 switch_2->set_line_orientation(
4345 3, switch_1_line_orientations[3]);
4346 switch_2->set_boundary_id_internal(
4347 switch_1_boundary_id);
4348 switch_2->set_manifold_id(
4349 switch_1->manifold_id());
4350 switch_2->set_user_index(switch_1_user_index);
4351 if (switch_1_user_flag)
4352 switch_2->set_user_flag();
4353 else
4354 switch_2->clear_user_flag();
4355
4356 const unsigned int child_0 =
4357 quad->child(0)->child_index(0);
4358 const unsigned int child_2 =
4359 quad->child(1)->child_index(0);
4360 quad->clear_children();
4361 quad->clear_refinement_case();
4362 quad->set_refinement_case(
4364 quad->set_children(0, child_0);
4365 quad->set_children(2, child_2);
4366 std::swap(quad_cell_count[child_0 + 1],
4367 quad_cell_count[child_2]);
4368 }
4369 else
4370 {
4371 // the face was refined
4372 // with cut_y, thus the
4373 // children are already
4374 // in correct order. we
4375 // only have to set them
4376 // correctly, deleting
4377 // the indirection of two
4378 // anisotropic refinement
4379 // and going directly
4380 // from the quad to
4381 // isotropic children
4382 const unsigned int child_0 =
4383 quad->child(0)->child_index(0);
4384 const unsigned int child_2 =
4385 quad->child(1)->child_index(0);
4386 quad->clear_children();
4387 quad->clear_refinement_case();
4388 quad->set_refinement_case(
4390 quad->set_children(0, child_0);
4391 quad->set_children(2, child_2);
4392 }
4393 else
4394 {
4395 quad->clear_children();
4396 quad->clear_refinement_case();
4397 }
4398 }
4399 break;
4400 }
4401 case RefinementCase<dim - 1>::cut_xy:
4402 {
4403 // if one of the cell counters is
4404 // zero, the others have to be as
4405 // well
4406
4407 Assert((quad_cell_count[quad->child_index(0)] == 0 &&
4408 quad_cell_count[quad->child_index(1)] == 0 &&
4409 quad_cell_count[quad->child_index(2)] == 0 &&
4410 quad_cell_count[quad->child_index(3)] == 0) ||
4411 (quad_cell_count[quad->child_index(0)] > 0 &&
4412 quad_cell_count[quad->child_index(1)] > 0 &&
4413 quad_cell_count[quad->child_index(2)] > 0 &&
4414 quad_cell_count[quad->child_index(3)] > 0),
4416
4417 if (quad_cell_count[quad->child_index(0)] == 0)
4418 {
4419 // we may delete the quad's
4420 // children, the inner lines
4421 // and the middle vertex as no
4422 // cell references them anymore
4423 lines_to_delete.push_back(quad->child(0)->line(1));
4424 lines_to_delete.push_back(quad->child(3)->line(0));
4425 lines_to_delete.push_back(quad->child(0)->line(3));
4426 lines_to_delete.push_back(quad->child(3)->line(2));
4427
4428 for (unsigned int child = 0; child < quad->n_children();
4429 ++child)
4430 quads_to_delete.push_back(quad->child(child));
4431
4433 .vertices_used[quad->child(0)->vertex_index(3)] =
4434 false;
4435
4436 quad->clear_children();
4437 quad->clear_refinement_case();
4438 }
4439 }
4440 break;
4441
4442 default:
4444 break;
4445 }
4446 }
4447
4448 // now we repeat a similar procedure
4449 // for the outer lines of this cell.
4450
4451 // if in debug mode: check that each
4452 // of the lines for which we consider
4453 // deleting the children in fact has
4454 // children (the bits/coarsening_3d
4455 // test tripped over this initially)
4456 for (unsigned int line_no = 0;
4457 line_no < GeometryInfo<dim>::lines_per_cell;
4458 ++line_no)
4459 {
4461 cell->line(line_no);
4462
4463 Assert(
4464 (GeometryInfo<dim>::line_refinement_case(ref_case, line_no) &&
4465 line->has_children()) ||
4466 GeometryInfo<dim>::line_refinement_case(ref_case, line_no) ==
4469
4470 if (line->has_children())
4471 {
4472 // if one of the cell counters is
4473 // zero, the other has to be as well
4474
4475 Assert((line_cell_count[line->child_index(0)] == 0 &&
4476 line_cell_count[line->child_index(1)] == 0) ||
4477 (line_cell_count[line->child_index(0)] > 0 &&
4478 line_cell_count[line->child_index(1)] > 0),
4480
4481 if (line_cell_count[line->child_index(0)] == 0)
4482 {
4483 for (unsigned int c = 0; c < 2; ++c)
4484 Assert(!line->child(c)->has_children(),
4486
4487 // we may delete the line's
4488 // children and the middle vertex
4489 // as no cell references them
4490 // anymore
4492 .vertices_used[line->child(0)->vertex_index(1)] = false;
4493
4494 lines_to_delete.push_back(line->child(0));
4495 lines_to_delete.push_back(line->child(1));
4496
4497 line->clear_children();
4498 }
4499 }
4500 }
4501
4502 // finally, delete unneeded quads and lines
4503
4504 // clear user pointers, to avoid that
4505 // they may appear at unwanted places
4506 // later on...
4507 // same for user flags, then finally
4508 // delete the quads and lines
4509 typename std::vector<
4511 line = lines_to_delete.begin(),
4512 endline = lines_to_delete.end();
4513 for (; line != endline; ++line)
4514 {
4515 (*line)->clear_user_data();
4516 (*line)->clear_user_flag();
4517 (*line)->clear_used_flag();
4518 }
4519
4520 typename std::vector<
4522 quad = quads_to_delete.begin(),
4523 endquad = quads_to_delete.end();
4524 for (; quad != endquad; ++quad)
4525 {
4526 (*quad)->clear_user_data();
4527 (*quad)->clear_children();
4528 (*quad)->clear_refinement_case();
4529 (*quad)->clear_user_flag();
4530 (*quad)->clear_used_flag();
4531 }
4532 }
4533
4534
4552 template <int spacedim>
4553 static void
4556 unsigned int &next_unused_vertex,
4558 &next_unused_line,
4560 &next_unused_cell,
4561 const typename Triangulation<2, spacedim>::cell_iterator &cell)
4562 {
4563 const unsigned int dim = 2;
4564 // clear refinement flag
4565 const RefinementCase<dim> ref_case = cell->refine_flag_set();
4566 cell->clear_refine_flag();
4567
4568 /* For the refinement process: since we go the levels up from the
4569 lowest, there are (unlike above) only two possibilities: a neighbor
4570 cell is on the same level or one level up (in both cases, it may or
4571 may not be refined later on, but we don't care here).
4572
4573 First:
4574 Set up an array of the 3x3 vertices, which are distributed on the
4575 cell (the array consists of indices into the @p{vertices} std::vector
4576
4577 2--7--3
4578 | | |
4579 4--8--5
4580 | | |
4581 0--6--1
4582
4583 note: in case of cut_x or cut_y not all these vertices are needed for
4584 the new cells
4585
4586 Second:
4587 Set up an array of the new lines (the array consists of iterator
4588 pointers into the lines arrays)
4589
4590 .-6-.-7-. The directions are: .->-.->-.
4591 1 9 3 ^ ^ ^
4592 .-10.11-. .->-.->-.
4593 0 8 2 ^ ^ ^
4594 .-4-.-5-. .->-.->-.
4595
4596 cut_x:
4597 .-4-.-5-.
4598 | | |
4599 0 6 1
4600 | | |
4601 .-2-.-3-.
4602
4603 cut_y:
4604 .---5---.
4605 1 3
4606 .---6---.
4607 0 2
4608 .---4---.
4609
4610
4611 Third:
4612 Set up an array of neighbors:
4613
4614 6 7
4615 .--.--.
4616 1| | |3
4617 .--.--.
4618 0| | |2
4619 .--.--.
4620 4 5
4621
4622 We need this array for two reasons: first to get the lines which will
4623 bound the four subcells (if the neighboring cell is refined, these
4624 lines already exist), and second to update neighborship information.
4625 Since if a neighbor is not refined, its neighborship record only
4626 points to the present, unrefined, cell rather than the children we
4627 are presently creating, we only need the neighborship information
4628 if the neighbor cells are refined. In all other cases, we store
4629 the unrefined neighbor address
4630
4631 We also need for every neighbor (if refined) which number among its
4632 neighbors the present (unrefined) cell has, since that number is to
4633 be replaced and because that also is the number of the subline which
4634 will be the interface between that neighbor and the to be created
4635 cell. We will store this number (between 0 and 3) in the field
4636 @p{neighbors_neighbor}.
4637
4638 It would be sufficient to use the children of the common line to the
4639 neighbor, if we only wanted to get the new sublines and the new
4640 vertex, but because we need to update the neighborship information of
4641 the two refined subcells of the neighbor, we need to search these
4642 anyway.
4643
4644 Convention:
4645 The created children are numbered like this:
4646
4647 .--.--.
4648 |2 . 3|
4649 .--.--.
4650 |0 | 1|
4651 .--.--.
4652 */
4653 // collect the indices of the eight surrounding vertices
4654 // 2--7--3
4655 // | | |
4656 // 4--8--5
4657 // | | |
4658 // 0--6--1
4659 int new_vertices[9];
4660 for (unsigned int vertex_no = 0; vertex_no < 4; ++vertex_no)
4661 new_vertices[vertex_no] = cell->vertex_index(vertex_no);
4662 for (unsigned int line_no = 0; line_no < 4; ++line_no)
4663 if (cell->line(line_no)->has_children())
4664 new_vertices[4 + line_no] =
4665 cell->line(line_no)->child(0)->vertex_index(1);
4666
4667 if (ref_case == RefinementCase<dim>::cut_xy)
4668 {
4669 // find the next
4670 // unused vertex and
4671 // allocate it for
4672 // the new vertex we
4673 // need here
4674 while (triangulation.vertices_used[next_unused_vertex] == true)
4675 ++next_unused_vertex;
4676 Assert(next_unused_vertex < triangulation.vertices.size(),
4677 ExcMessage(
4678 "Internal error: During refinement, the triangulation "
4679 "wants to access an element of the 'vertices' array "
4680 "but it turns out that the array is not large enough."));
4681 triangulation.vertices_used[next_unused_vertex] = true;
4682
4683 new_vertices[8] = next_unused_vertex;
4684
4685 // determine middle vertex by transfinite interpolation to be
4686 // consistent with what happens to quads in a
4687 // Triangulation<3,3> when they are refined
4688 triangulation.vertices[next_unused_vertex] =
4689 cell->center(true, true);
4690 }
4691
4692
4693 // Now the lines:
4695 unsigned int lmin = 8;
4696 unsigned int lmax = 12;
4697 if (ref_case != RefinementCase<dim>::cut_xy)
4698 {
4699 lmin = 6;
4700 lmax = 7;
4701 }
4702
4703 for (unsigned int l = lmin; l < lmax; ++l)
4704 {
4705 while (next_unused_line->used() == true)
4706 ++next_unused_line;
4707 new_lines[l] = next_unused_line;
4708 ++next_unused_line;
4709
4710 AssertIsNotUsed(new_lines[l]);
4711 }
4712
4713 if (ref_case == RefinementCase<dim>::cut_xy)
4714 {
4715 // .-6-.-7-.
4716 // 1 9 3
4717 // .-10.11-.
4718 // 0 8 2
4719 // .-4-.-5-.
4720
4721 // lines 0-7 already exist, create only the four interior
4722 // lines 8-11
4723 unsigned int l = 0;
4724 for (const unsigned int face_no : GeometryInfo<dim>::face_indices())
4725 for (unsigned int c = 0; c < 2; ++c, ++l)
4726 new_lines[l] = cell->line(face_no)->child(c);
4727 Assert(l == 8, ExcInternalError());
4728
4729 new_lines[8]->set_bounding_object_indices(
4730 {new_vertices[6], new_vertices[8]});
4731 new_lines[9]->set_bounding_object_indices(
4732 {new_vertices[8], new_vertices[7]});
4733 new_lines[10]->set_bounding_object_indices(
4734 {new_vertices[4], new_vertices[8]});
4735 new_lines[11]->set_bounding_object_indices(
4736 {new_vertices[8], new_vertices[5]});
4737 }
4738 else if (ref_case == RefinementCase<dim>::cut_x)
4739 {
4740 // .-4-.-5-.
4741 // | | |
4742 // 0 6 1
4743 // | | |
4744 // .-2-.-3-.
4745 new_lines[0] = cell->line(0);
4746 new_lines[1] = cell->line(1);
4747 new_lines[2] = cell->line(2)->child(0);
4748 new_lines[3] = cell->line(2)->child(1);
4749 new_lines[4] = cell->line(3)->child(0);
4750 new_lines[5] = cell->line(3)->child(1);
4751 new_lines[6]->set_bounding_object_indices(
4752 {new_vertices[6], new_vertices[7]});
4753 }
4754 else
4755 {
4757 // .---5---.
4758 // 1 3
4759 // .---6---.
4760 // 0 2
4761 // .---4---.
4762 new_lines[0] = cell->line(0)->child(0);
4763 new_lines[1] = cell->line(0)->child(1);
4764 new_lines[2] = cell->line(1)->child(0);
4765 new_lines[3] = cell->line(1)->child(1);
4766 new_lines[4] = cell->line(2);
4767 new_lines[5] = cell->line(3);
4768 new_lines[6]->set_bounding_object_indices(
4769 {new_vertices[4], new_vertices[5]});
4770 }
4771
4772 for (unsigned int l = lmin; l < lmax; ++l)
4773 {
4774 new_lines[l]->set_used_flag();
4775 new_lines[l]->clear_user_flag();
4776 new_lines[l]->clear_user_data();
4777 new_lines[l]->clear_children();
4778 // interior line
4779 new_lines[l]->set_boundary_id_internal(
4781 new_lines[l]->set_manifold_id(cell->manifold_id());
4782 }
4783
4784 // Now add the four (two)
4785 // new cells!
4788 while (next_unused_cell->used() == true)
4789 ++next_unused_cell;
4790
4791 const unsigned int n_children = GeometryInfo<dim>::n_children(ref_case);
4792 for (unsigned int i = 0; i < n_children; ++i)
4793 {
4794 AssertIsNotUsed(next_unused_cell);
4795 subcells[i] = next_unused_cell;
4796 ++next_unused_cell;
4797 if (i % 2 == 1 && i < n_children - 1)
4798 while (next_unused_cell->used() == true)
4799 ++next_unused_cell;
4800 }
4801
4802 if (ref_case == RefinementCase<dim>::cut_xy)
4803 {
4804 // children:
4805 // .--.--.
4806 // |2 . 3|
4807 // .--.--.
4808 // |0 | 1|
4809 // .--.--.
4810 // lines:
4811 // .-6-.-7-.
4812 // 1 9 3
4813 // .-10.11-.
4814 // 0 8 2
4815 // .-4-.-5-.
4816 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
4817 new_lines[8]->index(),
4818 new_lines[4]->index(),
4819 new_lines[10]->index()});
4820 subcells[1]->set_bounding_object_indices({new_lines[8]->index(),
4821 new_lines[2]->index(),
4822 new_lines[5]->index(),
4823 new_lines[11]->index()});
4824 subcells[2]->set_bounding_object_indices({new_lines[1]->index(),
4825 new_lines[9]->index(),
4826 new_lines[10]->index(),
4827 new_lines[6]->index()});
4828 subcells[3]->set_bounding_object_indices({new_lines[9]->index(),
4829 new_lines[3]->index(),
4830 new_lines[11]->index(),
4831 new_lines[7]->index()});
4832 }
4833 else if (ref_case == RefinementCase<dim>::cut_x)
4834 {
4835 // children:
4836 // .--.--.
4837 // | . |
4838 // .0 . 1.
4839 // | | |
4840 // .--.--.
4841 // lines:
4842 // .-4-.-5-.
4843 // | | |
4844 // 0 6 1
4845 // | | |
4846 // .-2-.-3-.
4847 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
4848 new_lines[6]->index(),
4849 new_lines[2]->index(),
4850 new_lines[4]->index()});
4851 subcells[1]->set_bounding_object_indices({new_lines[6]->index(),
4852 new_lines[1]->index(),
4853 new_lines[3]->index(),
4854 new_lines[5]->index()});
4855 }
4856 else
4857 {
4859 // children:
4860 // .-----.
4861 // | 1 |
4862 // .-----.
4863 // | 0 |
4864 // .-----.
4865 // lines:
4866 // .---5---.
4867 // 1 3
4868 // .---6---.
4869 // 0 2
4870 // .---4---.
4871 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
4872 new_lines[2]->index(),
4873 new_lines[4]->index(),
4874 new_lines[6]->index()});
4875 subcells[1]->set_bounding_object_indices({new_lines[1]->index(),
4876 new_lines[3]->index(),
4877 new_lines[6]->index(),
4878 new_lines[5]->index()});
4879 }
4880
4881 types::subdomain_id subdomainid = cell->subdomain_id();
4882
4883 for (unsigned int i = 0; i < n_children; ++i)
4884 {
4885 subcells[i]->set_used_flag();
4886 subcells[i]->clear_refine_flag();
4887 subcells[i]->clear_user_flag();
4888 subcells[i]->clear_user_data();
4889 subcells[i]->clear_children();
4890 // inherit material properties
4891 subcells[i]->set_material_id(cell->material_id());
4892 subcells[i]->set_manifold_id(cell->manifold_id());
4893 subcells[i]->set_subdomain_id(subdomainid);
4894
4895 if (i % 2 == 0)
4896 subcells[i]->set_parent(cell->index());
4897 }
4898
4899
4900
4901 // set child index for even children i=0,2 (0)
4902 for (unsigned int i = 0; i < n_children / 2; ++i)
4903 cell->set_children(2 * i, subcells[2 * i]->index());
4904 // set the refine case
4905 cell->set_refinement_case(ref_case);
4906
4907 // note that the
4908 // refinement flag was
4909 // already cleared at the
4910 // beginning of this function
4911
4912 if (dim == spacedim - 1)
4913 for (unsigned int c = 0; c < n_children; ++c)
4914 cell->child(c)->set_direction_flag(cell->direction_flag());
4915 }
4916
4917
4918
4919 template <int dim, int spacedim>
4922 const bool check_for_distorted_cells)
4923 {
4924 AssertDimension(dim, 2);
4925
4926 // Check whether a new level is needed. We have to check for
4927 // this on the highest level only
4928 for (const auto &cell : triangulation.active_cell_iterators_on_level(
4929 triangulation.levels.size() - 1))
4930 if (cell->refine_flag_set())
4931 {
4932 triangulation.levels.push_back(
4933 std::make_unique<
4935 break;
4936 }
4937
4940 line != triangulation.end_line();
4941 ++line)
4942 {
4943 line->clear_user_flag();
4944 line->clear_user_data();
4945 }
4946
4947 unsigned int n_single_lines = 0;
4948 unsigned int n_lines_in_pairs = 0;
4949 unsigned int needed_vertices = 0;
4950
4951 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
4952 {
4953 // count number of flagged cells on this level and compute
4954 // how many new vertices and new lines will be needed
4955 unsigned int needed_cells = 0;
4956
4957 for (const auto &cell :
4959 if (cell->refine_flag_set())
4960 {
4961 if (cell->reference_cell() == ReferenceCells::Triangle)
4962 {
4963 needed_cells += 4;
4964 needed_vertices += 0;
4965 n_single_lines += 3;
4966 }
4967 else if (cell->reference_cell() ==
4969 {
4970 needed_cells += 4;
4971 needed_vertices += 1;
4972 n_single_lines += 4;
4973 }
4974 else
4975 {
4977 }
4978
4979 for (const auto line_no : cell->face_indices())
4980 {
4981 auto line = cell->line(line_no);
4982 if (line->has_children() == false)
4983 line->set_user_flag();
4984 }
4985 }
4986
4987
4988 const unsigned int used_cells =
4989 std::count(triangulation.levels[level + 1]->cells.used.begin(),
4990 triangulation.levels[level + 1]->cells.used.end(),
4991 true);
4992
4993
4995 used_cells + needed_cells,
4996 2,
4997 spacedim);
4998
5000 needed_cells,
5001 0);
5002 }
5003
5004 for (auto line = triangulation.begin_line();
5005 line != triangulation.end_line();
5006 ++line)
5007 if (line->user_flag_set())
5008 {
5009 Assert(line->has_children() == false, ExcInternalError());
5010 n_lines_in_pairs += 2;
5011 needed_vertices += 1;
5012 }
5013
5014 reserve_space(triangulation.faces->lines, n_lines_in_pairs, 0);
5015
5016 needed_vertices += std::count(triangulation.vertices_used.begin(),
5018 true);
5019
5020 if (needed_vertices > triangulation.vertices.size())
5021 {
5022 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
5023 triangulation.vertices_used.resize(needed_vertices, false);
5024 }
5025
5026 unsigned int next_unused_vertex = 0;
5027
5028 {
5031 endl = triangulation.end_line();
5033 next_unused_line = triangulation.begin_raw_line();
5034
5035 for (; line != endl; ++line)
5036 if (line->user_flag_set())
5037 {
5038 // This line needs to be refined. Find the next unused vertex
5039 // and set it appropriately
5040 while (triangulation.vertices_used[next_unused_vertex] == true)
5041 ++next_unused_vertex;
5042 Assert(next_unused_vertex < triangulation.vertices.size(),
5043 ExcMessage(
5044 "Internal error: During refinement, the triangulation "
5045 "wants to access an element of the 'vertices' array "
5046 "but it turns out that the array is not large "
5047 "enough."));
5048 triangulation.vertices_used[next_unused_vertex] = true;
5049
5050 triangulation.vertices[next_unused_vertex] = line->center(true);
5051
5052 bool pair_found = false;
5053 (void)pair_found;
5054 for (; next_unused_line != endl; ++next_unused_line)
5055 if (!next_unused_line->used() &&
5056 !(++next_unused_line)->used())
5057 {
5058 --next_unused_line;
5059 pair_found = true;
5060 break;
5061 }
5062 Assert(pair_found, ExcInternalError());
5063
5064 line->set_children(0, next_unused_line->index());
5065
5067 children[2] = {next_unused_line, ++next_unused_line};
5068
5069 AssertIsNotUsed(children[0]);
5070 AssertIsNotUsed(children[1]);
5071
5072 children[0]->set_bounding_object_indices(
5073 {line->vertex_index(0), next_unused_vertex});
5074 children[1]->set_bounding_object_indices(
5075 {next_unused_vertex, line->vertex_index(1)});
5076
5077 for (auto &child : children)
5078 {
5079 child->set_used_flag();
5080 child->clear_children();
5081 child->clear_user_data();
5082 child->clear_user_flag();
5083 child->set_boundary_id_internal(line->boundary_id());
5084 child->set_manifold_id(line->manifold_id());
5085 // Line orientation is relative to the cell it is on so
5086 // those cannot be set at this point.
5087 }
5088
5089 line->clear_user_flag();
5090 }
5091 }
5092
5093 reserve_space(triangulation.faces->lines, 0, n_single_lines);
5094
5096 cells_with_distorted_children;
5097
5099 next_unused_line = triangulation.begin_raw_line();
5100
5101 const auto create_children = [](auto &triangulation,
5102 unsigned int &next_unused_vertex,
5103 auto &next_unused_line,
5104 auto &next_unused_cell,
5105 const auto &cell) {
5106 const auto ref_case = cell->refine_flag_set();
5107 cell->clear_refine_flag();
5108
5109 unsigned int n_new_vertices = 0;
5110
5111 if (cell->reference_cell() == ReferenceCells::Triangle)
5112 n_new_vertices = 6;
5113 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5114 n_new_vertices = 9;
5115 else
5117
5118 std::vector<unsigned int> new_vertices(n_new_vertices,
5120 for (unsigned int vertex_no = 0; vertex_no < cell->n_vertices();
5121 ++vertex_no)
5122 new_vertices[vertex_no] = cell->vertex_index(vertex_no);
5123 for (unsigned int line_no = 0; line_no < cell->n_lines(); ++line_no)
5124 if (cell->line(line_no)->has_children())
5125 new_vertices[cell->n_vertices() + line_no] =
5126 cell->line(line_no)->child(0)->vertex_index(1);
5127
5128 if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5129 {
5130 while (triangulation.vertices_used[next_unused_vertex] == true)
5131 ++next_unused_vertex;
5132 Assert(
5133 next_unused_vertex < triangulation.vertices.size(),
5134 ExcMessage(
5135 "Internal error: During refinement, the triangulation wants "
5136 "to access an element of the 'vertices' array but it turns "
5137 "out that the array is not large enough."));
5138 triangulation.vertices_used[next_unused_vertex] = true;
5139
5140 new_vertices[8] = next_unused_vertex;
5141
5142 triangulation.vertices[next_unused_vertex] =
5143 cell->center(true, true);
5144 }
5145
5146 std::array<typename Triangulation<dim, spacedim>::raw_line_iterator,
5147 12>
5148 new_lines;
5149 std::array<unsigned char, 12> inherited_orientations;
5150 inherited_orientations.fill(
5152 unsigned int lmin = 0;
5153 unsigned int lmax = 0;
5154
5155 if (cell->reference_cell() == ReferenceCells::Triangle)
5156 {
5157 lmin = 6;
5158 lmax = 9;
5159 // For triangles, the innermost faces are always reversed for the
5160 // first three children and are in the standard orientation for
5161 // the last one.
5162 std::fill(inherited_orientations.begin() + lmin,
5163 inherited_orientations.begin() + lmax,
5165 }
5166 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5167 {
5168 lmin = 8;
5169 lmax = 12;
5170 }
5171 else
5172 {
5174 }
5175
5176 for (unsigned int l = lmin; l < lmax; ++l)
5177 {
5178 while (next_unused_line->used() == true)
5179 ++next_unused_line;
5180 new_lines[l] = next_unused_line;
5181 ++next_unused_line;
5182
5183 AssertIsNotUsed(new_lines[l]);
5184 }
5185
5186 // set up lines which have parents:
5187 for (const unsigned int face_no : cell->face_indices())
5188 {
5189 // Check the face (line) orientation to ensure that the (six or
5190 // eight) outer lines in new_lines are indexed in the default
5191 // orientation. This way we can index into this array in the
5192 // without special casing orientations (e.g., quadrilateral child
5193 // 3 will always have lines 9, 3, 11, 7) when setting child lines.
5194 const unsigned char combined_orientation =
5195 cell->combined_face_orientation(face_no);
5196 Assert(combined_orientation ==
5198 combined_orientation ==
5201 for (unsigned int c = 0; c < 2; ++c)
5202 {
5203 new_lines[2 * face_no + c] = cell->line(face_no)->child(c);
5204 inherited_orientations[2 * face_no + c] =
5205 cell->combined_face_orientation(face_no);
5206 }
5207 if (combined_orientation ==
5209 std::swap(new_lines[2 * face_no], new_lines[2 * face_no + 1]);
5210 }
5211
5212 // set up lines which do not have parents:
5213 if (cell->reference_cell() == ReferenceCells::Triangle)
5214 {
5215 new_lines[6]->set_bounding_object_indices(
5216 {new_vertices[3], new_vertices[4]});
5217 new_lines[7]->set_bounding_object_indices(
5218 {new_vertices[4], new_vertices[5]});
5219 new_lines[8]->set_bounding_object_indices(
5220 {new_vertices[5], new_vertices[3]});
5221 }
5222 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5223 {
5224 new_lines[8]->set_bounding_object_indices(
5225 {new_vertices[6], new_vertices[8]});
5226 new_lines[9]->set_bounding_object_indices(
5227 {new_vertices[8], new_vertices[7]});
5228 new_lines[10]->set_bounding_object_indices(
5229 {new_vertices[4], new_vertices[8]});
5230 new_lines[11]->set_bounding_object_indices(
5231 {new_vertices[8], new_vertices[5]});
5232 }
5233 else
5234 {
5236 }
5237
5238 for (unsigned int l = lmin; l < lmax; ++l)
5239 {
5240 new_lines[l]->set_used_flag();
5241 new_lines[l]->clear_user_flag();
5242 new_lines[l]->clear_user_data();
5243 new_lines[l]->clear_children();
5244 // new lines are always internal.
5245 new_lines[l]->set_boundary_id_internal(
5247 new_lines[l]->set_manifold_id(cell->manifold_id());
5248 }
5249
5252 while (next_unused_cell->used() == true)
5253 ++next_unused_cell;
5254
5255 unsigned int n_children = 0;
5256 if (cell->reference_cell() == ReferenceCells::Triangle)
5257 n_children = 4;
5258 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5259 n_children = 4;
5260 else
5262
5263 for (unsigned int i = 0; i < n_children; ++i)
5264 {
5265 AssertIsNotUsed(next_unused_cell);
5266 subcells[i] = next_unused_cell;
5267 ++next_unused_cell;
5268 if (i % 2 == 1 && i < n_children - 1)
5269 while (next_unused_cell->used() == true)
5270 ++next_unused_cell;
5271 }
5272
5273 // Assign lines to child cells:
5274 constexpr unsigned int X = numbers::invalid_unsigned_int;
5275 static constexpr ::ndarray<unsigned int, 4, 4> tri_child_lines =
5276 {{{{0, 8, 5, X}}, {{1, 2, 6, X}}, {{7, 3, 4, X}}, {{6, 7, 8, X}}}};
5277 static constexpr ::ndarray<unsigned int, 4, 4>
5278 quad_child_lines = {{{{0, 8, 4, 10}},
5279 {{8, 2, 5, 11}},
5280 {{1, 9, 10, 6}},
5281 {{9, 3, 11, 7}}}};
5282 // Here and below we assume that child cells have the same reference
5283 // cell type as the parent.
5284 const auto &child_lines =
5285 cell->reference_cell() == ReferenceCells::Triangle ?
5286 tri_child_lines :
5287 quad_child_lines;
5288 for (unsigned int i = 0; i < n_children; ++i)
5289 {
5290 if (cell->reference_cell() == ReferenceCells::Triangle)
5291 subcells[i]->set_bounding_object_indices(
5292 {new_lines[child_lines[i][0]]->index(),
5293 new_lines[child_lines[i][1]]->index(),
5294 new_lines[child_lines[i][2]]->index()});
5295 else
5296 subcells[i]->set_bounding_object_indices(
5297 {new_lines[child_lines[i][0]]->index(),
5298 new_lines[child_lines[i][1]]->index(),
5299 new_lines[child_lines[i][2]]->index(),
5300 new_lines[child_lines[i][3]]->index()});
5301
5302 subcells[i]->set_used_flag();
5303 subcells[i]->clear_refine_flag();
5304 subcells[i]->clear_user_flag();
5305 subcells[i]->clear_user_data();
5306 subcells[i]->clear_children();
5307 // inherit material properties
5308 subcells[i]->set_material_id(cell->material_id());
5309 subcells[i]->set_manifold_id(cell->manifold_id());
5310 subcells[i]->set_subdomain_id(cell->subdomain_id());
5311
5312 triangulation.levels[subcells[i]->level()]
5313 ->reference_cell[subcells[i]->index()] = cell->reference_cell();
5314
5315 // Finally, now that children are marked as used, we can set
5316 // orientation flags:
5317 for (unsigned int face_no : cell->face_indices())
5318 subcells[i]->set_combined_face_orientation(
5319 face_no, inherited_orientations[child_lines[i][face_no]]);
5320
5321 if (i % 2 == 0)
5322 subcells[i]->set_parent(cell->index());
5323 }
5324
5325 // Unlike the same lines on other children, the innermost triangle's
5326 // faces are all in the default orientation:
5327 if (cell->reference_cell() == ReferenceCells::Triangle)
5328 for (unsigned int face_no : cell->face_indices())
5329 subcells[3]->set_combined_face_orientation(
5331
5332 for (unsigned int i = 0; i < n_children / 2; ++i)
5333 cell->set_children(2 * i, subcells[2 * i]->index());
5334
5335 cell->set_refinement_case(ref_case);
5336
5337 if (dim == spacedim - 1)
5338 for (unsigned int c = 0; c < n_children; ++c)
5339 cell->child(c)->set_direction_flag(cell->direction_flag());
5340 };
5341
5342 for (int level = 0;
5344 ++level)
5345 {
5347 next_unused_cell = triangulation.begin_raw(level + 1);
5348
5349 for (const auto &cell :
5351 if (cell->refine_flag_set())
5352 {
5353 create_children(triangulation,
5354 next_unused_vertex,
5355 next_unused_line,
5356 next_unused_cell,
5357 cell);
5358
5359 if (cell->reference_cell() == ReferenceCells::Quadrilateral &&
5360 check_for_distorted_cells &&
5361 has_distorted_children<dim, spacedim>(cell))
5362 cells_with_distorted_children.distorted_cells.push_back(
5363 cell);
5364
5365 triangulation.signals.post_refinement_on_cell(cell);
5366 }
5367 }
5368
5369 return cells_with_distorted_children;
5370 }
5371
5372
5373
5378 template <int spacedim>
5381 const bool /*check_for_distorted_cells*/)
5382 {
5383 const unsigned int dim = 1;
5384
5385 // Check whether a new level is needed. We have to check for
5386 // this on the highest level only
5387 for (const auto &cell : triangulation.active_cell_iterators_on_level(
5388 triangulation.levels.size() - 1))
5389 if (cell->refine_flag_set())
5390 {
5391 triangulation.levels.push_back(
5392 std::make_unique<
5394 break;
5395 }
5396
5397
5398 // check how much space is needed on every level. We need not
5399 // check the highest level since either - on the highest level
5400 // no cells are flagged for refinement - there are, but
5401 // prepare_refinement added another empty level
5402 unsigned int needed_vertices = 0;
5403 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5404 {
5405 // count number of flagged
5406 // cells on this level
5407 unsigned int flagged_cells = 0;
5408
5409 for (const auto &acell :
5411 if (acell->refine_flag_set())
5412 ++flagged_cells;
5413
5414 // count number of used cells
5415 // on the next higher level
5416 const unsigned int used_cells =
5417 std::count(triangulation.levels[level + 1]->cells.used.begin(),
5418 triangulation.levels[level + 1]->cells.used.end(),
5419 true);
5420
5421 // reserve space for the used_cells cells already existing
5422 // on the next higher level as well as for the
5423 // 2*flagged_cells that will be created on that level
5426 flagged_cells,
5427 1,
5428 spacedim);
5429 // reserve space for 2*flagged_cells new lines on the next
5430 // higher level
5433 flagged_cells,
5434 0);
5435
5436 needed_vertices += flagged_cells;
5437 }
5438
5439 // add to needed vertices how many
5440 // vertices are already in use
5441 needed_vertices += std::count(triangulation.vertices_used.begin(),
5443 true);
5444 // if we need more vertices: create them, if not: leave the
5445 // array as is, since shrinking is not really possible because
5446 // some of the vertices at the end may be in use
5447 if (needed_vertices > triangulation.vertices.size())
5448 {
5449 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
5450 triangulation.vertices_used.resize(needed_vertices, false);
5451 }
5452
5453
5454 // Do REFINEMENT on every level; exclude highest level as
5455 // above
5456
5457 // index of next unused vertex
5458 unsigned int next_unused_vertex = 0;
5459
5460 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5461 {
5463 next_unused_cell = triangulation.begin_raw(level + 1);
5464
5465 for (const auto &cell :
5467 if (cell->refine_flag_set())
5468 {
5469 // clear refinement flag
5470 cell->clear_refine_flag();
5471
5472 // search for next unused
5473 // vertex
5474 while (triangulation.vertices_used[next_unused_vertex] ==
5475 true)
5476 ++next_unused_vertex;
5477 Assert(
5478 next_unused_vertex < triangulation.vertices.size(),
5479 ExcMessage(
5480 "Internal error: During refinement, the triangulation "
5481 "wants to access an element of the 'vertices' array "
5482 "but it turns out that the array is not large enough."));
5483
5484 // Now we always ask the cell itself where to put
5485 // the new point. The cell in turn will query the
5486 // manifold object internally.
5487 triangulation.vertices[next_unused_vertex] =
5488 cell->center(true);
5489
5490 triangulation.vertices_used[next_unused_vertex] = true;
5491
5492 // search for next two unused cell (++ takes care of
5493 // the end of the vector)
5495 first_child,
5496 second_child;
5497 while (next_unused_cell->used() == true)
5498 ++next_unused_cell;
5499 first_child = next_unused_cell;
5500 first_child->set_used_flag();
5501 first_child->clear_user_data();
5502 ++next_unused_cell;
5503 AssertIsNotUsed(next_unused_cell);
5504 second_child = next_unused_cell;
5505 second_child->set_used_flag();
5506 second_child->clear_user_data();
5507
5508 types::subdomain_id subdomainid = cell->subdomain_id();
5509
5510 // insert first child
5511 cell->set_children(0, first_child->index());
5512 first_child->clear_children();
5513 first_child->set_bounding_object_indices(
5514 {cell->vertex_index(0), next_unused_vertex});
5515 first_child->set_material_id(cell->material_id());
5516 first_child->set_manifold_id(cell->manifold_id());
5517 first_child->set_subdomain_id(subdomainid);
5518 if (dim == spacedim - 1)
5519 first_child->set_direction_flag(cell->direction_flag());
5520
5521 first_child->set_parent(cell->index());
5522
5523 // Set manifold id of the right face. Only do this
5524 // on the first child.
5525 first_child->face(1)->set_manifold_id(cell->manifold_id());
5526
5527 // reset neighborship info (refer to
5528 // internal::TriangulationImplementation::TriaLevel<0> for
5529 // details)
5530 first_child->set_neighbor(1, second_child);
5531 if (cell->neighbor(0).state() != IteratorState::valid)
5532 first_child->set_neighbor(0, cell->neighbor(0));
5533 else if (cell->neighbor(0)->is_active())
5534 {
5535 // since the neighbors level is always <=level,
5536 // if the cell is active, then there are no
5537 // cells to the left which may want to know
5538 // about this new child cell.
5539 Assert(cell->neighbor(0)->level() <= cell->level(),
5541 first_child->set_neighbor(0, cell->neighbor(0));
5542 }
5543 else
5544 // left neighbor is refined
5545 {
5546 // set neighbor to cell on same level
5547 const unsigned int nbnb = cell->neighbor_of_neighbor(0);
5548 first_child->set_neighbor(0,
5549 cell->neighbor(0)->child(nbnb));
5550
5551 // reset neighbor info of all right descendant
5552 // of the left neighbor of cell
5554 left_neighbor = cell->neighbor(0);
5555 while (left_neighbor->has_children())
5556 {
5557 left_neighbor = left_neighbor->child(nbnb);
5558 left_neighbor->set_neighbor(nbnb, first_child);
5559 }
5560 }
5561
5562 // insert second child
5563 second_child->clear_children();
5564 second_child->set_bounding_object_indices(
5565 {next_unused_vertex, cell->vertex_index(1)});
5566 second_child->set_neighbor(0, first_child);
5567 second_child->set_material_id(cell->material_id());
5568 second_child->set_manifold_id(cell->manifold_id());
5569 second_child->set_subdomain_id(subdomainid);
5570 if (dim == spacedim - 1)
5571 second_child->set_direction_flag(cell->direction_flag());
5572
5573 if (cell->neighbor(1).state() != IteratorState::valid)
5574 second_child->set_neighbor(1, cell->neighbor(1));
5575 else if (cell->neighbor(1)->is_active())
5576 {
5577 Assert(cell->neighbor(1)->level() <= cell->level(),
5579 second_child->set_neighbor(1, cell->neighbor(1));
5580 }
5581 else
5582 // right neighbor is refined same as above
5583 {
5584 const unsigned int nbnb = cell->neighbor_of_neighbor(1);
5585 second_child->set_neighbor(
5586 1, cell->neighbor(1)->child(nbnb));
5587
5589 right_neighbor = cell->neighbor(1);
5590 while (right_neighbor->has_children())
5591 {
5592 right_neighbor = right_neighbor->child(nbnb);
5593 right_neighbor->set_neighbor(nbnb, second_child);
5594 }
5595 }
5596 // inform all listeners that cell refinement is done
5597 triangulation.signals.post_refinement_on_cell(cell);
5598 }
5599 }
5600
5601 // in 1d, we can not have distorted children unless the parent
5602 // was already distorted (that is because we don't use
5603 // boundary information for 1d triangulations). so return an
5604 // empty list
5606 }
5607
5608
5613 template <int spacedim>
5616 const bool check_for_distorted_cells)
5617 {
5618 const unsigned int dim = 2;
5619
5620 // First check whether we can get away with isotropic refinement, or
5621 // whether we need to run through the full anisotropic algorithm
5622 {
5623 bool do_isotropic_refinement = true;
5624 for (const auto &cell : triangulation.active_cell_iterators())
5625 if (cell->refine_flag_set() == RefinementCase<dim>::cut_x ||
5626 cell->refine_flag_set() == RefinementCase<dim>::cut_y)
5627 {
5628 do_isotropic_refinement = false;
5629 break;
5630 }
5631
5632 if (do_isotropic_refinement)
5633 return execute_refinement_isotropic(triangulation,
5634 check_for_distorted_cells);
5635 }
5636
5637 // If we get here, we are doing anisotropic refinement.
5638
5639 // Check whether a new level is needed. We have to check for
5640 // this on the highest level only
5641 for (const auto &cell : triangulation.active_cell_iterators_on_level(
5642 triangulation.levels.size() - 1))
5643 if (cell->refine_flag_set())
5644 {
5645 triangulation.levels.push_back(
5646 std::make_unique<
5648 break;
5649 }
5650
5651 // TODO[WB]: we clear user flags and pointers of lines; we're going
5652 // to use them to flag which lines need refinement
5655 line != triangulation.end_line();
5656 ++line)
5657 {
5658 line->clear_user_flag();
5659 line->clear_user_data();
5660 }
5661 // running over all cells and lines count the number
5662 // n_single_lines of lines which can be stored as single
5663 // lines, e.g. inner lines
5664 unsigned int n_single_lines = 0;
5665
5666 // New lines to be created: number lines which are stored in
5667 // pairs (the children of lines must be stored in pairs)
5668 unsigned int n_lines_in_pairs = 0;
5669
5670 // check how much space is needed on every level. We need not
5671 // check the highest level since either - on the highest level
5672 // no cells are flagged for refinement - there are, but
5673 // prepare_refinement added another empty level
5674 unsigned int needed_vertices = 0;
5675 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5676 {
5677 // count number of flagged cells on this level and compute
5678 // how many new vertices and new lines will be needed
5679 unsigned int needed_cells = 0;
5680
5681 for (const auto &cell :
5683 if (cell->refine_flag_set())
5684 {
5685 if (cell->refine_flag_set() == RefinementCase<dim>::cut_xy)
5686 {
5687 needed_cells += 4;
5688
5689 // new vertex at center of cell is needed in any
5690 // case
5691 ++needed_vertices;
5692
5693 // the four inner lines can be stored as singles
5694 n_single_lines += 4;
5695 }
5696 else // cut_x || cut_y
5697 {
5698 // set the flag showing that anisotropic
5699 // refinement is used for at least one cell
5701
5702 needed_cells += 2;
5703 // no vertex at center
5704
5705 // the inner line can be stored as single
5706 n_single_lines += 1;
5707 }
5708
5709 // mark all faces (lines) for refinement; checking
5710 // locally whether the neighbor would also like to
5711 // refine them is rather difficult for lines so we
5712 // only flag them and after visiting all cells, we
5713 // decide which lines need refinement;
5714 for (const unsigned int line_no :
5716 {
5718 cell->refine_flag_set(), line_no) ==
5720 {
5722 line = cell->line(line_no);
5723 if (line->has_children() == false)
5724 line->set_user_flag();
5725 }
5726 }
5727 }
5728
5729
5730 // count number of used cells on the next higher level
5731 const unsigned int used_cells =
5732 std::count(triangulation.levels[level + 1]->cells.used.begin(),
5733 triangulation.levels[level + 1]->cells.used.end(),
5734 true);
5735
5736
5737 // reserve space for the used_cells cells already existing
5738 // on the next higher level as well as for the
5739 // needed_cells that will be created on that level
5741 used_cells + needed_cells,
5742 2,
5743 spacedim);
5744
5745 // reserve space for needed_cells new quads on the next
5746 // higher level
5748 needed_cells,
5749 0);
5750 }
5751
5752 // now count the lines which were flagged for refinement
5755 line != triangulation.end_line();
5756 ++line)
5757 if (line->user_flag_set())
5758 {
5759 Assert(line->has_children() == false, ExcInternalError());
5760 n_lines_in_pairs += 2;
5761 needed_vertices += 1;
5762 }
5763 // reserve space for n_lines_in_pairs new lines. note, that
5764 // we can't reserve space for the single lines here as well,
5765 // as all the space reserved for lines in pairs would be
5766 // counted as unused and we would end up with too little space
5767 // to store all lines. memory reservation for n_single_lines
5768 // can only be done AFTER we refined the lines of the current
5769 // cells
5770 reserve_space(triangulation.faces->lines, n_lines_in_pairs, 0);
5771
5772 // add to needed vertices how many vertices are already in use
5773 needed_vertices += std::count(triangulation.vertices_used.begin(),
5775 true);
5776 // if we need more vertices: create them, if not: leave the
5777 // array as is, since shrinking is not really possible because
5778 // some of the vertices at the end may be in use
5779 if (needed_vertices > triangulation.vertices.size())
5780 {
5781 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
5782 triangulation.vertices_used.resize(needed_vertices, false);
5783 }
5784
5785
5786 // Do REFINEMENT on every level; exclude highest level as
5787 // above
5788
5789 // index of next unused vertex
5790 unsigned int next_unused_vertex = 0;
5791
5792 // first the refinement of lines. children are stored
5793 // pairwise
5794 {
5795 // only active objects can be refined further
5798 endl = triangulation.end_line();
5800 next_unused_line = triangulation.begin_raw_line();
5801
5802 for (; line != endl; ++line)
5803 if (line->user_flag_set())
5804 {
5805 // this line needs to be refined
5806
5807 // find the next unused vertex and set it
5808 // appropriately
5809 while (triangulation.vertices_used[next_unused_vertex] == true)
5810 ++next_unused_vertex;
5811 Assert(
5812 next_unused_vertex < triangulation.vertices.size(),
5813 ExcMessage(
5814 "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."));
5815 triangulation.vertices_used[next_unused_vertex] = true;
5816
5817 triangulation.vertices[next_unused_vertex] = line->center(true);
5818
5819 // now that we created the right point, make up the
5820 // two child lines. To this end, find a pair of
5821 // unused lines
5822 bool pair_found = false;
5823 (void)pair_found;
5824 for (; next_unused_line != endl; ++next_unused_line)
5825 if (!next_unused_line->used() &&
5826 !(++next_unused_line)->used())
5827 {
5828 // go back to the first of the two unused
5829 // lines
5830 --next_unused_line;
5831 pair_found = true;
5832 break;
5833 }
5834 Assert(pair_found, ExcInternalError());
5835
5836 // there are now two consecutive unused lines, such
5837 // that the children of a line will be consecutive.
5838 // then set the child pointer of the present line
5839 line->set_children(0, next_unused_line->index());
5840
5841 // set the two new lines
5843 children[2] = {next_unused_line, ++next_unused_line};
5844 // some tests; if any of the iterators should be
5845 // invalid, then already dereferencing will fail
5846 AssertIsNotUsed(children[0]);
5847 AssertIsNotUsed(children[1]);
5848
5849 children[0]->set_bounding_object_indices(
5850 {line->vertex_index(0), next_unused_vertex});
5851 children[1]->set_bounding_object_indices(
5852 {next_unused_vertex, line->vertex_index(1)});
5853
5854 children[0]->set_used_flag();
5855 children[1]->set_used_flag();
5856 children[0]->clear_children();
5857 children[1]->clear_children();
5858 children[0]->clear_user_data();
5859 children[1]->clear_user_data();
5860 children[0]->clear_user_flag();
5861 children[1]->clear_user_flag();
5862
5863
5864 children[0]->set_boundary_id_internal(line->boundary_id());
5865 children[1]->set_boundary_id_internal(line->boundary_id());
5866
5867 children[0]->set_manifold_id(line->manifold_id());
5868 children[1]->set_manifold_id(line->manifold_id());
5869
5870 // finally clear flag indicating the need for
5871 // refinement
5872 line->clear_user_flag();
5873 }
5874 }
5875
5876
5877 // Now set up the new cells
5878
5879 // reserve space for inner lines (can be stored as single
5880 // lines)
5881 reserve_space(triangulation.faces->lines, 0, n_single_lines);
5882
5884 cells_with_distorted_children;
5885
5886 // reset next_unused_line, as now also single empty places in
5887 // the vector can be used
5889 next_unused_line = triangulation.begin_raw_line();
5890
5891 for (int level = 0;
5893 ++level)
5894 {
5896 next_unused_cell = triangulation.begin_raw(level + 1);
5897
5898 for (const auto &cell :
5900 if (cell->refine_flag_set())
5901 {
5902 // actually set up the children and update neighbor
5903 // information
5904 create_children(triangulation,
5905 next_unused_vertex,
5906 next_unused_line,
5907 next_unused_cell,
5908 cell);
5909
5910 if (check_for_distorted_cells &&
5911 has_distorted_children<dim, spacedim>(cell))
5912 cells_with_distorted_children.distorted_cells.push_back(
5913 cell);
5914 // inform all listeners that cell refinement is done
5915 triangulation.signals.post_refinement_on_cell(cell);
5916 }
5917 }
5918
5919 return cells_with_distorted_children;
5920 }
5921
5922
5923 template <int spacedim>
5926 const bool check_for_distorted_cells)
5927 {
5928 static const int dim = 3;
5929 static const unsigned int X = numbers::invalid_unsigned_int;
5930 using raw_line_iterator =
5932 using raw_quad_iterator =
5934
5935 Assert(spacedim == 3, ExcNotImplemented());
5936
5937 Assert(triangulation.vertices.size() ==
5940
5941 // Check whether a new level is needed. We have to check for
5942 // this on the highest level only
5943 for (const auto &cell : triangulation.active_cell_iterators_on_level(
5944 triangulation.levels.size() - 1))
5945 if (cell->refine_flag_set())
5946 {
5947 triangulation.levels.push_back(
5948 std::make_unique<
5950 break;
5951 }
5952
5953 // first clear user flags for quads and lines; we're going to
5954 // use them to flag which lines and quads need refinement
5955 triangulation.faces->quads.clear_user_data();
5956 triangulation.faces->lines.clear_user_flags();
5957 triangulation.faces->quads.clear_user_flags();
5958
5959 // check how much space is needed on every level. We need not
5960 // check the highest level since either
5961 // - on the highest level no cells are flagged for refinement
5962 // - there are, but prepare_refinement added another empty
5963 // level which then is the highest level
5964
5965 // variables to hold the number of newly to be created
5966 // vertices, lines and quads. as these are stored globally,
5967 // declare them outside the loop over al levels. we need lines
5968 // and quads in pairs for refinement of old ones and lines and
5969 // quads, that can be stored as single ones, as they are newly
5970 // created in the inside of an existing cell
5971 unsigned int needed_vertices = 0;
5972 unsigned int needed_lines_single = 0;
5973 unsigned int needed_quads_single = 0;
5974 unsigned int needed_lines_pair = 0;
5975 unsigned int needed_quads_pair = 0;
5976 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5977 {
5978 unsigned int new_cells = 0;
5979
5980 for (const auto &cell :
5982 if (cell->refine_flag_set())
5983 {
5984 // Only support isotropic refinement
5985 Assert(cell->refine_flag_set() ==
5988
5989 // Now count up how many new cells, faces, edges, and vertices
5990 // we will need to allocate to do this refinement.
5991 new_cells += cell->reference_cell().n_isotropic_children();
5992
5993 if (cell->reference_cell() == ReferenceCells::Hexahedron)
5994 {
5995 ++needed_vertices;
5996 needed_lines_single += 6;
5997 needed_quads_single += 12;
5998 }
5999 else if (cell->reference_cell() ==
6001 {
6002 needed_lines_single += 1;
6003 needed_quads_single += 8;
6004 }
6005 else
6006 {
6008 }
6009
6010 // Also check whether we have to refine any of the faces and
6011 // edges that bound this cell. They may of course already be
6012 // refined, so we only *mark* them for refinement by setting
6013 // the user flags
6014 for (const auto face : cell->face_indices())
6015 if (cell->face(face)->n_children() == 0)
6016 cell->face(face)->set_user_flag();
6017 else
6018 Assert(cell->face(face)->n_children() ==
6019 cell->reference_cell()
6020 .face_reference_cell(face)
6021 .n_isotropic_children(),
6023
6024 for (const auto line : cell->line_indices())
6025 if (cell->line(line)->has_children() == false)
6026 cell->line(line)->set_user_flag();
6027 else
6028 Assert(cell->line(line)->n_children() == 2,
6030 }
6031
6032 const unsigned int used_cells =
6033 std::count(triangulation.levels[level + 1]->cells.used.begin(),
6034 triangulation.levels[level + 1]->cells.used.end(),
6035 true);
6036
6039 used_cells + new_cells,
6040 3,
6041 spacedim,
6042 false);
6043 else
6045 used_cells + new_cells,
6046 3,
6047 spacedim,
6048 true);
6049
6050 reserve_space(triangulation.levels[level + 1]->cells, new_cells);
6051 }
6052
6053 // now count the quads and lines which were flagged for
6054 // refinement
6057 quad != triangulation.end_quad();
6058 ++quad)
6059 {
6060 if (quad->user_flag_set() == false)
6061 continue;
6062
6063 if (quad->reference_cell() == ReferenceCells::Quadrilateral)
6064 {
6065 needed_quads_pair += 4;
6066 needed_lines_pair += 4;
6067 needed_vertices += 1;
6068 }
6069 else if (quad->reference_cell() == ReferenceCells::Triangle)
6070 {
6071 needed_quads_pair += 4;
6072 needed_lines_single += 3;
6073 }
6074 else
6075 {
6077 }
6078 }
6079
6082 line != triangulation.end_line();
6083 ++line)
6084 {
6085 if (line->user_flag_set() == false)
6086 continue;
6087
6088 needed_lines_pair += 2;
6089 needed_vertices += 1;
6090 }
6091
6093 needed_lines_pair,
6094 needed_lines_single);
6096 needed_quads_pair,
6097 needed_quads_single);
6099 needed_quads_pair,
6100 needed_quads_single);
6101
6102
6103 // add to needed vertices how many vertices are already in use
6104 needed_vertices += std::count(triangulation.vertices_used.begin(),
6106 true);
6107
6108 if (needed_vertices > triangulation.vertices.size())
6109 {
6110 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
6111 triangulation.vertices_used.resize(needed_vertices, false);
6112 }
6113
6114 //-----------------------------------------
6115 // Before we start with the actual refinement, we do some
6116 // sanity checks if in debug mode. especially, we try to catch
6117 // the notorious problem with lines being twice refined,
6118 // i.e. there are cells adjacent at one line ("around the
6119 // edge", but not at a face), with two cells differing by more
6120 // than one refinement level
6121 //
6122 // this check is very simple to implement here, since we have
6123 // all lines flagged if they shall be refined
6124#ifdef DEBUG
6125 for (const auto &cell : triangulation.active_cell_iterators())
6126 if (!cell->refine_flag_set())
6127 for (unsigned int line_n = 0; line_n < cell->n_lines(); ++line_n)
6128 if (cell->line(line_n)->has_children())
6129 for (unsigned int c = 0; c < 2; ++c)
6130 Assert(cell->line(line_n)->child(c)->user_flag_set() == false,
6132#endif
6133
6134 unsigned int current_vertex = 0;
6135
6136 // helper function - find the next available vertex number and mark it
6137 // as used.
6138 auto get_next_unused_vertex = [](const unsigned int current_vertex,
6139 std::vector<bool> &vertices_used) {
6140 unsigned int next_vertex = current_vertex;
6141 while (next_vertex < vertices_used.size() &&
6142 vertices_used[next_vertex] == true)
6143 ++next_vertex;
6144 Assert(next_vertex < vertices_used.size(), ExcInternalError());
6145 vertices_used[next_vertex] = true;
6146
6147 return next_vertex;
6148 };
6149
6150 // LINES
6151 {
6154 endl = triangulation.end_line();
6155 raw_line_iterator next_unused_line = triangulation.begin_raw_line();
6156
6157 for (; line != endl; ++line)
6158 {
6159 if (line->user_flag_set() == false)
6160 continue;
6161
6162 next_unused_line =
6163 triangulation.faces->lines.template next_free_pair_object<1>(
6165 Assert(next_unused_line.state() == IteratorState::valid,
6167
6168 // now we found two consecutive unused lines, such
6169 // that the children of a line will be consecutive.
6170 // then set the child pointer of the present line
6171 line->set_children(0, next_unused_line->index());
6172
6173 const std::array<raw_line_iterator, 2> children{
6174 {next_unused_line, ++next_unused_line}};
6175
6176 AssertIsNotUsed(children[0]);
6177 AssertIsNotUsed(children[1]);
6178
6179 current_vertex =
6180 get_next_unused_vertex(current_vertex,
6182 triangulation.vertices[current_vertex] = line->center(true);
6183
6184 children[0]->set_bounding_object_indices(
6185 {line->vertex_index(0), current_vertex});
6186 children[1]->set_bounding_object_indices(
6187 {current_vertex, line->vertex_index(1)});
6188
6189 const auto manifold_id = line->manifold_id();
6190 const auto boundary_id = line->boundary_id();
6191 for (const auto &child : children)
6192 {
6193 child->set_used_flag();
6194 child->clear_children();
6195 child->clear_user_data();
6196 child->clear_user_flag();
6197 child->set_boundary_id_internal(boundary_id);
6198 child->set_manifold_id(manifold_id);
6199 }
6200
6201 line->clear_user_flag();
6202 }
6203 }
6204
6205 // QUADS
6206 {
6208 quad = triangulation.begin_quad(),
6209 endq = triangulation.end_quad();
6210
6211 for (; quad != endq; ++quad)
6212 {
6213 if (quad->user_flag_set() == false)
6214 continue;
6215
6216 const auto reference_face_type = quad->reference_cell();
6217
6218 // 1) create new lines (property is set later)
6219 // maximum of 4 new lines (4 quadrilateral, 3 triangle)
6220 std::array<raw_line_iterator, 4> new_lines;
6221 if (reference_face_type == ReferenceCells::Quadrilateral)
6222 {
6223 for (unsigned int l = 0; l < 2; ++l)
6224 {
6225 auto next_unused_line =
6226 triangulation.faces->lines
6227 .template next_free_pair_object<1>(triangulation);
6228 new_lines[2 * l] = next_unused_line;
6229 new_lines[2 * l + 1] = ++next_unused_line;
6230 }
6231 }
6232 else if (reference_face_type == ReferenceCells::Triangle)
6233 {
6234 for (unsigned int l = 0; l < 3; ++l)
6235 new_lines[l] =
6236 triangulation.faces->lines
6237 .template next_free_single_object<1>(triangulation);
6238 }
6239 else
6240 {
6242 }
6243
6244 for (const unsigned int line : quad->line_indices())
6245 {
6246 AssertIsNotUsed(new_lines[line]);
6247 (void)line;
6248 }
6249
6250 // 2) create new quads (properties are set below). Both triangles
6251 // and quads are divided in four.
6252 std::array<raw_quad_iterator, 4> new_quads;
6253 for (unsigned int q = 0; q < 2; ++q)
6254 {
6255 auto next_unused_quad =
6256 triangulation.faces->quads
6257 .template next_free_pair_object<2>(triangulation);
6258
6259 new_quads[2 * q] = next_unused_quad;
6260 new_quads[2 * q + 1] = ++next_unused_quad;
6261
6262 quad->set_children(2 * q, new_quads[2 * q]->index());
6263 }
6264 quad->set_refinement_case(RefinementCase<2>::cut_xy);
6265
6266 for (const auto &quad : new_quads)
6267 {
6268 AssertIsNotUsed(quad);
6269 (void)quad;
6270 }
6271
6272 // 3) set vertex indices and set new vertex
6273
6274 // Maximum of 9 vertices per refined quad (9 for Quadrilateral, 6
6275 // for Triangle)
6276 std::array<unsigned int, 9> vertex_indices = {};
6277 unsigned int k = 0;
6278 for (const auto i : quad->vertex_indices())
6279 vertex_indices[k++] = quad->vertex_index(i);
6280
6281 for (const auto i : quad->line_indices())
6282 vertex_indices[k++] = quad->line(i)->child(0)->vertex_index(1);
6283
6284 if (reference_face_type == ReferenceCells::Quadrilateral)
6285 {
6286 current_vertex =
6287 get_next_unused_vertex(current_vertex,
6289 vertex_indices[k++] = current_vertex;
6290
6291 triangulation.vertices[current_vertex] =
6292 quad->center(true, true);
6293 }
6294
6295 // 4) set new lines on quads and their properties
6296 std::array<raw_line_iterator, 12> lines;
6297 unsigned int n_lines = 0;
6298 for (unsigned int l = 0; l < quad->n_lines(); ++l)
6299 for (unsigned int c = 0; c < 2; ++c)
6300 {
6301 static constexpr ::ndarray<unsigned int, 2, 2> index =
6302 {{// child 0, line_orientation=false and true
6303 {{1, 0}},
6304 // child 1, line_orientation=false and true
6305 {{0, 1}}}};
6306
6307 lines[n_lines++] =
6308 quad->line(l)->child(index[c][quad->line_orientation(l)]);
6309 }
6310
6311 for (unsigned int l = 0; l < quad->n_lines(); ++l)
6312 lines[n_lines++] = new_lines[l];
6313
6314 std::array<int, 12> line_indices;
6315 for (unsigned int i = 0; i < n_lines; ++i)
6316 line_indices[i] = lines[i]->index();
6317
6318 static constexpr ::ndarray<unsigned int, 12, 2>
6319 line_vertices_quad{{{{0, 4}},
6320 {{4, 2}},
6321 {{1, 5}},
6322 {{5, 3}},
6323 {{0, 6}},
6324 {{6, 1}},
6325 {{2, 7}},
6326 {{7, 3}},
6327 {{6, 8}},
6328 {{8, 7}},
6329 {{4, 8}},
6330 {{8, 5}}}};
6331
6332 static constexpr ::ndarray<unsigned int, 4, 4>
6333 quad_lines_quad{{{{0, 8, 4, 10}},
6334 {{8, 2, 5, 11}},
6335 {{1, 9, 10, 6}},
6336 {{9, 3, 11, 7}}}};
6337
6338 static constexpr ::ndarray<unsigned int, 12, 2>
6339 line_vertices_tri{{{{0, 3}},
6340 {{3, 1}},
6341 {{1, 4}},
6342 {{4, 2}},
6343 {{2, 5}},
6344 {{5, 0}},
6345 {{3, 4}},
6346 {{4, 5}},
6347 {{3, 5}},
6348 {{X, X}},
6349 {{X, X}},
6350 {{X, X}}}};
6351
6352 static constexpr ::ndarray<unsigned int, 4, 4>
6353 quad_lines_tri{{{{0, 8, 5, X}},
6354 {{1, 2, 6, X}},
6355 {{7, 3, 4, X}},
6356 {{6, 7, 8, X}}}};
6357
6358 static constexpr ::ndarray<unsigned int, 4, 4, 2>
6359 quad_line_vertices_tri{
6360 {{{{{0, 3}}, {{3, 5}}, {{5, 0}}, {{X, X}}}},
6361 {{{{3, 1}}, {{1, 4}}, {{4, 3}}, {{X, X}}}},
6362 {{{{5, 4}}, {{4, 2}}, {{2, 5}}, {{X, X}}}},
6363 {{{{3, 4}}, {{4, 5}}, {{5, 3}}, {{X, X}}}}}};
6364
6365 const auto &line_vertices =
6366 (reference_face_type == ReferenceCells::Quadrilateral) ?
6367 line_vertices_quad :
6368 line_vertices_tri;
6369 const auto &quad_lines =
6370 (reference_face_type == ReferenceCells::Quadrilateral) ?
6371 quad_lines_quad :
6372 quad_lines_tri;
6373
6374 for (unsigned int i = 0, j = 2 * quad->n_lines();
6375 i < quad->n_lines();
6376 ++i, ++j)
6377 {
6378 auto &new_line = new_lines[i];
6379 new_line->set_bounding_object_indices(
6380 {vertex_indices[line_vertices[j][0]],
6381 vertex_indices[line_vertices[j][1]]});
6382 new_line->set_used_flag();
6383 new_line->clear_user_flag();
6384 new_line->clear_user_data();
6385 new_line->clear_children();
6386 new_line->set_boundary_id_internal(quad->boundary_id());
6387 new_line->set_manifold_id(quad->manifold_id());
6388 }
6389
6390 // 5) set properties of quads
6391 for (unsigned int i = 0; i < new_quads.size(); ++i)
6392 {
6393 auto &new_quad = new_quads[i];
6394
6395 // TODO: we assume here that all children have the same type
6396 // as the parent
6397 triangulation.faces->set_quad_type(new_quad->index(),
6398 reference_face_type);
6399
6400 if (reference_face_type == ReferenceCells::Triangle)
6401 new_quad->set_bounding_object_indices(
6402 {line_indices[quad_lines[i][0]],
6403 line_indices[quad_lines[i][1]],
6404 line_indices[quad_lines[i][2]]});
6405 else if (reference_face_type == ReferenceCells::Quadrilateral)
6406 new_quad->set_bounding_object_indices(
6407 {line_indices[quad_lines[i][0]],
6408 line_indices[quad_lines[i][1]],
6409 line_indices[quad_lines[i][2]],
6410 line_indices[quad_lines[i][3]]});
6411 else
6413
6414 new_quad->set_used_flag();
6415 new_quad->clear_user_flag();
6416 new_quad->clear_user_data();
6417 new_quad->clear_children();
6418 new_quad->set_boundary_id_internal(quad->boundary_id());
6419 new_quad->set_manifold_id(quad->manifold_id());
6420
6421#ifdef DEBUG
6422 std::set<unsigned int> s;
6423#endif
6424
6425 // ... and fix orientation of lines of face for triangles,
6426 // using an expensive algorithm, quadrilaterals are treated
6427 // a few lines below by a cheaper algorithm
6428 if (reference_face_type == ReferenceCells::Triangle)
6429 {
6430 for (const auto f : new_quad->line_indices())
6431 {
6432 const std::array<unsigned int, 2> vertices_0 = {
6433 {lines[quad_lines[i][f]]->vertex_index(0),
6434 lines[quad_lines[i][f]]->vertex_index(1)}};
6435
6436 const std::array<unsigned int, 2> vertices_1 = {
6437 {vertex_indices[quad_line_vertices_tri[i][f][0]],
6438 vertex_indices[quad_line_vertices_tri[i][f][1]]}};
6439
6440 const auto orientation =
6442 make_array_view(vertices_0),
6443 make_array_view(vertices_1));
6444
6445#ifdef DEBUG
6446 for (const auto i : vertices_0)
6447 s.insert(i);
6448 for (const auto i : vertices_1)
6449 s.insert(i);
6450#endif
6451
6452 new_quad->set_line_orientation(
6453 f,
6454 orientation ==
6456 default_combined_face_orientation());
6457 }
6458#ifdef DEBUG
6459 AssertDimension(s.size(), 3);
6460#endif
6461 }
6462 }
6463
6464 // fix orientation of lines of faces for quadrilaterals with
6465 // cheap algorithm
6466 if (reference_face_type == ReferenceCells::Quadrilateral)
6467 {
6468 static constexpr ::ndarray<unsigned int, 4, 2>
6469 quad_child_boundary_lines{
6470 {{{0, 2}}, {{1, 3}}, {{0, 1}}, {{2, 3}}}};
6471
6472 for (unsigned int i = 0; i < 4; ++i)
6473 for (unsigned int j = 0; j < 2; ++j)
6474 new_quads[quad_child_boundary_lines[i][j]]
6475 ->set_line_orientation(i, quad->line_orientation(i));
6476 }
6477
6478 quad->clear_user_flag();
6479 }
6480 }
6481
6483 cells_with_distorted_children;
6484
6487 for (unsigned int level = 0; level != triangulation.levels.size() - 1;
6488 ++level)
6489 {
6491 next_unused_hex = triangulation.begin_raw_hex(level + 1);
6492 Assert(hex == triangulation.end() ||
6493 hex->level() >= static_cast<int>(level),
6495
6496 for (; hex != triangulation.end() &&
6497 hex->level() == static_cast<int>(level);
6498 ++hex)
6499 {
6500 if (hex->refine_flag_set() ==
6502 continue;
6503
6504 const auto &reference_cell_type = hex->reference_cell();
6505
6506 const RefinementCase<dim> ref_case = hex->refine_flag_set();
6507 hex->clear_refine_flag();
6508 hex->set_refinement_case(ref_case);
6509
6510 unsigned int n_new_lines = 0;
6511 unsigned int n_new_quads = 0;
6512 unsigned int n_new_hexes = 0;
6513
6514 if (reference_cell_type == ReferenceCells::Hexahedron)
6515 {
6516 n_new_lines = 6;
6517 n_new_quads = 12;
6518 n_new_hexes = 8;
6519 }
6520 else if (reference_cell_type == ReferenceCells::Tetrahedron)
6521 {
6522 n_new_lines = 1;
6523 n_new_quads = 8;
6524 n_new_hexes = 8;
6525 }
6526 else
6528
6529 std::array<raw_line_iterator, 6> new_lines;
6530 for (unsigned int i = 0; i < n_new_lines; ++i)
6531 {
6532 new_lines[i] =
6533 triangulation.faces->lines
6534 .template next_free_single_object<1>(triangulation);
6535
6536 AssertIsNotUsed(new_lines[i]);
6537 new_lines[i]->set_used_flag();
6538 new_lines[i]->clear_user_flag();
6539 new_lines[i]->clear_user_data();
6540 new_lines[i]->clear_children();
6541 new_lines[i]->set_boundary_id_internal(
6543 new_lines[i]->set_manifold_id(hex->manifold_id());
6544 }
6545
6546 std::array<raw_quad_iterator, 12> new_quads;
6547 for (unsigned int i = 0; i < n_new_quads; ++i)
6548 {
6549 new_quads[i] =
6550 triangulation.faces->quads
6551 .template next_free_single_object<2>(triangulation);
6552
6553 auto &new_quad = new_quads[i];
6554
6555 // TODO: faces of children have the same type as the faces
6556 // of the parent
6557 triangulation.faces->set_quad_type(
6558 new_quad->index(),
6559 reference_cell_type.face_reference_cell(0));
6560
6561 AssertIsNotUsed(new_quad);
6562 new_quad->set_used_flag();
6563 new_quad->clear_user_flag();
6564 new_quad->clear_user_data();
6565 new_quad->clear_children();
6566 new_quad->set_boundary_id_internal(
6568 new_quad->set_manifold_id(hex->manifold_id());
6569 for (const auto j : new_quads[i]->line_indices())
6570 new_quad->set_line_orientation(j, true);
6571 }
6572
6573 // we always get 8 children per refined cell
6574 std::array<
6576 8>
6577 new_hexes;
6578 {
6579 for (unsigned int i = 0; i < n_new_hexes; ++i)
6580 {
6581 if (i % 2 == 0)
6582 next_unused_hex =
6583 triangulation.levels[level + 1]->cells.next_free_hex(
6584 triangulation, level + 1);
6585 else
6586 ++next_unused_hex;
6587
6588 new_hexes[i] = next_unused_hex;
6589
6590 auto &new_hex = new_hexes[i];
6591
6592 // children have the same type as the parent
6593 triangulation.levels[new_hex->level()]
6594 ->reference_cell[new_hex->index()] =
6595 reference_cell_type;
6596
6597 AssertIsNotUsed(new_hex);
6598 new_hex->set_used_flag();
6599 new_hex->clear_user_flag();
6600 new_hex->clear_user_data();
6601 new_hex->clear_children();
6602 new_hex->set_material_id(hex->material_id());
6603 new_hex->set_manifold_id(hex->manifold_id());
6604 new_hex->set_subdomain_id(hex->subdomain_id());
6605
6606 if (i % 2)
6607 new_hex->set_parent(hex->index());
6608
6609 // set the orientation flag to its default state for all
6610 // faces initially. later on go the other way round and
6611 // reset faces that are at the boundary of the mother cube
6612 for (const auto f : new_hex->face_indices())
6613 new_hex->set_combined_face_orientation(
6614 f,
6616 }
6617 for (unsigned int i = 0; i < n_new_hexes / 2; ++i)
6618 hex->set_children(2 * i, new_hexes[2 * i]->index());
6619 }
6620
6621 {
6622 // load vertex indices
6623 std::array<unsigned int, 27> vertex_indices = {};
6624
6625 {
6626 unsigned int k = 0;
6627
6628 // avoid a compiler warning by fixing the max number of
6629 // loop iterations to 8
6630 const unsigned int n_vertices =
6631 std::min(hex->n_vertices(), 8u);
6632 for (unsigned int i = 0; i < n_vertices; ++i)
6633 vertex_indices[k++] = hex->vertex_index(i);
6634
6635 const std::array<unsigned int, 12> line_indices =
6636 TriaAccessorImplementation::Implementation::
6637 get_line_indices_of_cell(*hex);
6638
6639 // For the tetrahedron the parent consists of the vertices
6640 // 0,1,2,3, the new vertices 4-9 are defined as the
6641 // midpoints of the edges: 4 -> (0,1), 5 -> (1,2), 6 ->
6642 // (2,0), 7 -> (0,3), 8 -> (1,3), 9 -> (2,3).
6643 // Order is defined by the reference cell, see
6644 // https://dealii.org/developer/doxygen/deal.II/group__simplex.html#simplex_reference_cells.
6645
6646 // Avoid a compiler warning by fixing the max number of loop
6647 // iterations to 12
6648 const unsigned int n_lines = std::min(hex->n_lines(), 12u);
6649 for (unsigned int l = 0; l < n_lines; ++l)
6650 {
6651 raw_line_iterator line(&triangulation,
6652 0,
6653 line_indices[l]);
6654 vertex_indices[k++] = line->child(0)->vertex_index(1);
6655 }
6656
6657 if (reference_cell_type == ReferenceCells::Hexahedron)
6658 {
6659 for (const unsigned int i : hex->face_indices())
6660 vertex_indices[k++] =
6661 hex->face(i)->child(0)->vertex_index(3);
6662
6663 // Set single new vertex in the center
6664 current_vertex =
6665 get_next_unused_vertex(current_vertex,
6667 vertex_indices[k++] = current_vertex;
6668
6669 triangulation.vertices[current_vertex] =
6670 hex->center(true, true);
6671 }
6672 }
6673
6674 unsigned int chosen_line_tetrahedron = 0;
6675 // set up new lines
6676 if (reference_cell_type == ReferenceCells::Hexahedron)
6677 {
6678 static constexpr ::ndarray<unsigned int, 6, 2>
6679 new_line_vertices = {{{{22, 26}},
6680 {{26, 23}},
6681 {{20, 26}},
6682 {{26, 21}},
6683 {{24, 26}},
6684 {{26, 25}}}};
6685 for (unsigned int i = 0; i < n_new_lines; ++i)
6686 new_lines[i]->set_bounding_object_indices(
6687 {vertex_indices[new_line_vertices[i][0]],
6688 vertex_indices[new_line_vertices[i][1]]});
6689 }
6690 else if (reference_cell_type == ReferenceCells::Tetrahedron)
6691 {
6692 // in the tetrahedron case, we have the three
6693 // possibilities (6,8), (5,7), (4,9) -> pick the
6694 // shortest line to guarantee the best possible aspect
6695 // ratios
6696 static constexpr ::ndarray<unsigned int, 3, 2>
6697 new_line_vertices = {{{{6, 8}}, {{5, 7}}, {{4, 9}}}};
6698
6699 // choose line to cut either by refinement case or by
6700 // shortest distance between edge midpoints
6701 std::uint8_t refinement_choice = hex->refine_choice();
6702 if (refinement_choice ==
6703 static_cast<char>(
6705 {
6706 const auto &vertices = triangulation.get_vertices();
6707 double min_distance =
6708 std::numeric_limits<double>::infinity();
6709 for (unsigned int i = 0; i < new_line_vertices.size();
6710 ++i)
6711 {
6712 const double current_distance =
6713 vertices
6714 [vertex_indices[new_line_vertices[i][0]]]
6715 .distance(
6717 [new_line_vertices[i][1]]]);
6718 if (current_distance < min_distance)
6719 {
6720 chosen_line_tetrahedron = i;
6721 min_distance = current_distance;
6722 }
6723 }
6724 }
6725 else if (refinement_choice ==
6726 static_cast<char>(
6728 chosen_line_tetrahedron = 0;
6729 else if (refinement_choice ==
6730 static_cast<char>(
6732 chosen_line_tetrahedron = 1;
6733 else if (refinement_choice ==
6734 static_cast<char>(
6736 chosen_line_tetrahedron = 2;
6737 else
6739
6740 hex->set_refinement_case(
6741 RefinementCase<dim>(chosen_line_tetrahedron + 1));
6742
6743 new_lines[0]->set_bounding_object_indices(
6745 [new_line_vertices[chosen_line_tetrahedron][0]],
6747 [new_line_vertices[chosen_line_tetrahedron][1]]});
6748 }
6749
6750 // set up new quads
6751 {
6752 boost::container::small_vector<raw_line_iterator, 30>
6753 relevant_lines;
6754
6755 if (reference_cell_type == ReferenceCells::Hexahedron)
6756 {
6757 relevant_lines.resize(30);
6758 for (unsigned int f = 0, k = 0; f < 6; ++f)
6759 for (unsigned int c = 0; c < 4; ++c, ++k)
6760 {
6761 static constexpr ::
6762 ndarray<unsigned int, 4, 2>
6763 temp = {
6764 {{{0, 1}}, {{3, 0}}, {{0, 3}}, {{3, 2}}}};
6765
6766 relevant_lines[k] =
6767 hex->face(f)
6768 ->isotropic_child(
6770 standard_to_real_face_vertex(
6771 temp[c][0],
6772 hex->face_orientation(f),
6773 hex->face_flip(f),
6774 hex->face_rotation(f)))
6775 ->line(GeometryInfo<dim>::
6776 standard_to_real_face_line(
6777 temp[c][1],
6778 hex->face_orientation(f),
6779 hex->face_flip(f),
6780 hex->face_rotation(f)));
6781 }
6782
6783 for (unsigned int i = 0, k = 24; i < 6; ++i, ++k)
6784 relevant_lines[k] = new_lines[i];
6785 }
6786 else if (reference_cell_type == ReferenceCells::Tetrahedron)
6787 {
6788 // The order of the lines is defined by the ordering
6789 // of the faces of the reference cell and the ordering
6790 // of the lines within a face.
6791 // Each face is split into 4 child triangles, the
6792 // relevant lines are defined by the vertices of the
6793 // center triangles: 0 -> (4,5), 1 -> (5,6), 2 -> (4,6),
6794 // 3 -> (4,7), 4 -> (7,8), 5 -> (4,8), 6 -> (6,9), 7 ->
6795 // (9,7), 8 -> (6,7), 9 -> (5,8), 10 -> (8,9), 11 ->
6796 // (5,9), Line 12 is determined by
6797 // chosen_line_tetrahedron i.e. (6,8), (5,7) or (4,9)
6798
6799 relevant_lines.resize(13);
6800
6801 unsigned int k = 0;
6802 for (unsigned int f = 0; f < 4; ++f)
6803 for (unsigned int l = 0; l < 3; ++l, ++k)
6804 {
6805 // TODO: add comment
6806 static const std::
6807 array<std::array<unsigned int, 3>, 6>
6808 table = {{{{1, 0, 2}}, // 0
6809 {{0, 1, 2}},
6810 {{0, 2, 1}}, // 2
6811 {{1, 2, 0}},
6812 {{2, 1, 0}}, // 4
6813 {{2, 0, 1}}}};
6814
6815 const unsigned char combined_orientation =
6816 hex->combined_face_orientation(f);
6817 relevant_lines[k] =
6818 hex->face(f)
6819 ->child(3 /*center triangle*/)
6820 ->line(table[combined_orientation][l]);
6821 }
6822
6823 relevant_lines[k++] = new_lines[0];
6824 AssertDimension(k, 13);
6825 }
6826 else
6828
6829 boost::container::small_vector<unsigned int, 30>
6830 relevant_line_indices(relevant_lines.size());
6831 for (unsigned int i = 0; i < relevant_line_indices.size();
6832 ++i)
6833 relevant_line_indices[i] = relevant_lines[i]->index();
6834
6835 // It is easierst to start at table cell_vertices,
6836 // there the vertices are listed which build up the
6837 // 8 child tets. To build the child tets, 8 new faces are
6838 // needed. The the vertices, which define the lines of these
6839 // new faces are listed in table_tet. Now only the
6840 // corresponding index of the lines and quads have to be
6841 // listed in new_quad_lines_tet and cell_quads_tet.
6842 const auto &new_quad_lines =
6843 hex->reference_cell().new_isotropic_child_face_lines(
6844 chosen_line_tetrahedron);
6845
6846 // The first 4 define the faces which cut off the
6847 // parent tetrahedron at the edges. the numbers are the
6848 // index of the relevant_lines defined above the last 4
6849 // faces cut apart the remaining octahedron, such that all
6850 // of these contain line number 12. the ordering of the
6851 // faces is arbitrary, the ordering within the faces has to
6852 // follow the righthand convention for triangles
6853 // The table defines the vertices of the lines above
6854 // see relevant_lines for mapping between line indices and
6855 // vertex numbering
6856 const auto &table =
6857 hex->reference_cell()
6858 .new_isotropic_child_face_line_vertices(
6859 chosen_line_tetrahedron);
6860
6861 static constexpr ::ndarray<unsigned int, 4, 2>
6862 representative_lines{
6863 {{{0, 2}}, {{2, 0}}, {{3, 3}}, {{1, 1}}}};
6864
6865 for (unsigned int q = 0; q < n_new_quads; ++q)
6866 {
6867 auto &new_quad = new_quads[q];
6868
6869 if (new_quad->n_lines() == 3)
6870 new_quad->set_bounding_object_indices(
6871 {relevant_line_indices[new_quad_lines[q][0]],
6872 relevant_line_indices[new_quad_lines[q][1]],
6873 relevant_line_indices[new_quad_lines[q][2]]});
6874 else if (new_quad->n_lines() == 4)
6875 new_quad->set_bounding_object_indices(
6876 {relevant_line_indices[new_quad_lines[q][0]],
6877 relevant_line_indices[new_quad_lines[q][1]],
6878 relevant_line_indices[new_quad_lines[q][2]],
6879 relevant_line_indices[new_quad_lines[q][3]]});
6880 else
6882
6883 // On hexes, we must only determine a single line
6884 // according to the representative_lines array above
6885 // (this saves expensive operations), for tets we do
6886 // all lines manually
6887 const unsigned int n_compute_lines =
6888 reference_cell_type == ReferenceCells::Hexahedron ?
6889 1 :
6890 new_quad->n_lines();
6891 for (unsigned int line = 0; line < n_compute_lines;
6892 ++line)
6893 {
6894 const unsigned int l =
6895 (reference_cell_type ==
6897 representative_lines[q % 4][0] :
6898 line;
6899
6900 const std::array<unsigned int, 2> vertices_0 = {
6901 {relevant_lines[new_quad_lines[q][l]]
6902 ->vertex_index(0),
6903 relevant_lines[new_quad_lines[q][l]]
6904 ->vertex_index(1)}};
6905
6906 const std::array<unsigned int, 2> vertices_1 = {
6907 {vertex_indices[table[q][l][0]],
6908 vertex_indices[table[q][l][1]]}};
6909
6910 const auto orientation =
6912 make_array_view(vertices_0),
6913 make_array_view(vertices_1));
6914
6915 new_quad->set_line_orientation(
6916 l,
6917 orientation ==
6919 default_combined_face_orientation());
6920
6921 // on a hex, inject the status of the current line
6922 // also to the line on the other quad along the
6923 // same direction
6924 if (reference_cell_type ==
6926 new_quads[representative_lines[q % 4][1] + q -
6927 (q % 4)]
6928 ->set_line_orientation(
6929 l,
6930 orientation ==
6932 default_combined_face_orientation());
6933 }
6934 }
6935 }
6936
6937 // set up new hex
6938 {
6939 std::array<int, 36> quad_indices;
6940
6941 if (reference_cell_type == ReferenceCells::Hexahedron)
6942 {
6943 for (unsigned int i = 0; i < n_new_quads; ++i)
6944 quad_indices[i] = new_quads[i]->index();
6945
6946 for (unsigned int f = 0, k = n_new_quads; f < 6; ++f)
6947 for (unsigned int c = 0; c < 4; ++c, ++k)
6948 quad_indices[k] =
6949 hex->face(f)->isotropic_child_index(
6951 c,
6952 hex->face_orientation(f),
6953 hex->face_flip(f),
6954 hex->face_rotation(f)));
6955 }
6956 else if (reference_cell_type == ReferenceCells::Tetrahedron)
6957 {
6958 // list of the indices of the surfaces which define the
6959 // 8 new tets. the indices 0-7 are the new quads defined
6960 // above (so 0-3 cut off the corners and 4-7 separate
6961 // the remaining octahedral), the indices between 8-11
6962 // are the children of the first face, from 12-15 of the
6963 // second, etc.
6964 for (unsigned int i = 0; i < n_new_quads; ++i)
6965 quad_indices[i] = new_quads[i]->index();
6966
6967 for (unsigned int f = 0, k = n_new_quads; f < 4; ++f)
6968 for (unsigned int c = 0; c < 4; ++c, ++k)
6969 {
6970 const unsigned char combined_orientation =
6971 hex->combined_face_orientation(f);
6972 quad_indices[k] = hex->face(f)->child_index(
6973 (c == 3) ? 3 :
6974 reference_cell_type
6975 .standard_to_real_face_vertex(
6976 c, f, combined_orientation));
6977 }
6978 }
6979 else
6980 {
6982 }
6983
6984 // indices of the faces which define the new tets
6985 // the ordering of the tets is arbitrary
6986 // the first 4 determine the tets cutting of the corners
6987 // the last 4 are ordered after their appearance in the
6988 // faces.
6989 // the ordering within the faces is determined by
6990 // convention for the tetrahedron unit cell, see
6991 // cell_vertices_tet below
6992 const auto &cell_quads =
6993 hex->reference_cell().new_isotropic_child_cell_faces(
6994 chosen_line_tetrahedron);
6995
6996 for (unsigned int c = 0;
6997 c < GeometryInfo<dim>::max_children_per_cell;
6998 ++c)
6999 {
7000 auto &new_hex = new_hexes[c];
7001
7002 if (new_hex->n_faces() == 4)
7003 {
7004 new_hex->set_bounding_object_indices(
7005 {quad_indices[cell_quads[c][0]],
7006 quad_indices[cell_quads[c][1]],
7007 quad_indices[cell_quads[c][2]],
7008 quad_indices[cell_quads[c][3]]});
7009
7010
7011 // for tets, we need to go through the faces and
7012 // figure the orientation out the hard way
7013 for (const auto f : new_hex->face_indices())
7014 {
7015 const auto &face = new_hex->face(f);
7016
7017 Assert(face->n_vertices() == 3,
7019
7020 const std::array<unsigned int, 3> vertices_0 = {
7021 {face->vertex_index(0),
7022 face->vertex_index(1),
7023 face->vertex_index(2)}};
7024
7025 // the 8 child tets are each defined by 4
7026 // vertices the ordering of the tets has to be
7027 // consistent with above the ordering within the
7028 // tets is given by the reference tet i.e.
7029 // looking at the fifth line the first 3
7030 // vertices are given by face 11, the last
7031 // vertex is the remaining of the tet
7032 const auto new_hex_vertices =
7033 hex->reference_cell()
7034 .new_isotropic_child_cell_vertices(
7035 chosen_line_tetrahedron)[c];
7036
7037 // arrange after vertices of the faces of the
7038 // unit cell
7039 const std::array<unsigned int, 3> vertices_1 = {
7040 {
7042 [new_hex_vertices
7044 .face_to_cell_vertices(f, 0, 1)]],
7046 [new_hex_vertices
7048 .face_to_cell_vertices(f, 1, 1)]],
7050 [new_hex_vertices
7052 .face_to_cell_vertices(f, 2, 1)]],
7053 }};
7054
7055 new_hex->set_combined_face_orientation(
7056 f,
7057 face->reference_cell()
7058 .get_combined_orientation(
7059 make_array_view(vertices_1),
7060 make_array_view(vertices_0)));
7061 }
7062 }
7063 else if (new_hex->n_faces() == 6)
7064 new_hex->set_bounding_object_indices(
7065 {quad_indices[cell_quads[c][0]],
7066 quad_indices[cell_quads[c][1]],
7067 quad_indices[cell_quads[c][2]],
7068 quad_indices[cell_quads[c][3]],
7069 quad_indices[cell_quads[c][4]],
7070 quad_indices[cell_quads[c][5]]});
7071 else
7073 }
7074
7075 // for hexes, we can simply inherit the orientation values
7076 // from the parent on the outer faces; the inner faces can
7077 // be skipped as their orientation is always the default
7078 // one set above
7079 static constexpr ::ndarray<unsigned int, 6, 4>
7080 face_to_child_indices_hex{{{{0, 2, 4, 6}},
7081 {{1, 3, 5, 7}},
7082 {{0, 1, 4, 5}},
7083 {{2, 3, 6, 7}},
7084 {{0, 1, 2, 3}},
7085 {{4, 5, 6, 7}}}};
7086 if (hex->n_faces() == 6)
7087 for (const auto f : hex->face_indices())
7088 {
7089 const unsigned char combined_orientation =
7090 hex->combined_face_orientation(f);
7091 for (unsigned int c = 0; c < 4; ++c)
7092 new_hexes[face_to_child_indices_hex[f][c]]
7093 ->set_combined_face_orientation(
7094 f, combined_orientation);
7095 }
7096 }
7097 }
7098
7099 if (check_for_distorted_cells &&
7100 has_distorted_children<dim, spacedim>(hex))
7101 cells_with_distorted_children.distorted_cells.push_back(hex);
7102
7103 triangulation.signals.post_refinement_on_cell(hex);
7104 }
7105 }
7106
7107 triangulation.faces->quads.clear_user_data();
7108
7109 return cells_with_distorted_children;
7110 }
7111
7116 template <int spacedim>
7119 const bool check_for_distorted_cells)
7120 {
7121 const unsigned int dim = 3;
7122
7123 {
7124 bool flag_isotropic_mesh = true;
7126 cell = triangulation.begin(),
7127 endc = triangulation.end();
7128 for (; cell != endc; ++cell)
7129 if (cell->used())
7131 cell->refine_flag_set() == RefinementCase<dim>::cut_x ||
7132 cell->refine_flag_set() == RefinementCase<dim>::cut_y ||
7133 cell->refine_flag_set() == RefinementCase<dim>::cut_z ||
7134 cell->refine_flag_set() == RefinementCase<dim>::cut_xy ||
7135 cell->refine_flag_set() == RefinementCase<dim>::cut_xz ||
7136 cell->refine_flag_set() == RefinementCase<dim>::cut_yz)
7137 {
7138 flag_isotropic_mesh = false;
7139 break;
7140 }
7141
7142 if (flag_isotropic_mesh)
7143 return execute_refinement_isotropic(triangulation,
7144 check_for_distorted_cells);
7145 }
7146
7147 // this function probably also works for spacedim>3 but it
7148 // isn't tested. it will probably be necessary to pull new
7149 // vertices onto the manifold just as we do for the other
7150 // functions above.
7151 Assert(spacedim == 3, ExcNotImplemented());
7152
7153 // Check whether a new level is needed. We have to check for
7154 // this on the highest level only
7155 for (const auto &cell : triangulation.active_cell_iterators_on_level(
7156 triangulation.levels.size() - 1))
7157 if (cell->refine_flag_set())
7158 {
7159 triangulation.levels.push_back(
7160 std::make_unique<
7162 break;
7163 }
7164
7165
7166 // first clear user flags for quads and lines; we're going to
7167 // use them to flag which lines and quads need refinement
7168 triangulation.faces->quads.clear_user_data();
7169
7172 line != triangulation.end_line();
7173 ++line)
7174 line->clear_user_flag();
7177 quad != triangulation.end_quad();
7178 ++quad)
7179 quad->clear_user_flag();
7180
7181 // create an array of face refine cases. User indices of faces
7182 // will be set to values corresponding with indices in this
7183 // array.
7184 const RefinementCase<dim - 1> face_refinement_cases[4] = {
7185 RefinementCase<dim - 1>::no_refinement,
7186 RefinementCase<dim - 1>::cut_x,
7187 RefinementCase<dim - 1>::cut_y,
7188 RefinementCase<dim - 1>::cut_xy};
7189
7190 // check how much space is needed on every level. We need not
7191 // check the highest level since either
7192 // - on the highest level no cells are flagged for refinement
7193 // - there are, but prepare_refinement added another empty
7194 // level which then is the highest level
7195
7196 // variables to hold the number of newly to be created
7197 // vertices, lines and quads. as these are stored globally,
7198 // declare them outside the loop over al levels. we need lines
7199 // and quads in pairs for refinement of old ones and lines and
7200 // quads, that can be stored as single ones, as they are newly
7201 // created in the inside of an existing cell
7202 unsigned int needed_vertices = 0;
7203 unsigned int needed_lines_single = 0;
7204 unsigned int needed_quads_single = 0;
7205 unsigned int needed_lines_pair = 0;
7206 unsigned int needed_quads_pair = 0;
7207 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
7208 {
7209 // count number of flagged cells on this level and compute
7210 // how many new vertices and new lines will be needed
7211 unsigned int new_cells = 0;
7212
7213 for (const auto &acell :
7215 if (acell->refine_flag_set())
7216 {
7217 RefinementCase<dim> ref_case = acell->refine_flag_set();
7218
7219 // now for interior vertices, lines and quads, which
7220 // are needed in any case
7221 if (ref_case == RefinementCase<dim>::cut_x ||
7222 ref_case == RefinementCase<dim>::cut_y ||
7223 ref_case == RefinementCase<dim>::cut_z)
7224 {
7225 ++needed_quads_single;
7226 new_cells += 2;
7228 }
7229 else if (ref_case == RefinementCase<dim>::cut_xy ||
7230 ref_case == RefinementCase<dim>::cut_xz ||
7231 ref_case == RefinementCase<dim>::cut_yz)
7232 {
7233 ++needed_lines_single;
7234 needed_quads_single += 4;
7235 new_cells += 4;
7237 }
7238 else if (ref_case == RefinementCase<dim>::cut_xyz)
7239 {
7240 ++needed_vertices;
7241 needed_lines_single += 6;
7242 needed_quads_single += 12;
7243 new_cells += 8;
7244 }
7245 else
7246 {
7247 // we should never get here
7249 }
7250
7251 // mark all faces for refinement; checking locally
7252 // if and how the neighbor would like to refine
7253 // these is difficult so we only flag them and after
7254 // visiting all cells, we decide which faces need
7255 // which refinement;
7256 for (const unsigned int face :
7258 {
7260 aface = acell->face(face);
7261 // get the RefineCase this faces has for the
7262 // given RefineCase of the cell
7263 RefinementCase<dim - 1> face_ref_case =
7265 ref_case,
7266 face,
7267 acell->face_orientation(face),
7268 acell->face_flip(face),
7269 acell->face_rotation(face));
7270 // only do something, if this face has to be
7271 // refined
7272 if (face_ref_case)
7273 {
7274 if (face_ref_case ==
7276 {
7277 if (aface->n_active_descendants() < 4)
7278 // we use user_flags to denote needed
7279 // isotropic refinement
7280 aface->set_user_flag();
7281 }
7282 else if (aface->refinement_case() != face_ref_case)
7283 // we use user_indices to denote needed
7284 // anisotropic refinement. note, that we
7285 // can have at most one anisotropic
7286 // refinement case for this face, as
7287 // otherwise prepare_refinement() would
7288 // have changed one of the cells to yield
7289 // isotropic refinement at this
7290 // face. therefore we set the user_index
7291 // uniquely
7292 {
7293 Assert(aface->refinement_case() ==
7295 dim - 1>::isotropic_refinement ||
7296 aface->refinement_case() ==
7299 aface->set_user_index(face_ref_case);
7300 }
7301 }
7302 } // for all faces
7303
7304 // flag all lines, that have to be refined
7305 for (unsigned int line = 0;
7306 line < GeometryInfo<dim>::lines_per_cell;
7307 ++line)
7309 line) &&
7310 !acell->line(line)->has_children())
7311 acell->line(line)->set_user_flag();
7312
7313 } // if refine_flag set and for all cells on this level
7314
7315
7316 // count number of used cells on the next higher level
7317 const unsigned int used_cells =
7318 std::count(triangulation.levels[level + 1]->cells.used.begin(),
7319 triangulation.levels[level + 1]->cells.used.end(),
7320 true);
7321
7322
7323 // reserve space for the used_cells cells already existing
7324 // on the next higher level as well as for the
7325 // 8*flagged_cells that will be created on that level
7327 used_cells + new_cells,
7328 3,
7329 spacedim);
7330 // reserve space for 8*flagged_cells new hexes on the next
7331 // higher level
7332 reserve_space(triangulation.levels[level + 1]->cells, new_cells);
7333 } // for all levels
7334 // now count the quads and lines which were flagged for
7335 // refinement
7338 quad != triangulation.end_quad();
7339 ++quad)
7340 {
7341 if (quad->user_flag_set())
7342 {
7343 // isotropic refinement: 1 interior vertex, 4 quads
7344 // and 4 interior lines. we store the interior lines
7345 // in pairs in case the face is already or will be
7346 // refined anisotropically
7347 needed_quads_pair += 4;
7348 needed_lines_pair += 4;
7349 needed_vertices += 1;
7350 }
7351 if (quad->user_index())
7352 {
7353 // anisotropic refinement: 1 interior
7354 // line and two quads
7355 needed_quads_pair += 2;
7356 needed_lines_single += 1;
7357 // there is a kind of complicated situation here which
7358 // requires our attention. if the quad is refined
7359 // isotropcally, two of the interior lines will get a
7360 // new mother line - the interior line of our
7361 // anisotropically refined quad. if those two lines
7362 // are not consecutive, we cannot do so and have to
7363 // replace them by two lines that are consecutive. we
7364 // try to avoid that situation, but it may happen
7365 // nevertheless through repeated refinement and
7366 // coarsening. thus we have to check here, as we will
7367 // need some additional space to store those new lines
7368 // in case we need them...
7369 if (quad->has_children())
7370 {
7371 Assert(quad->refinement_case() ==
7374 if ((face_refinement_cases[quad->user_index()] ==
7376 (quad->child(0)->line_index(1) + 1 !=
7377 quad->child(2)->line_index(1))) ||
7378 (face_refinement_cases[quad->user_index()] ==
7380 (quad->child(0)->line_index(3) + 1 !=
7381 quad->child(1)->line_index(3))))
7382 needed_lines_pair += 2;
7383 }
7384 }
7385 }
7386
7389 line != triangulation.end_line();
7390 ++line)
7391 if (line->user_flag_set())
7392 {
7393 needed_lines_pair += 2;
7394 needed_vertices += 1;
7395 }
7396
7397 // reserve space for needed_lines new lines stored in pairs
7399 needed_lines_pair,
7400 needed_lines_single);
7401 // reserve space for needed_quads new quads stored in pairs
7403 needed_quads_pair,
7404 needed_quads_single);
7406 needed_quads_pair,
7407 needed_quads_single);
7408
7409
7410 // add to needed vertices how many vertices are already in use
7411 needed_vertices += std::count(triangulation.vertices_used.begin(),
7413 true);
7414 // if we need more vertices: create them, if not: leave the
7415 // array as is, since shrinking is not really possible because
7416 // some of the vertices at the end may be in use
7417 if (needed_vertices > triangulation.vertices.size())
7418 {
7419 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
7420 triangulation.vertices_used.resize(needed_vertices, false);
7421 }
7422
7423
7424 //-----------------------------------------
7425 // Before we start with the actual refinement, we do some
7426 // sanity checks if in debug mode. especially, we try to catch
7427 // the notorious problem with lines being twice refined,
7428 // i.e. there are cells adjacent at one line ("around the
7429 // edge", but not at a face), with two cells differing by more
7430 // than one refinement level
7431 //
7432 // this check is very simple to implement here, since we have
7433 // all lines flagged if they shall be refined
7434#ifdef DEBUG
7435 for (const auto &cell : triangulation.active_cell_iterators())
7436 if (!cell->refine_flag_set())
7437 for (unsigned int line = 0;
7438 line < GeometryInfo<dim>::lines_per_cell;
7439 ++line)
7440 if (cell->line(line)->has_children())
7441 for (unsigned int c = 0; c < 2; ++c)
7442 Assert(cell->line(line)->child(c)->user_flag_set() == false,
7444#endif
7445
7446 //-----------------------------------------
7447 // Do refinement on every level
7448 //
7449 // To make life a bit easier, we first refine those lines and
7450 // quads that were flagged for refinement and then compose the
7451 // newly to be created cells.
7452 //
7453 // index of next unused vertex
7454 unsigned int next_unused_vertex = 0;
7455
7456 // first for lines
7457 {
7458 // only active objects can be refined further
7461 endl = triangulation.end_line();
7463 next_unused_line = triangulation.begin_raw_line();
7464
7465 for (; line != endl; ++line)
7466 if (line->user_flag_set())
7467 {
7468 // this line needs to be refined
7469
7470 // find the next unused vertex and set it
7471 // appropriately
7472 while (triangulation.vertices_used[next_unused_vertex] == true)
7473 ++next_unused_vertex;
7474 Assert(
7475 next_unused_vertex < triangulation.vertices.size(),
7476 ExcMessage(
7477 "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."));
7478 triangulation.vertices_used[next_unused_vertex] = true;
7479
7480 triangulation.vertices[next_unused_vertex] = line->center(true);
7481
7482 // now that we created the right point, make up the
7483 // two child lines (++ takes care of the end of the
7484 // vector)
7485 next_unused_line =
7486 triangulation.faces->lines.template next_free_pair_object<1>(
7488 Assert(next_unused_line.state() == IteratorState::valid,
7490
7491 // now we found two consecutive unused lines, such
7492 // that the children of a line will be consecutive.
7493 // then set the child pointer of the present line
7494 line->set_children(0, next_unused_line->index());
7495
7496 // set the two new lines
7498 children[2] = {next_unused_line, ++next_unused_line};
7499
7500 // some tests; if any of the iterators should be
7501 // invalid, then already dereferencing will fail
7502 AssertIsNotUsed(children[0]);
7503 AssertIsNotUsed(children[1]);
7504
7505 children[0]->set_bounding_object_indices(
7506 {line->vertex_index(0), next_unused_vertex});
7507 children[1]->set_bounding_object_indices(
7508 {next_unused_vertex, line->vertex_index(1)});
7509
7510 children[0]->set_used_flag();
7511 children[1]->set_used_flag();
7512 children[0]->clear_children();
7513 children[1]->clear_children();
7514 children[0]->clear_user_data();
7515 children[1]->clear_user_data();
7516 children[0]->clear_user_flag();
7517 children[1]->clear_user_flag();
7518
7519 children[0]->set_boundary_id_internal(line->boundary_id());
7520 children[1]->set_boundary_id_internal(line->boundary_id());
7521
7522 children[0]->set_manifold_id(line->manifold_id());
7523 children[1]->set_manifold_id(line->manifold_id());
7524
7525 // finally clear flag
7526 // indicating the need
7527 // for refinement
7528 line->clear_user_flag();
7529 }
7530 }
7531
7532
7533 //-------------------------------------
7534 // now refine marked quads
7535 //-------------------------------------
7536
7537 // here we encounter several cases:
7538
7539 // a) the quad is unrefined and shall be refined isotropically
7540
7541 // b) the quad is unrefined and shall be refined
7542 // anisotropically
7543
7544 // c) the quad is unrefined and shall be refined both
7545 // anisotropically and isotropically (this is reduced to case
7546 // b) and then case b) for the children again)
7547
7548 // d) the quad is refined anisotropically and shall be refined
7549 // isotropically (this is reduced to case b) for the
7550 // anisotropic children)
7551
7552 // e) the quad is refined isotropically and shall be refined
7553 // anisotropically (this is transformed to case c), however we
7554 // might have to renumber/rename children...)
7555
7556 // we need a loop in cases c) and d), as the anisotropic
7557 // children might have a lower index than the mother quad
7558 for (unsigned int loop = 0; loop < 2; ++loop)
7559 {
7560 // usually, only active objects can be refined
7561 // further. however, in cases d) and e) that is not true,
7562 // so we have to use 'normal' iterators here
7564 quad = triangulation.begin_quad(),
7565 endq = triangulation.end_quad();
7567 next_unused_line = triangulation.begin_raw_line();
7569 next_unused_quad = triangulation.begin_raw_quad();
7570
7571 for (; quad != endq; ++quad)
7572 {
7573 if (quad->user_index())
7574 {
7575 RefinementCase<dim - 1> aniso_quad_ref_case =
7576 face_refinement_cases[quad->user_index()];
7577 // there is one unlikely event here, where we
7578 // already have refind the face: if the face was
7579 // refined anisotropically and we want to refine
7580 // it isotropically, both children are flagged for
7581 // anisotropic refinement. however, if those
7582 // children were already flagged for anisotropic
7583 // refinement, they might already be processed and
7584 // refined.
7585 if (aniso_quad_ref_case == quad->refinement_case())
7586 continue;
7587
7588 Assert(quad->refinement_case() ==
7590 quad->refinement_case() ==
7593
7594 // this quad needs to be refined anisotropically
7595 Assert(quad->user_index() ==
7597 quad->user_index() ==
7600
7601 // make the new line interior to the quad
7603 new_line;
7604
7605 new_line =
7606 triangulation.faces->lines
7607 .template next_free_single_object<1>(triangulation);
7608 AssertIsNotUsed(new_line);
7609
7610 // first collect the
7611 // indices of the vertices:
7612 // *--1--*
7613 // | | |
7614 // | | | cut_x
7615 // | | |
7616 // *--0--*
7617 //
7618 // *-----*
7619 // | |
7620 // 0-----1 cut_y
7621 // | |
7622 // *-----*
7623 unsigned int vertex_indices[2];
7624 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
7625 {
7626 vertex_indices[0] =
7627 quad->line(2)->child(0)->vertex_index(1);
7628 vertex_indices[1] =
7629 quad->line(3)->child(0)->vertex_index(1);
7630 }
7631 else
7632 {
7633 vertex_indices[0] =
7634 quad->line(0)->child(0)->vertex_index(1);
7635 vertex_indices[1] =
7636 quad->line(1)->child(0)->vertex_index(1);
7637 }
7638
7639 new_line->set_bounding_object_indices(
7641 new_line->set_used_flag();
7642 new_line->clear_user_flag();
7643 new_line->clear_user_data();
7644 new_line->clear_children();
7645 new_line->set_boundary_id_internal(quad->boundary_id());
7646 new_line->set_manifold_id(quad->manifold_id());
7647
7648 // child 0 and 1 of a line are switched if the
7649 // line orientation is false. set up a miniature
7650 // table, indicating which child to take for line
7651 // orientations false and true. first index: child
7652 // index in standard orientation, second index:
7653 // line orientation
7654 const unsigned int index[2][2] = {
7655 {1, 0}, // child 0, line_orientation=false and true
7656 {0, 1}}; // child 1, line_orientation=false and true
7657
7658 // find some space (consecutive) for the two newly
7659 // to be created quads.
7661 new_quads[2];
7662
7663 next_unused_quad =
7664 triangulation.faces->quads
7665 .template next_free_pair_object<2>(triangulation);
7666 new_quads[0] = next_unused_quad;
7667 AssertIsNotUsed(new_quads[0]);
7668
7669 ++next_unused_quad;
7670 new_quads[1] = next_unused_quad;
7671 AssertIsNotUsed(new_quads[1]);
7672
7673 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
7674 {
7675 new_quads[0]->set_bounding_object_indices(
7676 {static_cast<int>(quad->line_index(0)),
7677 new_line->index(),
7678 quad->line(2)
7679 ->child(index[0][quad->line_orientation(2)])
7680 ->index(),
7681 quad->line(3)
7682 ->child(index[0][quad->line_orientation(3)])
7683 ->index()});
7684 new_quads[1]->set_bounding_object_indices(
7685 {new_line->index(),
7686 static_cast<int>(quad->line_index(1)),
7687 quad->line(2)
7688 ->child(index[1][quad->line_orientation(2)])
7689 ->index(),
7690 quad->line(3)
7691 ->child(index[1][quad->line_orientation(3)])
7692 ->index()});
7693 }
7694 else
7695 {
7696 new_quads[0]->set_bounding_object_indices(
7697 {quad->line(0)
7698 ->child(index[0][quad->line_orientation(0)])
7699 ->index(),
7700 quad->line(1)
7701 ->child(index[0][quad->line_orientation(1)])
7702 ->index(),
7703 static_cast<int>(quad->line_index(2)),
7704 new_line->index()});
7705 new_quads[1]->set_bounding_object_indices(
7706 {quad->line(0)
7707 ->child(index[1][quad->line_orientation(0)])
7708 ->index(),
7709 quad->line(1)
7710 ->child(index[1][quad->line_orientation(1)])
7711 ->index(),
7712 new_line->index(),
7713 static_cast<int>(quad->line_index(3))});
7714 }
7715
7716 for (const auto &new_quad : new_quads)
7717 {
7718 new_quad->set_used_flag();
7719 new_quad->clear_user_flag();
7720 new_quad->clear_user_data();
7721 new_quad->clear_children();
7722 new_quad->set_boundary_id_internal(quad->boundary_id());
7723 new_quad->set_manifold_id(quad->manifold_id());
7724 // set all line orientations to true, change
7725 // this after the loop, as we have to consider
7726 // different lines for each child
7727 for (unsigned int j = 0;
7728 j < GeometryInfo<dim>::lines_per_face;
7729 ++j)
7730 new_quad->set_line_orientation(j, true);
7731 }
7732 // now set the line orientation of children of
7733 // outer lines correctly, the lines in the
7734 // interior of the refined quad are automatically
7735 // oriented conforming to the standard
7736 new_quads[0]->set_line_orientation(
7737 0, quad->line_orientation(0));
7738 new_quads[0]->set_line_orientation(
7739 2, quad->line_orientation(2));
7740 new_quads[1]->set_line_orientation(
7741 1, quad->line_orientation(1));
7742 new_quads[1]->set_line_orientation(
7743 3, quad->line_orientation(3));
7744 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
7745 {
7746 new_quads[0]->set_line_orientation(
7747 3, quad->line_orientation(3));
7748 new_quads[1]->set_line_orientation(
7749 2, quad->line_orientation(2));
7750 }
7751 else
7752 {
7753 new_quads[0]->set_line_orientation(
7754 1, quad->line_orientation(1));
7755 new_quads[1]->set_line_orientation(
7756 0, quad->line_orientation(0));
7757 }
7758
7759 // test, whether this face is refined
7760 // isotropically already. if so, set the correct
7761 // children pointers.
7762 if (quad->refinement_case() ==
7763 RefinementCase<dim - 1>::cut_xy)
7764 {
7765 // we will put a new refinemnt level of
7766 // anisotropic refinement between the
7767 // unrefined and isotropically refined quad
7768 // ending up with the same fine quads but
7769 // introducing anisotropically refined ones as
7770 // children of the unrefined quad and mother
7771 // cells of the original fine ones.
7772
7773 // this process includes the creation of a new
7774 // middle line which we will assign as the
7775 // mother line of two of the existing inner
7776 // lines. If those inner lines are not
7777 // consecutive in memory, we won't find them
7778 // later on, so we have to create new ones
7779 // instead and replace all occurrences of the
7780 // old ones with those new ones. As this is
7781 // kind of ugly, we hope we don't have to do
7782 // it often...
7784 old_child[2];
7785 if (aniso_quad_ref_case ==
7787 {
7788 old_child[0] = quad->child(0)->line(1);
7789 old_child[1] = quad->child(2)->line(1);
7790 }
7791 else
7792 {
7793 Assert(aniso_quad_ref_case ==
7796
7797 old_child[0] = quad->child(0)->line(3);
7798 old_child[1] = quad->child(1)->line(3);
7799 }
7800
7801 if (old_child[0]->index() + 1 != old_child[1]->index())
7802 {
7803 // this is exactly the ugly case we taked
7804 // about. so, no coimplaining, lets get
7805 // two new lines and copy all info
7806 typename Triangulation<dim,
7807 spacedim>::raw_line_iterator
7808 new_child[2];
7809
7810 new_child[0] = new_child[1] =
7811 triangulation.faces->lines
7812 .template next_free_pair_object<1>(
7814 ++new_child[1];
7815
7816 new_child[0]->set_used_flag();
7817 new_child[1]->set_used_flag();
7818
7819 const int old_index_0 = old_child[0]->index(),
7820 old_index_1 = old_child[1]->index(),
7821 new_index_0 = new_child[0]->index(),
7822 new_index_1 = new_child[1]->index();
7823
7824 // loop over all quads and replace the old
7825 // lines
7826 for (unsigned int q = 0;
7827 q < triangulation.faces->quads.n_objects();
7828 ++q)
7829 for (unsigned int l = 0;
7830 l < GeometryInfo<dim>::lines_per_face;
7831 ++l)
7832 {
7833 const int this_index =
7834 triangulation.faces->quads
7835 .get_bounding_object_indices(q)[l];
7836 if (this_index == old_index_0)
7837 triangulation.faces->quads
7838 .get_bounding_object_indices(q)[l] =
7839 new_index_0;
7840 else if (this_index == old_index_1)
7841 triangulation.faces->quads
7842 .get_bounding_object_indices(q)[l] =
7843 new_index_1;
7844 }
7845 // now we have to copy all information of
7846 // the two lines
7847 for (unsigned int i = 0; i < 2; ++i)
7848 {
7849 Assert(!old_child[i]->has_children(),
7851
7852 new_child[i]->set_bounding_object_indices(
7853 {old_child[i]->vertex_index(0),
7854 old_child[i]->vertex_index(1)});
7855 new_child[i]->set_boundary_id_internal(
7856 old_child[i]->boundary_id());
7857 new_child[i]->set_manifold_id(
7858 old_child[i]->manifold_id());
7859 new_child[i]->set_user_index(
7860 old_child[i]->user_index());
7861 if (old_child[i]->user_flag_set())
7862 new_child[i]->set_user_flag();
7863 else
7864 new_child[i]->clear_user_flag();
7865
7866 new_child[i]->clear_children();
7867
7868 old_child[i]->clear_user_flag();
7869 old_child[i]->clear_user_index();
7870 old_child[i]->clear_used_flag();
7871 }
7872 }
7873 // now that we cared about the lines, go on
7874 // with the quads themselves, where we might
7875 // encounter similar situations...
7876 if (aniso_quad_ref_case ==
7878 {
7879 new_line->set_children(
7880 0, quad->child(0)->line_index(1));
7881 Assert(new_line->child(1) ==
7882 quad->child(2)->line(1),
7884 // now evereything is quite
7885 // complicated. we have the children
7886 // numbered according to
7887 //
7888 // *---*---*
7889 // |n+2|n+3|
7890 // *---*---*
7891 // | n |n+1|
7892 // *---*---*
7893 //
7894 // from the original isotropic
7895 // refinement. we have to reorder them as
7896 //
7897 // *---*---*
7898 // |n+1|n+3|
7899 // *---*---*
7900 // | n |n+2|
7901 // *---*---*
7902 //
7903 // such that n and n+1 are consecutive
7904 // children of m and n+2 and n+3 are
7905 // consecutive children of m+1, where m
7906 // and m+1 are given as in
7907 //
7908 // *---*---*
7909 // | | |
7910 // | m |m+1|
7911 // | | |
7912 // *---*---*
7913 //
7914 // this is a bit ugly, of course: loop
7915 // over all cells on all levels and look
7916 // for faces n+1 (switch_1) and n+2
7917 // (switch_2).
7918 const typename Triangulation<dim, spacedim>::
7919 quad_iterator switch_1 = quad->child(1),
7920 switch_2 = quad->child(2);
7921 const int switch_1_index = switch_1->index();
7922 const int switch_2_index = switch_2->index();
7923 for (unsigned int l = 0;
7924 l < triangulation.levels.size();
7925 ++l)
7926 for (unsigned int h = 0;
7927 h <
7928 triangulation.levels[l]->cells.n_objects();
7929 ++h)
7930 for (const unsigned int q :
7932 {
7933 const int face_index =
7935 ->cells.get_bounding_object_indices(
7936 h)[q];
7937 if (face_index == switch_1_index)
7939 ->cells.get_bounding_object_indices(
7940 h)[q] = switch_2_index;
7941 else if (face_index == switch_2_index)
7943 ->cells.get_bounding_object_indices(
7944 h)[q] = switch_1_index;
7945 }
7946 // now we have to copy all information of
7947 // the two quads
7948 const unsigned int switch_1_lines[4] = {
7949 switch_1->line_index(0),
7950 switch_1->line_index(1),
7951 switch_1->line_index(2),
7952 switch_1->line_index(3)};
7953 const bool switch_1_line_orientations[4] = {
7954 switch_1->line_orientation(0),
7955 switch_1->line_orientation(1),
7956 switch_1->line_orientation(2),
7957 switch_1->line_orientation(3)};
7958 const types::boundary_id switch_1_boundary_id =
7959 switch_1->boundary_id();
7960 const unsigned int switch_1_user_index =
7961 switch_1->user_index();
7962 const bool switch_1_user_flag =
7963 switch_1->user_flag_set();
7964 const RefinementCase<dim - 1>
7965 switch_1_refinement_case =
7966 switch_1->refinement_case();
7967 const int switch_1_first_child_pair =
7968 (switch_1_refinement_case ?
7969 switch_1->child_index(0) :
7970 -1);
7971 const int switch_1_second_child_pair =
7972 (switch_1_refinement_case ==
7973 RefinementCase<dim - 1>::cut_xy ?
7974 switch_1->child_index(2) :
7975 -1);
7976
7977 switch_1->set_bounding_object_indices(
7978 {switch_2->line_index(0),
7979 switch_2->line_index(1),
7980 switch_2->line_index(2),
7981 switch_2->line_index(3)});
7982 switch_1->set_line_orientation(
7983 0, switch_2->line_orientation(0));
7984 switch_1->set_line_orientation(
7985 1, switch_2->line_orientation(1));
7986 switch_1->set_line_orientation(
7987 2, switch_2->line_orientation(2));
7988 switch_1->set_line_orientation(
7989 3, switch_2->line_orientation(3));
7990 switch_1->set_boundary_id_internal(
7991 switch_2->boundary_id());
7992 switch_1->set_manifold_id(switch_2->manifold_id());
7993 switch_1->set_user_index(switch_2->user_index());
7994 if (switch_2->user_flag_set())
7995 switch_1->set_user_flag();
7996 else
7997 switch_1->clear_user_flag();
7998 switch_1->clear_refinement_case();
7999 switch_1->set_refinement_case(
8000 switch_2->refinement_case());
8001 switch_1->clear_children();
8002 if (switch_2->refinement_case())
8003 switch_1->set_children(0,
8004 switch_2->child_index(0));
8005 if (switch_2->refinement_case() ==
8006 RefinementCase<dim - 1>::cut_xy)
8007 switch_1->set_children(2,
8008 switch_2->child_index(2));
8009
8010 switch_2->set_bounding_object_indices(
8011 {switch_1_lines[0],
8012 switch_1_lines[1],
8013 switch_1_lines[2],
8014 switch_1_lines[3]});
8015 switch_2->set_line_orientation(
8016 0, switch_1_line_orientations[0]);
8017 switch_2->set_line_orientation(
8018 1, switch_1_line_orientations[1]);
8019 switch_2->set_line_orientation(
8020 2, switch_1_line_orientations[2]);
8021 switch_2->set_line_orientation(
8022 3, switch_1_line_orientations[3]);
8023 switch_2->set_boundary_id_internal(
8024 switch_1_boundary_id);
8025 switch_2->set_manifold_id(switch_1->manifold_id());
8026 switch_2->set_user_index(switch_1_user_index);
8027 if (switch_1_user_flag)
8028 switch_2->set_user_flag();
8029 else
8030 switch_2->clear_user_flag();
8031 switch_2->clear_refinement_case();
8032 switch_2->set_refinement_case(
8033 switch_1_refinement_case);
8034 switch_2->clear_children();
8035 switch_2->set_children(0,
8036 switch_1_first_child_pair);
8037 switch_2->set_children(2,
8038 switch_1_second_child_pair);
8039
8040 new_quads[0]->set_refinement_case(
8042 new_quads[0]->set_children(0, quad->child_index(0));
8043 new_quads[1]->set_refinement_case(
8045 new_quads[1]->set_children(0, quad->child_index(2));
8046 }
8047 else
8048 {
8049 new_quads[0]->set_refinement_case(
8051 new_quads[0]->set_children(0, quad->child_index(0));
8052 new_quads[1]->set_refinement_case(
8054 new_quads[1]->set_children(0, quad->child_index(2));
8055 new_line->set_children(
8056 0, quad->child(0)->line_index(3));
8057 Assert(new_line->child(1) ==
8058 quad->child(1)->line(3),
8060 }
8061 quad->clear_children();
8062 }
8063
8064 // note these quads as children to the present one
8065 quad->set_children(0, new_quads[0]->index());
8066
8067 quad->set_refinement_case(aniso_quad_ref_case);
8068
8069 // finally clear flag indicating the need for
8070 // refinement
8071 quad->clear_user_data();
8072 } // if (anisotropic refinement)
8073
8074 if (quad->user_flag_set())
8075 {
8076 // this quad needs to be refined isotropically
8077
8078 // first of all: we only get here in the first run
8079 // of the loop
8080 Assert(loop == 0, ExcInternalError());
8081
8082 // find the next unused vertex. we'll need this in
8083 // any case
8084 while (triangulation.vertices_used[next_unused_vertex] ==
8085 true)
8086 ++next_unused_vertex;
8087 Assert(
8088 next_unused_vertex < triangulation.vertices.size(),
8089 ExcMessage(
8090 "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."));
8091
8092 // now: if the quad is refined anisotropically
8093 // already, set the anisotropic refinement flag
8094 // for both children. Additionally, we have to
8095 // refine the inner line, as it is an outer line
8096 // of the two (anisotropic) children
8097 const RefinementCase<dim - 1> quad_ref_case =
8098 quad->refinement_case();
8099
8100 if (quad_ref_case == RefinementCase<dim - 1>::cut_x ||
8101 quad_ref_case == RefinementCase<dim - 1>::cut_y)
8102 {
8103 // set the 'opposite' refine case for children
8104 quad->child(0)->set_user_index(
8105 RefinementCase<dim - 1>::cut_xy - quad_ref_case);
8106 quad->child(1)->set_user_index(
8107 RefinementCase<dim - 1>::cut_xy - quad_ref_case);
8108 // refine the inner line
8110 middle_line;
8111 if (quad_ref_case == RefinementCase<dim - 1>::cut_x)
8112 middle_line = quad->child(0)->line(1);
8113 else
8114 middle_line = quad->child(0)->line(3);
8115
8116 // if the face has been refined
8117 // anisotropically in the last refinement step
8118 // it might be, that it is flagged already and
8119 // that the middle line is thus refined
8120 // already. if not create children.
8121 if (!middle_line->has_children())
8122 {
8123 // set the middle vertex
8124 // appropriately. double refinement of
8125 // quads can only happen in the interior
8126 // of the domain, so we need not care
8127 // about boundary quads here
8128 triangulation.vertices[next_unused_vertex] =
8129 middle_line->center(true);
8130 triangulation.vertices_used[next_unused_vertex] =
8131 true;
8132
8133 // now search a slot for the two
8134 // child lines
8135 next_unused_line =
8136 triangulation.faces->lines
8137 .template next_free_pair_object<1>(
8139
8140 // set the child pointer of the present
8141 // line
8142 middle_line->set_children(
8143 0, next_unused_line->index());
8144
8145 // set the two new lines
8146 const typename Triangulation<dim, spacedim>::
8147 raw_line_iterator children[2] = {
8148 next_unused_line, ++next_unused_line};
8149
8150 // some tests; if any of the iterators
8151 // should be invalid, then already
8152 // dereferencing will fail
8153 AssertIsNotUsed(children[0]);
8154 AssertIsNotUsed(children[1]);
8155
8156 children[0]->set_bounding_object_indices(
8157 {middle_line->vertex_index(0),
8158 next_unused_vertex});
8159 children[1]->set_bounding_object_indices(
8160 {next_unused_vertex,
8161 middle_line->vertex_index(1)});
8162
8163 children[0]->set_used_flag();
8164 children[1]->set_used_flag();
8165 children[0]->clear_children();
8166 children[1]->clear_children();
8167 children[0]->clear_user_data();
8168 children[1]->clear_user_data();
8169 children[0]->clear_user_flag();
8170 children[1]->clear_user_flag();
8171
8172 children[0]->set_boundary_id_internal(
8173 middle_line->boundary_id());
8174 children[1]->set_boundary_id_internal(
8175 middle_line->boundary_id());
8176
8177 children[0]->set_manifold_id(
8178 middle_line->manifold_id());
8179 children[1]->set_manifold_id(
8180 middle_line->manifold_id());
8181 }
8182 // now remove the flag from the quad and go to
8183 // the next quad, the actual refinement of the
8184 // quad takes place later on in this pass of
8185 // the loop or in the next one
8186 quad->clear_user_flag();
8187 continue;
8188 } // if (several refinement cases)
8189
8190 // if we got here, we have an unrefined quad and
8191 // have to do the usual work like in an purely
8192 // isotropic refinement
8193 Assert(quad_ref_case ==
8196
8197 // set the middle vertex appropriately: it might be that
8198 // the quad itself is not at the boundary, but that one of
8199 // its lines actually is. in this case, the newly created
8200 // vertices at the centers of the lines are not
8201 // necessarily the mean values of the adjacent vertices,
8202 // so do not compute the new vertex as the mean value of
8203 // the 4 vertices of the face, but rather as a weighted
8204 // mean value of the 8 vertices which we already have (the
8205 // four old ones, and the four ones inserted as middle
8206 // points for the four lines). summing up some more points
8207 // is generally cheaper than first asking whether one of
8208 // the lines is at the boundary
8209 //
8210 // note that the exact weights are chosen such as to
8211 // minimize the distortion of the four new quads from the
8212 // optimal shape. their description uses the formulas
8213 // underlying the TransfiniteInterpolationManifold
8214 // implementation
8215 triangulation.vertices[next_unused_vertex] =
8216 quad->center(true, true);
8217 triangulation.vertices_used[next_unused_vertex] = true;
8218
8219 // now that we created the right point, make up
8220 // the four lines interior to the quad (++ takes
8221 // care of the end of the vector)
8223 new_lines[4];
8224
8225 for (unsigned int i = 0; i < 4; ++i)
8226 {
8227 if (i % 2 == 0)
8228 // search a free pair of lines for 0. and
8229 // 2. line, so that two of them end up
8230 // together, which is necessary if later on
8231 // we want to refine the quad
8232 // anisotropically and the two lines end up
8233 // as children of new line
8234 next_unused_line =
8235 triangulation.faces->lines
8236 .template next_free_pair_object<1>(triangulation);
8237
8238 new_lines[i] = next_unused_line;
8239 ++next_unused_line;
8240
8241 AssertIsNotUsed(new_lines[i]);
8242 }
8243
8244 // set the data of the four lines. first collect
8245 // the indices of the five vertices:
8246 //
8247 // *--3--*
8248 // | | |
8249 // 0--4--1
8250 // | | |
8251 // *--2--*
8252 //
8253 // the lines are numbered as follows:
8254 //
8255 // *--*--*
8256 // | 1 |
8257 // *2-*-3*
8258 // | 0 |
8259 // *--*--*
8260
8261 const unsigned int vertex_indices[5] = {
8262 quad->line(0)->child(0)->vertex_index(1),
8263 quad->line(1)->child(0)->vertex_index(1),
8264 quad->line(2)->child(0)->vertex_index(1),
8265 quad->line(3)->child(0)->vertex_index(1),
8266 next_unused_vertex};
8267
8268 new_lines[0]->set_bounding_object_indices(
8270 new_lines[1]->set_bounding_object_indices(
8272 new_lines[2]->set_bounding_object_indices(
8274 new_lines[3]->set_bounding_object_indices(
8276
8277 for (const auto &new_line : new_lines)
8278 {
8279 new_line->set_used_flag();
8280 new_line->clear_user_flag();
8281 new_line->clear_user_data();
8282 new_line->clear_children();
8283 new_line->set_boundary_id_internal(quad->boundary_id());
8284 new_line->set_manifold_id(quad->manifold_id());
8285 }
8286
8287 // now for the quads. again, first collect some
8288 // data about the indices of the lines, with the
8289 // following numbering:
8290 //
8291 // .-6-.-7-.
8292 // 1 9 3
8293 // .-10.11-.
8294 // 0 8 2
8295 // .-4-.-5-.
8296
8297 // child 0 and 1 of a line are switched if the
8298 // line orientation is false. set up a miniature
8299 // table, indicating which child to take for line
8300 // orientations false and true. first index: child
8301 // index in standard orientation, second index:
8302 // line orientation
8303 const unsigned int index[2][2] = {
8304 {1, 0}, // child 0, line_orientation=false and true
8305 {0, 1}}; // child 1, line_orientation=false and true
8306
8307 const int line_indices[12] = {
8308 quad->line(0)
8309 ->child(index[0][quad->line_orientation(0)])
8310 ->index(),
8311 quad->line(0)
8312 ->child(index[1][quad->line_orientation(0)])
8313 ->index(),
8314 quad->line(1)
8315 ->child(index[0][quad->line_orientation(1)])
8316 ->index(),
8317 quad->line(1)
8318 ->child(index[1][quad->line_orientation(1)])
8319 ->index(),
8320 quad->line(2)
8321 ->child(index[0][quad->line_orientation(2)])
8322 ->index(),
8323 quad->line(2)
8324 ->child(index[1][quad->line_orientation(2)])
8325 ->index(),
8326 quad->line(3)
8327 ->child(index[0][quad->line_orientation(3)])
8328 ->index(),
8329 quad->line(3)
8330 ->child(index[1][quad->line_orientation(3)])
8331 ->index(),
8332 new_lines[0]->index(),
8333 new_lines[1]->index(),
8334 new_lines[2]->index(),
8335 new_lines[3]->index()};
8336
8337 // find some space (consecutive)
8338 // for the first two newly to be
8339 // created quads.
8341 new_quads[4];
8342
8343 next_unused_quad =
8344 triangulation.faces->quads
8345 .template next_free_pair_object<2>(triangulation);
8346
8347 new_quads[0] = next_unused_quad;
8348 AssertIsNotUsed(new_quads[0]);
8349
8350 ++next_unused_quad;
8351 new_quads[1] = next_unused_quad;
8352 AssertIsNotUsed(new_quads[1]);
8353
8354 next_unused_quad =
8355 triangulation.faces->quads
8356 .template next_free_pair_object<2>(triangulation);
8357 new_quads[2] = next_unused_quad;
8358 AssertIsNotUsed(new_quads[2]);
8359
8360 ++next_unused_quad;
8361 new_quads[3] = next_unused_quad;
8362 AssertIsNotUsed(new_quads[3]);
8363
8364 // note these quads as children to the present one
8365 quad->set_children(0, new_quads[0]->index());
8366 quad->set_children(2, new_quads[2]->index());
8367 quad->set_refinement_case(RefinementCase<2>::cut_xy);
8368
8369 new_quads[0]->set_bounding_object_indices(
8370 {line_indices[0],
8371 line_indices[8],
8372 line_indices[4],
8373 line_indices[10]});
8374 new_quads[1]->set_bounding_object_indices(
8375 {line_indices[8],
8376 line_indices[2],
8377 line_indices[5],
8378 line_indices[11]});
8379 new_quads[2]->set_bounding_object_indices(
8380 {line_indices[1],
8381 line_indices[9],
8382 line_indices[10],
8383 line_indices[6]});
8384 new_quads[3]->set_bounding_object_indices(
8385 {line_indices[9],
8386 line_indices[3],
8387 line_indices[11],
8388 line_indices[7]});
8389 for (const auto &new_quad : new_quads)
8390 {
8391 new_quad->set_used_flag();
8392 new_quad->clear_user_flag();
8393 new_quad->clear_user_data();
8394 new_quad->clear_children();
8395 new_quad->set_boundary_id_internal(quad->boundary_id());
8396 new_quad->set_manifold_id(quad->manifold_id());
8397 // set all line orientations to true, change
8398 // this after the loop, as we have to consider
8399 // different lines for each child
8400 for (unsigned int j = 0;
8401 j < GeometryInfo<dim>::lines_per_face;
8402 ++j)
8403 new_quad->set_line_orientation(j, true);
8404 }
8405 // now set the line orientation of children of
8406 // outer lines correctly, the lines in the
8407 // interior of the refined quad are automatically
8408 // oriented conforming to the standard
8409 new_quads[0]->set_line_orientation(
8410 0, quad->line_orientation(0));
8411 new_quads[0]->set_line_orientation(
8412 2, quad->line_orientation(2));
8413 new_quads[1]->set_line_orientation(
8414 1, quad->line_orientation(1));
8415 new_quads[1]->set_line_orientation(
8416 2, quad->line_orientation(2));
8417 new_quads[2]->set_line_orientation(
8418 0, quad->line_orientation(0));
8419 new_quads[2]->set_line_orientation(
8420 3, quad->line_orientation(3));
8421 new_quads[3]->set_line_orientation(
8422 1, quad->line_orientation(1));
8423 new_quads[3]->set_line_orientation(
8424 3, quad->line_orientation(3));
8425
8426 // finally clear flag indicating the need for
8427 // refinement
8428 quad->clear_user_flag();
8429 } // if (isotropic refinement)
8430 } // for all quads
8431 } // looped two times over all quads, all quads refined now
8432
8433 //---------------------------------
8434 // Now, finally, set up the new
8435 // cells
8436 //---------------------------------
8437
8439 cells_with_distorted_children;
8440
8441 for (unsigned int level = 0; level != triangulation.levels.size() - 1;
8442 ++level)
8443 {
8444 // only active objects can be refined further; remember
8445 // that we won't operate on the finest level, so
8446 // triangulation.begin_*(level+1) is allowed
8451 next_unused_hex = triangulation.begin_raw_hex(level + 1);
8452
8453 for (; hex != endh; ++hex)
8454 if (hex->refine_flag_set())
8455 {
8456 // this hex needs to be refined
8457
8458 // clear flag indicating the need for refinement. do
8459 // it here already, since we can't do it anymore
8460 // once the cell has children
8461 const RefinementCase<dim> ref_case = hex->refine_flag_set();
8462 hex->clear_refine_flag();
8463 hex->set_refinement_case(ref_case);
8464
8465 // depending on the refine case we might have to
8466 // create additional vertices, lines and quads
8467 // interior of the hex before the actual children
8468 // can be set up.
8469
8470 // in a first step: reserve the needed space for
8471 // lines, quads and hexes and initialize them
8472 // correctly
8473
8474 unsigned int n_new_lines = 0;
8475 unsigned int n_new_quads = 0;
8476 unsigned int n_new_hexes = 0;
8477 switch (ref_case)
8478 {
8482 n_new_lines = 0;
8483 n_new_quads = 1;
8484 n_new_hexes = 2;
8485 break;
8489 n_new_lines = 1;
8490 n_new_quads = 4;
8491 n_new_hexes = 4;
8492 break;
8494 n_new_lines = 6;
8495 n_new_quads = 12;
8496 n_new_hexes = 8;
8497 break;
8498 default:
8500 break;
8501 }
8502
8503 // find some space for the newly to be created
8504 // interior lines and initialize them.
8505 std::vector<
8507 new_lines(n_new_lines);
8508 for (unsigned int i = 0; i < n_new_lines; ++i)
8509 {
8510 new_lines[i] =
8511 triangulation.faces->lines
8512 .template next_free_single_object<1>(triangulation);
8513
8514 AssertIsNotUsed(new_lines[i]);
8515 new_lines[i]->set_used_flag();
8516 new_lines[i]->clear_user_flag();
8517 new_lines[i]->clear_user_data();
8518 new_lines[i]->clear_children();
8519 // interior line
8520 new_lines[i]->set_boundary_id_internal(
8522 // they inherit geometry description of the hex they
8523 // belong to
8524 new_lines[i]->set_manifold_id(hex->manifold_id());
8525 }
8526
8527 // find some space for the newly to be created
8528 // interior quads and initialize them.
8529 std::vector<
8531 new_quads(n_new_quads);
8532 for (unsigned int i = 0; i < n_new_quads; ++i)
8533 {
8534 new_quads[i] =
8535 triangulation.faces->quads
8536 .template next_free_single_object<2>(triangulation);
8537
8538 AssertIsNotUsed(new_quads[i]);
8539 new_quads[i]->set_used_flag();
8540 new_quads[i]->clear_user_flag();
8541 new_quads[i]->clear_user_data();
8542 new_quads[i]->clear_children();
8543 // interior quad
8544 new_quads[i]->set_boundary_id_internal(
8546 // they inherit geometry description of the hex they
8547 // belong to
8548 new_quads[i]->set_manifold_id(hex->manifold_id());
8549 // set all line orientation flags to true by
8550 // default, change this afterwards, if necessary
8551 for (unsigned int j = 0;
8552 j < GeometryInfo<dim>::lines_per_face;
8553 ++j)
8554 new_quads[i]->set_line_orientation(j, true);
8555 }
8556
8557 types::subdomain_id subdomainid = hex->subdomain_id();
8558
8559 // find some space for the newly to be created hexes
8560 // and initialize them.
8561 std::vector<
8563 new_hexes(n_new_hexes);
8564 for (unsigned int i = 0; i < n_new_hexes; ++i)
8565 {
8566 if (i % 2 == 0)
8567 next_unused_hex =
8568 triangulation.levels[level + 1]->cells.next_free_hex(
8569 triangulation, level + 1);
8570 else
8571 ++next_unused_hex;
8572
8573 new_hexes[i] = next_unused_hex;
8574
8575 AssertIsNotUsed(new_hexes[i]);
8576 new_hexes[i]->set_used_flag();
8577 new_hexes[i]->clear_user_flag();
8578 new_hexes[i]->clear_user_data();
8579 new_hexes[i]->clear_children();
8580 // inherit material
8581 // properties
8582 new_hexes[i]->set_material_id(hex->material_id());
8583 new_hexes[i]->set_manifold_id(hex->manifold_id());
8584 new_hexes[i]->set_subdomain_id(subdomainid);
8585
8586 if (i % 2)
8587 new_hexes[i]->set_parent(hex->index());
8588 // set the face_orientation flag to true for all
8589 // faces initially, as this is the default value
8590 // which is true for all faces interior to the
8591 // hex. later on go the other way round and
8592 // reset faces that are at the boundary of the
8593 // mother cube
8594 //
8595 // the same is true for the face_flip and
8596 // face_rotation flags. however, the latter two
8597 // are set to false by default as this is the
8598 // standard value
8599 for (const unsigned int f :
8601 new_hexes[i]->set_combined_face_orientation(
8602 f,
8604 }
8605 // note these hexes as children to the present cell
8606 for (unsigned int i = 0; i < n_new_hexes / 2; ++i)
8607 hex->set_children(2 * i, new_hexes[2 * i]->index());
8608
8609 // we have to take into account whether the
8610 // different faces are oriented correctly or in the
8611 // opposite direction, so store that up front
8612
8613 // face_orientation
8614 const bool f_or[6] = {hex->face_orientation(0),
8615 hex->face_orientation(1),
8616 hex->face_orientation(2),
8617 hex->face_orientation(3),
8618 hex->face_orientation(4),
8619 hex->face_orientation(5)};
8620
8621 // face_flip
8622 const bool f_fl[6] = {hex->face_flip(0),
8623 hex->face_flip(1),
8624 hex->face_flip(2),
8625 hex->face_flip(3),
8626 hex->face_flip(4),
8627 hex->face_flip(5)};
8628
8629 // face_rotation
8630 const bool f_ro[6] = {hex->face_rotation(0),
8631 hex->face_rotation(1),
8632 hex->face_rotation(2),
8633 hex->face_rotation(3),
8634 hex->face_rotation(4),
8635 hex->face_rotation(5)};
8636
8637 // combined orientation
8638 const unsigned char f_co[6] = {
8639 hex->combined_face_orientation(0),
8640 hex->combined_face_orientation(1),
8641 hex->combined_face_orientation(2),
8642 hex->combined_face_orientation(3),
8643 hex->combined_face_orientation(4),
8644 hex->combined_face_orientation(5)};
8645
8646 // little helper table, indicating, whether the
8647 // child with index 0 or with index 1 can be found
8648 // at the standard origin of an anisotropically
8649 // refined quads in real orientation index 1:
8650 // (RefineCase - 1) index 2: face_flip
8651
8652 // index 3: face rotation
8653 // note: face orientation has no influence
8654 const unsigned int child_at_origin[2][2][2] = {
8655 {{0, 0}, // RefinementCase<dim>::cut_x, face_flip=false,
8656 // face_rotation=false and true
8657 {1, 1}}, // RefinementCase<dim>::cut_x, face_flip=true,
8658 // face_rotation=false and true
8659 {{0, 1}, // RefinementCase<dim>::cut_y, face_flip=false,
8660 // face_rotation=false and true
8661 {1, 0}}}; // RefinementCase<dim>::cut_y, face_flip=true,
8662 // face_rotation=false and true
8663
8664 //-------------------------------------
8665 //
8666 // in the following we will do the same thing for
8667 // each refinement case: create a new vertex (if
8668 // needed), create new interior lines (if needed),
8669 // create new interior quads and afterwards build
8670 // the children hexes out of these and the existing
8671 // subfaces of the outer quads (which have been
8672 // created above). However, even if the steps are
8673 // quite similar, the actual work strongly depends
8674 // on the actual refinement case. therefore, we use
8675 // separate blocks of code for each of these cases,
8676 // which hopefully increases the readability to some
8677 // extend.
8678
8679 switch (ref_case)
8680 {
8682 {
8683 //----------------------------
8684 //
8685 // RefinementCase<dim>::cut_x
8686 //
8687 // the refined cube will look
8688 // like this:
8689 //
8690 // *----*----*
8691 // / / /|
8692 // / / / |
8693 // / / / |
8694 // *----*----* |
8695 // | | | |
8696 // | | | *
8697 // | | | /
8698 // | | | /
8699 // | | |/
8700 // *----*----*
8701 //
8702 // again, first collect some data about the
8703 // indices of the lines, with the following
8704 // numbering:
8705
8706 // face 2: front plane
8707 // (note: x,y exchanged)
8708 // *---*---*
8709 // | | |
8710 // | 0 |
8711 // | | |
8712 // *---*---*
8713 // m0
8714 // face 3: back plane
8715 // (note: x,y exchanged)
8716 // m1
8717 // *---*---*
8718 // | | |
8719 // | 1 |
8720 // | | |
8721 // *---*---*
8722 // face 4: bottom plane
8723 // *---*---*
8724 // / / /
8725 // / 2 /
8726 // / / /
8727 // *---*---*
8728 // m0
8729 // face 5: top plane
8730 // m1
8731 // *---*---*
8732 // / / /
8733 // / 3 /
8734 // / / /
8735 // *---*---*
8736
8737 // set up a list of line iterators first. from
8738 // this, construct lists of line_indices and
8739 // line orientations later on
8740 const typename Triangulation<dim, spacedim>::
8741 raw_line_iterator lines[4] = {
8742 hex->face(2)->child(0)->line(
8743 (hex->face(2)->refinement_case() ==
8745 1 :
8746 3), // 0
8747 hex->face(3)->child(0)->line(
8748 (hex->face(3)->refinement_case() ==
8750 1 :
8751 3), // 1
8752 hex->face(4)->child(0)->line(
8753 (hex->face(4)->refinement_case() ==
8755 1 :
8756 3), // 2
8757 hex->face(5)->child(0)->line(
8758 (hex->face(5)->refinement_case() ==
8760 1 :
8761 3) // 3
8762 };
8763
8764 unsigned int line_indices[4];
8765 for (unsigned int i = 0; i < 4; ++i)
8766 line_indices[i] = lines[i]->index();
8767
8768 // the orientation of lines for the inner quads
8769 // is quite tricky. as these lines are newly
8770 // created ones and thus have no parents, they
8771 // cannot inherit this property. set up an array
8772 // and fill it with the respective values
8773 bool line_orientation[4];
8774
8775 // the middle vertex marked as m0 above is the
8776 // start vertex for lines 0 and 2 in standard
8777 // orientation, whereas m1 is the end vertex of
8778 // lines 1 and 3 in standard orientation
8779 const unsigned int middle_vertices[2] = {
8780 hex->line(2)->child(0)->vertex_index(1),
8781 hex->line(7)->child(0)->vertex_index(1)};
8782
8783 for (unsigned int i = 0; i < 4; ++i)
8784 if (lines[i]->vertex_index(i % 2) ==
8785 middle_vertices[i % 2])
8786 line_orientation[i] = true;
8787 else
8788 {
8789 // it must be the other
8790 // way round then
8791 Assert(lines[i]->vertex_index((i + 1) % 2) ==
8792 middle_vertices[i % 2],
8794 line_orientation[i] = false;
8795 }
8796
8797 // set up the new quad, line numbering is as
8798 // indicated above
8799 new_quads[0]->set_bounding_object_indices(
8800 {line_indices[0],
8801 line_indices[1],
8802 line_indices[2],
8803 line_indices[3]});
8804
8805 new_quads[0]->set_line_orientation(
8806 0, line_orientation[0]);
8807 new_quads[0]->set_line_orientation(
8808 1, line_orientation[1]);
8809 new_quads[0]->set_line_orientation(
8810 2, line_orientation[2]);
8811 new_quads[0]->set_line_orientation(
8812 3, line_orientation[3]);
8813
8814 // the quads are numbered as follows:
8815 //
8816 // planes in the interior of the old hex:
8817 //
8818 // *
8819 // /|
8820 // / | x
8821 // / | *-------* *---------*
8822 // * | | | / /
8823 // | 0 | | | / /
8824 // | * | | / /
8825 // | / *-------*y *---------*x
8826 // | /
8827 // |/
8828 // *
8829 //
8830 // children of the faces of the old hex
8831 //
8832 // *---*---* *---*---*
8833 // /| | | / / /|
8834 // / | | | / 9 / 10/ |
8835 // / | 5 | 6 | / / / |
8836 // * | | | *---*---* |
8837 // | 1 *---*---* | | | 2 *
8838 // | / / / | | | /
8839 // | / 7 / 8 / | 3 | 4 | /
8840 // |/ / / | | |/
8841 // *---*---* *---*---*
8842 //
8843 // note that we have to take care of the
8844 // orientation of faces.
8845 const int quad_indices[11] = {
8846 new_quads[0]->index(), // 0
8847
8848 hex->face(0)->index(), // 1
8849
8850 hex->face(1)->index(), // 2
8851
8852 hex->face(2)->child_index(
8853 child_at_origin[hex->face(2)->refinement_case() -
8854 1][f_fl[2]][f_ro[2]]), // 3
8855 hex->face(2)->child_index(
8856 1 -
8857 child_at_origin[hex->face(2)->refinement_case() -
8858 1][f_fl[2]][f_ro[2]]),
8859
8860 hex->face(3)->child_index(
8861 child_at_origin[hex->face(3)->refinement_case() -
8862 1][f_fl[3]][f_ro[3]]), // 5
8863 hex->face(3)->child_index(
8864 1 -
8865 child_at_origin[hex->face(3)->refinement_case() -
8866 1][f_fl[3]][f_ro[3]]),
8867
8868 hex->face(4)->child_index(
8869 child_at_origin[hex->face(4)->refinement_case() -
8870 1][f_fl[4]][f_ro[4]]), // 7
8871 hex->face(4)->child_index(
8872 1 -
8873 child_at_origin[hex->face(4)->refinement_case() -
8874 1][f_fl[4]][f_ro[4]]),
8875
8876 hex->face(5)->child_index(
8877 child_at_origin[hex->face(5)->refinement_case() -
8878 1][f_fl[5]][f_ro[5]]), // 9
8879 hex->face(5)->child_index(
8880 1 -
8881 child_at_origin[hex->face(5)->refinement_case() -
8882 1][f_fl[5]][f_ro[5]])
8883
8884 };
8885
8886 new_hexes[0]->set_bounding_object_indices(
8887 {quad_indices[1],
8888 quad_indices[0],
8889 quad_indices[3],
8890 quad_indices[5],
8891 quad_indices[7],
8892 quad_indices[9]});
8893 new_hexes[1]->set_bounding_object_indices(
8894 {quad_indices[0],
8895 quad_indices[2],
8896 quad_indices[4],
8897 quad_indices[6],
8898 quad_indices[8],
8899 quad_indices[10]});
8900 break;
8901 }
8902
8904 {
8905 //----------------------------
8906 //
8907 // RefinementCase<dim>::cut_y
8908 //
8909 // the refined cube will look like this:
8910 //
8911 // *---------*
8912 // / /|
8913 // *---------* |
8914 // / /| |
8915 // *---------* | |
8916 // | | | |
8917 // | | | *
8918 // | | |/
8919 // | | *
8920 // | |/
8921 // *---------*
8922 //
8923 // again, first collect some data about the
8924 // indices of the lines, with the following
8925 // numbering:
8926
8927 // face 0: left plane
8928 // *
8929 // /|
8930 // * |
8931 // /| |
8932 // * | |
8933 // | 0 |
8934 // | | *
8935 // | |/
8936 // | *m0
8937 // |/
8938 // *
8939 // face 1: right plane
8940 // *
8941 // /|
8942 // m1* |
8943 // /| |
8944 // * | |
8945 // | 1 |
8946 // | | *
8947 // | |/
8948 // | *
8949 // |/
8950 // *
8951 // face 4: bottom plane
8952 // *-------*
8953 // / /
8954 // m0*---2---*
8955 // / /
8956 // *-------*
8957 // face 5: top plane
8958 // *-------*
8959 // / /
8960 // *---3---*m1
8961 // / /
8962 // *-------*
8963
8964 // set up a list of line iterators first. from
8965 // this, construct lists of line_indices and
8966 // line orientations later on
8967 const typename Triangulation<dim, spacedim>::
8968 raw_line_iterator lines[4] = {
8969 hex->face(0)->child(0)->line(
8970 (hex->face(0)->refinement_case() ==
8972 1 :
8973 3), // 0
8974 hex->face(1)->child(0)->line(
8975 (hex->face(1)->refinement_case() ==
8977 1 :
8978 3), // 1
8979 hex->face(4)->child(0)->line(
8980 (hex->face(4)->refinement_case() ==
8982 1 :
8983 3), // 2
8984 hex->face(5)->child(0)->line(
8985 (hex->face(5)->refinement_case() ==
8987 1 :
8988 3) // 3
8989 };
8990
8991 unsigned int line_indices[4];
8992 for (unsigned int i = 0; i < 4; ++i)
8993 line_indices[i] = lines[i]->index();
8994
8995 // the orientation of lines for the inner quads
8996 // is quite tricky. as these lines are newly
8997 // created ones and thus have no parents, they
8998 // cannot inherit this property. set up an array
8999 // and fill it with the respective values
9000 bool line_orientation[4];
9001
9002 // the middle vertex marked as m0 above is the
9003 // start vertex for lines 0 and 2 in standard
9004 // orientation, whereas m1 is the end vertex of
9005 // lines 1 and 3 in standard orientation
9006 const unsigned int middle_vertices[2] = {
9007 hex->line(0)->child(0)->vertex_index(1),
9008 hex->line(5)->child(0)->vertex_index(1)};
9009
9010 for (unsigned int i = 0; i < 4; ++i)
9011 if (lines[i]->vertex_index(i % 2) ==
9012 middle_vertices[i % 2])
9013 line_orientation[i] = true;
9014 else
9015 {
9016 // it must be the other way round then
9017 Assert(lines[i]->vertex_index((i + 1) % 2) ==
9018 middle_vertices[i % 2],
9020 line_orientation[i] = false;
9021 }
9022
9023 // set up the new quad, line numbering is as
9024 // indicated above
9025 new_quads[0]->set_bounding_object_indices(
9026 {line_indices[2],
9027 line_indices[3],
9028 line_indices[0],
9029 line_indices[1]});
9030
9031 new_quads[0]->set_line_orientation(
9032 0, line_orientation[2]);
9033 new_quads[0]->set_line_orientation(
9034 1, line_orientation[3]);
9035 new_quads[0]->set_line_orientation(
9036 2, line_orientation[0]);
9037 new_quads[0]->set_line_orientation(
9038 3, line_orientation[1]);
9039
9040 // the quads are numbered as follows:
9041 //
9042 // planes in the interior of the old hex:
9043 //
9044 // *
9045 // /|
9046 // / | x
9047 // / | *-------* *---------*
9048 // * | | | / /
9049 // | | | 0 | / /
9050 // | * | | / /
9051 // | / *-------*y *---------*x
9052 // | /
9053 // |/
9054 // *
9055 //
9056 // children of the faces of the old hex
9057 //
9058 // *-------* *-------*
9059 // /| | / 10 /|
9060 // * | | *-------* |
9061 // /| | 6 | / 9 /| |
9062 // * |2| | *-------* |4|
9063 // | | *-------* | | | *
9064 // |1|/ 8 / | |3|/
9065 // | *-------* | 5 | *
9066 // |/ 7 / | |/
9067 // *-------* *-------*
9068 //
9069 // note that we have to take care of the
9070 // orientation of faces.
9071 const int quad_indices[11] = {
9072 new_quads[0]->index(), // 0
9073
9074 hex->face(0)->child_index(
9075 child_at_origin[hex->face(0)->refinement_case() -
9076 1][f_fl[0]][f_ro[0]]), // 1
9077 hex->face(0)->child_index(
9078 1 -
9079 child_at_origin[hex->face(0)->refinement_case() -
9080 1][f_fl[0]][f_ro[0]]),
9081
9082 hex->face(1)->child_index(
9083 child_at_origin[hex->face(1)->refinement_case() -
9084 1][f_fl[1]][f_ro[1]]), // 3
9085 hex->face(1)->child_index(
9086 1 -
9087 child_at_origin[hex->face(1)->refinement_case() -
9088 1][f_fl[1]][f_ro[1]]),
9089
9090 hex->face(2)->index(), // 5
9091
9092 hex->face(3)->index(), // 6
9093
9094 hex->face(4)->child_index(
9095 child_at_origin[hex->face(4)->refinement_case() -
9096 1][f_fl[4]][f_ro[4]]), // 7
9097 hex->face(4)->child_index(
9098 1 -
9099 child_at_origin[hex->face(4)->refinement_case() -
9100 1][f_fl[4]][f_ro[4]]),
9101
9102 hex->face(5)->child_index(
9103 child_at_origin[hex->face(5)->refinement_case() -
9104 1][f_fl[5]][f_ro[5]]), // 9
9105 hex->face(5)->child_index(
9106 1 -
9107 child_at_origin[hex->face(5)->refinement_case() -
9108 1][f_fl[5]][f_ro[5]])
9109
9110 };
9111
9112 new_hexes[0]->set_bounding_object_indices(
9113 {quad_indices[1],
9114 quad_indices[3],
9115 quad_indices[5],
9116 quad_indices[0],
9117 quad_indices[7],
9118 quad_indices[9]});
9119 new_hexes[1]->set_bounding_object_indices(
9120 {quad_indices[2],
9121 quad_indices[4],
9122 quad_indices[0],
9123 quad_indices[6],
9124 quad_indices[8],
9125 quad_indices[10]});
9126 break;
9127 }
9128
9130 {
9131 //----------------------------
9132 //
9133 // RefinementCase<dim>::cut_z
9134 //
9135 // the refined cube will look like this:
9136 //
9137 // *---------*
9138 // / /|
9139 // / / |
9140 // / / *
9141 // *---------* /|
9142 // | | / |
9143 // | |/ *
9144 // *---------* /
9145 // | | /
9146 // | |/
9147 // *---------*
9148 //
9149 // again, first collect some data about the
9150 // indices of the lines, with the following
9151 // numbering:
9152
9153 // face 0: left plane
9154 // *
9155 // /|
9156 // / |
9157 // / *
9158 // * /|
9159 // | 0 |
9160 // |/ *
9161 // m0* /
9162 // | /
9163 // |/
9164 // *
9165 // face 1: right plane
9166 // *
9167 // /|
9168 // / |
9169 // / *m1
9170 // * /|
9171 // | 1 |
9172 // |/ *
9173 // * /
9174 // | /
9175 // |/
9176 // *
9177 // face 2: front plane
9178 // (note: x,y exchanged)
9179 // *-------*
9180 // | |
9181 // m0*---2---*
9182 // | |
9183 // *-------*
9184 // face 3: back plane
9185 // (note: x,y exchanged)
9186 // *-------*
9187 // | |
9188 // *---3---*m1
9189 // | |
9190 // *-------*
9191
9192 // set up a list of line iterators first. from
9193 // this, construct lists of line_indices and
9194 // line orientations later on
9195 const typename Triangulation<dim, spacedim>::
9196 raw_line_iterator lines[4] = {
9197 hex->face(0)->child(0)->line(
9198 (hex->face(0)->refinement_case() ==
9200 1 :
9201 3), // 0
9202 hex->face(1)->child(0)->line(
9203 (hex->face(1)->refinement_case() ==
9205 1 :
9206 3), // 1
9207 hex->face(2)->child(0)->line(
9208 (hex->face(2)->refinement_case() ==
9210 1 :
9211 3), // 2
9212 hex->face(3)->child(0)->line(
9213 (hex->face(3)->refinement_case() ==
9215 1 :
9216 3) // 3
9217 };
9218
9219 unsigned int line_indices[4];
9220 for (unsigned int i = 0; i < 4; ++i)
9221 line_indices[i] = lines[i]->index();
9222
9223 // the orientation of lines for the inner quads
9224 // is quite tricky. as these lines are newly
9225 // created ones and thus have no parents, they
9226 // cannot inherit this property. set up an array
9227 // and fill it with the respective values
9228 bool line_orientation[4];
9229
9230 // the middle vertex marked as m0 above is the
9231 // start vertex for lines 0 and 2 in standard
9232 // orientation, whereas m1 is the end vertex of
9233 // lines 1 and 3 in standard orientation
9234 const unsigned int middle_vertices[2] = {
9235 middle_vertex_index<dim, spacedim>(hex->line(8)),
9236 middle_vertex_index<dim, spacedim>(hex->line(11))};
9237
9238 for (unsigned int i = 0; i < 4; ++i)
9239 if (lines[i]->vertex_index(i % 2) ==
9240 middle_vertices[i % 2])
9241 line_orientation[i] = true;
9242 else
9243 {
9244 // it must be the other way round then
9245 Assert(lines[i]->vertex_index((i + 1) % 2) ==
9246 middle_vertices[i % 2],
9248 line_orientation[i] = false;
9249 }
9250
9251 // set up the new quad, line numbering is as
9252 // indicated above
9253 new_quads[0]->set_bounding_object_indices(
9254 {line_indices[0],
9255 line_indices[1],
9256 line_indices[2],
9257 line_indices[3]});
9258
9259 new_quads[0]->set_line_orientation(
9260 0, line_orientation[0]);
9261 new_quads[0]->set_line_orientation(
9262 1, line_orientation[1]);
9263 new_quads[0]->set_line_orientation(
9264 2, line_orientation[2]);
9265 new_quads[0]->set_line_orientation(
9266 3, line_orientation[3]);
9267
9268 // the quads are numbered as follows:
9269 //
9270 // planes in the interior of the old hex:
9271 //
9272 // *
9273 // /|
9274 // / | x
9275 // / | *-------* *---------*
9276 // * | | | / /
9277 // | | | | / 0 /
9278 // | * | | / /
9279 // | / *-------*y *---------*x
9280 // | /
9281 // |/
9282 // *
9283 //
9284 // children of the faces of the old hex
9285 //
9286 // *---*---* *-------*
9287 // /| 8 | / /|
9288 // / | | / 10 / |
9289 // / *-------* / / *
9290 // * 2/| | *-------* 4/|
9291 // | / | 7 | | 6 | / |
9292 // |/1 *-------* | |/3 *
9293 // * / / *-------* /
9294 // | / 9 / | | /
9295 // |/ / | 5 |/
9296 // *-------* *---*---*
9297 //
9298 // note that we have to take care of the
9299 // orientation of faces.
9300 const int quad_indices[11] = {
9301 new_quads[0]->index(), // 0
9302
9303 hex->face(0)->child_index(
9304 child_at_origin[hex->face(0)->refinement_case() -
9305 1][f_fl[0]][f_ro[0]]), // 1
9306 hex->face(0)->child_index(
9307 1 -
9308 child_at_origin[hex->face(0)->refinement_case() -
9309 1][f_fl[0]][f_ro[0]]),
9310
9311 hex->face(1)->child_index(
9312 child_at_origin[hex->face(1)->refinement_case() -
9313 1][f_fl[1]][f_ro[1]]), // 3
9314 hex->face(1)->child_index(
9315 1 -
9316 child_at_origin[hex->face(1)->refinement_case() -
9317 1][f_fl[1]][f_ro[1]]),
9318
9319 hex->face(2)->child_index(
9320 child_at_origin[hex->face(2)->refinement_case() -
9321 1][f_fl[2]][f_ro[2]]), // 5
9322 hex->face(2)->child_index(
9323 1 -
9324 child_at_origin[hex->face(2)->refinement_case() -
9325 1][f_fl[2]][f_ro[2]]),
9326
9327 hex->face(3)->child_index(
9328 child_at_origin[hex->face(3)->refinement_case() -
9329 1][f_fl[3]][f_ro[3]]), // 7
9330 hex->face(3)->child_index(
9331 1 -
9332 child_at_origin[hex->face(3)->refinement_case() -
9333 1][f_fl[3]][f_ro[3]]),
9334
9335 hex->face(4)->index(), // 9
9336
9337 hex->face(5)->index() // 10
9338 };
9339
9340 new_hexes[0]->set_bounding_object_indices(
9341 {quad_indices[1],
9342 quad_indices[3],
9343 quad_indices[5],
9344 quad_indices[7],
9345 quad_indices[9],
9346 quad_indices[0]});
9347 new_hexes[1]->set_bounding_object_indices(
9348 {quad_indices[2],
9349 quad_indices[4],
9350 quad_indices[6],
9351 quad_indices[8],
9352 quad_indices[0],
9353 quad_indices[10]});
9354 break;
9355 }
9356
9358 {
9359 //----------------------------
9360 //
9361 // RefinementCase<dim>::cut_xy
9362 //
9363 // the refined cube will look like this:
9364 //
9365 // *----*----*
9366 // / / /|
9367 // *----*----* |
9368 // / / /| |
9369 // *----*----* | |
9370 // | | | | |
9371 // | | | | *
9372 // | | | |/
9373 // | | | *
9374 // | | |/
9375 // *----*----*
9376 //
9377
9378 // first, create the new internal line
9379 new_lines[0]->set_bounding_object_indices(
9380 {middle_vertex_index<dim, spacedim>(hex->face(4)),
9381 middle_vertex_index<dim, spacedim>(hex->face(5))});
9382
9383 // again, first collect some data about the
9384 // indices of the lines, with the following
9385 // numbering:
9386
9387 // face 0: left plane
9388 // *
9389 // /|
9390 // * |
9391 // /| |
9392 // * | |
9393 // | 0 |
9394 // | | *
9395 // | |/
9396 // | *
9397 // |/
9398 // *
9399 // face 1: right plane
9400 // *
9401 // /|
9402 // * |
9403 // /| |
9404 // * | |
9405 // | 1 |
9406 // | | *
9407 // | |/
9408 // | *
9409 // |/
9410 // *
9411 // face 2: front plane
9412 // (note: x,y exchanged)
9413 // *---*---*
9414 // | | |
9415 // | 2 |
9416 // | | |
9417 // *-------*
9418 // face 3: back plane
9419 // (note: x,y exchanged)
9420 // *---*---*
9421 // | | |
9422 // | 3 |
9423 // | | |
9424 // *---*---*
9425 // face 4: bottom plane
9426 // *---*---*
9427 // / 5 /
9428 // *-6-*-7-*
9429 // / 4 /
9430 // *---*---*
9431 // face 5: top plane
9432 // *---*---*
9433 // / 9 /
9434 // *10-*-11*
9435 // / 8 /
9436 // *---*---*
9437 // middle planes
9438 // *-------* *---*---*
9439 // / / | | |
9440 // / / | 12 |
9441 // / / | | |
9442 // *-------* *---*---*
9443
9444 // set up a list of line iterators first. from
9445 // this, construct lists of line_indices and
9446 // line orientations later on
9447 const typename Triangulation<
9448 dim,
9449 spacedim>::raw_line_iterator lines[13] = {
9450 hex->face(0)->child(0)->line(
9451 (hex->face(0)->refinement_case() ==
9453 1 :
9454 3), // 0
9455 hex->face(1)->child(0)->line(
9456 (hex->face(1)->refinement_case() ==
9458 1 :
9459 3), // 1
9460 hex->face(2)->child(0)->line(
9461 (hex->face(2)->refinement_case() ==
9463 1 :
9464 3), // 2
9465 hex->face(3)->child(0)->line(
9466 (hex->face(3)->refinement_case() ==
9468 1 :
9469 3), // 3
9470
9471 hex->face(4)
9472 ->isotropic_child(
9474 0, f_or[4], f_fl[4], f_ro[4]))
9475 ->line(
9477 1, f_or[4], f_fl[4], f_ro[4])), // 4
9478 hex->face(4)
9479 ->isotropic_child(
9481 3, f_or[4], f_fl[4], f_ro[4]))
9482 ->line(
9484 0, f_or[4], f_fl[4], f_ro[4])), // 5
9485 hex->face(4)
9486 ->isotropic_child(
9488 0, f_or[4], f_fl[4], f_ro[4]))
9489 ->line(
9491 3, f_or[4], f_fl[4], f_ro[4])), // 6
9492 hex->face(4)
9493 ->isotropic_child(
9495 3, f_or[4], f_fl[4], f_ro[4]))
9496 ->line(
9498 2, f_or[4], f_fl[4], f_ro[4])), // 7
9499
9500 hex->face(5)
9501 ->isotropic_child(
9503 0, f_or[5], f_fl[5], f_ro[5]))
9504 ->line(
9506 1, f_or[5], f_fl[5], f_ro[5])), // 8
9507 hex->face(5)
9508 ->isotropic_child(
9510 3, f_or[5], f_fl[5], f_ro[5]))
9511 ->line(
9513 0, f_or[5], f_fl[5], f_ro[5])), // 9
9514 hex->face(5)
9515 ->isotropic_child(
9517 0, f_or[5], f_fl[5], f_ro[5]))
9518 ->line(
9520 3, f_or[5], f_fl[5], f_ro[5])), // 10
9521 hex->face(5)
9522 ->isotropic_child(
9524 3, f_or[5], f_fl[5], f_ro[5]))
9525 ->line(
9527 2, f_or[5], f_fl[5], f_ro[5])), // 11
9528
9529 new_lines[0] // 12
9530 };
9531
9532 unsigned int line_indices[13];
9533 for (unsigned int i = 0; i < 13; ++i)
9534 line_indices[i] = lines[i]->index();
9535
9536 // the orientation of lines for the inner quads
9537 // is quite tricky. as these lines are newly
9538 // created ones and thus have no parents, they
9539 // cannot inherit this property. set up an array
9540 // and fill it with the respective values
9541 bool line_orientation[13];
9542
9543 // the middle vertices of the lines of our
9544 // bottom face
9545 const unsigned int middle_vertices[4] = {
9546 hex->line(0)->child(0)->vertex_index(1),
9547 hex->line(1)->child(0)->vertex_index(1),
9548 hex->line(2)->child(0)->vertex_index(1),
9549 hex->line(3)->child(0)->vertex_index(1),
9550 };
9551
9552 // note: for lines 0 to 3 the orientation of the
9553 // line is 'true', if vertex 0 is on the bottom
9554 // face
9555 for (unsigned int i = 0; i < 4; ++i)
9556 if (lines[i]->vertex_index(0) == middle_vertices[i])
9557 line_orientation[i] = true;
9558 else
9559 {
9560 // it must be the other way round then
9561 Assert(lines[i]->vertex_index(1) ==
9562 middle_vertices[i],
9564 line_orientation[i] = false;
9565 }
9566
9567 // note: for lines 4 to 11 (inner lines of the
9568 // outer quads) the following holds: the second
9569 // vertex of the even lines in standard
9570 // orientation is the vertex in the middle of
9571 // the quad, whereas for odd lines the first
9572 // vertex is the same middle vertex.
9573 for (unsigned int i = 4; i < 12; ++i)
9574 if (lines[i]->vertex_index((i + 1) % 2) ==
9575 middle_vertex_index<dim, spacedim>(
9576 hex->face(3 + i / 4)))
9577 line_orientation[i] = true;
9578 else
9579 {
9580 // it must be the other way
9581 // round then
9582 Assert(lines[i]->vertex_index(i % 2) ==
9583 (middle_vertex_index<dim, spacedim>(
9584 hex->face(3 + i / 4))),
9586 line_orientation[i] = false;
9587 }
9588 // for the last line the line orientation is
9589 // always true, since it was just constructed
9590 // that way
9591 line_orientation[12] = true;
9592
9593 // set up the 4 quads, numbered as follows (left
9594 // quad numbering, right line numbering
9595 // extracted from above)
9596 //
9597 // * *
9598 // /| 9|
9599 // * | * |
9600 // y/| | 8| 3
9601 // * |1| * | |
9602 // | | |x | 12|
9603 // |0| * | | *
9604 // | |/ 2 |5
9605 // | * | *
9606 // |/ |4
9607 // * *
9608 //
9609 // x
9610 // *---*---* *10-*-11*
9611 // | | | | | |
9612 // | 2 | 3 | 0 12 1
9613 // | | | | | |
9614 // *---*---*y *-6-*-7-*
9615
9616 new_quads[0]->set_bounding_object_indices(
9617 {line_indices[2],
9618 line_indices[12],
9619 line_indices[4],
9620 line_indices[8]});
9621 new_quads[1]->set_bounding_object_indices(
9622 {line_indices[12],
9623 line_indices[3],
9624 line_indices[5],
9625 line_indices[9]});
9626 new_quads[2]->set_bounding_object_indices(
9627 {line_indices[6],
9628 line_indices[10],
9629 line_indices[0],
9630 line_indices[12]});
9631 new_quads[3]->set_bounding_object_indices(
9632 {line_indices[7],
9633 line_indices[11],
9634 line_indices[12],
9635 line_indices[1]});
9636
9637 new_quads[0]->set_line_orientation(
9638 0, line_orientation[2]);
9639 new_quads[0]->set_line_orientation(
9640 2, line_orientation[4]);
9641 new_quads[0]->set_line_orientation(
9642 3, line_orientation[8]);
9643
9644 new_quads[1]->set_line_orientation(
9645 1, line_orientation[3]);
9646 new_quads[1]->set_line_orientation(
9647 2, line_orientation[5]);
9648 new_quads[1]->set_line_orientation(
9649 3, line_orientation[9]);
9650
9651 new_quads[2]->set_line_orientation(
9652 0, line_orientation[6]);
9653 new_quads[2]->set_line_orientation(
9654 1, line_orientation[10]);
9655 new_quads[2]->set_line_orientation(
9656 2, line_orientation[0]);
9657
9658 new_quads[3]->set_line_orientation(
9659 0, line_orientation[7]);
9660 new_quads[3]->set_line_orientation(
9661 1, line_orientation[11]);
9662 new_quads[3]->set_line_orientation(
9663 3, line_orientation[1]);
9664
9665 // the quads are numbered as follows:
9666 //
9667 // planes in the interior of the old hex:
9668 //
9669 // *
9670 // /|
9671 // * | x
9672 // /| | *---*---* *---------*
9673 // * |1| | | | / /
9674 // | | | | 2 | 3 | / /
9675 // |0| * | | | / /
9676 // | |/ *---*---*y *---------*x
9677 // | *
9678 // |/
9679 // *
9680 //
9681 // children of the faces of the old hex
9682 //
9683 // *---*---* *---*---*
9684 // /| | | /18 / 19/|
9685 // * |10 | 11| /---/---* |
9686 // /| | | | /16 / 17/| |
9687 // * |5| | | *---*---* |7|
9688 // | | *---*---* | | | | *
9689 // |4|/14 / 15/ | | |6|/
9690 // | *---/---/ | 8 | 9 | *
9691 // |/12 / 13/ | | |/
9692 // *---*---* *---*---*
9693 //
9694 // note that we have to take care of the
9695 // orientation of faces.
9696 const int quad_indices[20] = {
9697 new_quads[0]->index(), // 0
9698 new_quads[1]->index(),
9699 new_quads[2]->index(),
9700 new_quads[3]->index(),
9701
9702 hex->face(0)->child_index(
9703 child_at_origin[hex->face(0)->refinement_case() -
9704 1][f_fl[0]][f_ro[0]]), // 4
9705 hex->face(0)->child_index(
9706 1 -
9707 child_at_origin[hex->face(0)->refinement_case() -
9708 1][f_fl[0]][f_ro[0]]),
9709
9710 hex->face(1)->child_index(
9711 child_at_origin[hex->face(1)->refinement_case() -
9712 1][f_fl[1]][f_ro[1]]), // 6
9713 hex->face(1)->child_index(
9714 1 -
9715 child_at_origin[hex->face(1)->refinement_case() -
9716 1][f_fl[1]][f_ro[1]]),
9717
9718 hex->face(2)->child_index(
9719 child_at_origin[hex->face(2)->refinement_case() -
9720 1][f_fl[2]][f_ro[2]]), // 8
9721 hex->face(2)->child_index(
9722 1 -
9723 child_at_origin[hex->face(2)->refinement_case() -
9724 1][f_fl[2]][f_ro[2]]),
9725
9726 hex->face(3)->child_index(
9727 child_at_origin[hex->face(3)->refinement_case() -
9728 1][f_fl[3]][f_ro[3]]), // 10
9729 hex->face(3)->child_index(
9730 1 -
9731 child_at_origin[hex->face(3)->refinement_case() -
9732 1][f_fl[3]][f_ro[3]]),
9733
9734 hex->face(4)->isotropic_child_index(
9736 0, f_or[4], f_fl[4], f_ro[4])), // 12
9737 hex->face(4)->isotropic_child_index(
9739 1, f_or[4], f_fl[4], f_ro[4])),
9740 hex->face(4)->isotropic_child_index(
9742 2, f_or[4], f_fl[4], f_ro[4])),
9743 hex->face(4)->isotropic_child_index(
9745 3, f_or[4], f_fl[4], f_ro[4])),
9746
9747 hex->face(5)->isotropic_child_index(
9749 0, f_or[5], f_fl[5], f_ro[5])), // 16
9750 hex->face(5)->isotropic_child_index(
9752 1, f_or[5], f_fl[5], f_ro[5])),
9753 hex->face(5)->isotropic_child_index(
9755 2, f_or[5], f_fl[5], f_ro[5])),
9756 hex->face(5)->isotropic_child_index(
9758 3, f_or[5], f_fl[5], f_ro[5]))};
9759
9760 new_hexes[0]->set_bounding_object_indices(
9761 {quad_indices[4],
9762 quad_indices[0],
9763 quad_indices[8],
9764 quad_indices[2],
9765 quad_indices[12],
9766 quad_indices[16]});
9767 new_hexes[1]->set_bounding_object_indices(
9768 {quad_indices[0],
9769 quad_indices[6],
9770 quad_indices[9],
9771 quad_indices[3],
9772 quad_indices[13],
9773 quad_indices[17]});
9774 new_hexes[2]->set_bounding_object_indices(
9775 {quad_indices[5],
9776 quad_indices[1],
9777 quad_indices[2],
9778 quad_indices[10],
9779 quad_indices[14],
9780 quad_indices[18]});
9781 new_hexes[3]->set_bounding_object_indices(
9782 {quad_indices[1],
9783 quad_indices[7],
9784 quad_indices[3],
9785 quad_indices[11],
9786 quad_indices[15],
9787 quad_indices[19]});
9788 break;
9789 }
9790
9792 {
9793 //----------------------------
9794 //
9795 // RefinementCase<dim>::cut_xz
9796 //
9797 // the refined cube will look like this:
9798 //
9799 // *----*----*
9800 // / / /|
9801 // / / / |
9802 // / / / *
9803 // *----*----* /|
9804 // | | | / |
9805 // | | |/ *
9806 // *----*----* /
9807 // | | | /
9808 // | | |/
9809 // *----*----*
9810 //
9811
9812 // first, create the new internal line
9813 new_lines[0]->set_bounding_object_indices(
9814 {middle_vertex_index<dim, spacedim>(hex->face(2)),
9815 middle_vertex_index<dim, spacedim>(hex->face(3))});
9816
9817 // again, first collect some data about the
9818 // indices of the lines, with the following
9819 // numbering:
9820
9821 // face 0: left plane
9822 // *
9823 // /|
9824 // / |
9825 // / *
9826 // * /|
9827 // | 0 |
9828 // |/ *
9829 // * /
9830 // | /
9831 // |/
9832 // *
9833 // face 1: right plane
9834 // *
9835 // /|
9836 // / |
9837 // / *
9838 // * /|
9839 // | 1 |
9840 // |/ *
9841 // * /
9842 // | /
9843 // |/
9844 // *
9845 // face 2: front plane
9846 // (note: x,y exchanged)
9847 // *---*---*
9848 // | 5 |
9849 // *-6-*-7-*
9850 // | 4 |
9851 // *---*---*
9852 // face 3: back plane
9853 // (note: x,y exchanged)
9854 // *---*---*
9855 // | 9 |
9856 // *10-*-11*
9857 // | 8 |
9858 // *---*---*
9859 // face 4: bottom plane
9860 // *---*---*
9861 // / / /
9862 // / 2 /
9863 // / / /
9864 // *---*---*
9865 // face 5: top plane
9866 // *---*---*
9867 // / / /
9868 // / 3 /
9869 // / / /
9870 // *---*---*
9871 // middle planes
9872 // *---*---* *-------*
9873 // / / / | |
9874 // / 12 / | |
9875 // / / / | |
9876 // *---*---* *-------*
9877
9878 // set up a list of line iterators first. from
9879 // this, construct lists of line_indices and
9880 // line orientations later on
9881 const typename Triangulation<
9882 dim,
9883 spacedim>::raw_line_iterator lines[13] = {
9884 hex->face(0)->child(0)->line(
9885 (hex->face(0)->refinement_case() ==
9887 1 :
9888 3), // 0
9889 hex->face(1)->child(0)->line(
9890 (hex->face(1)->refinement_case() ==
9892 1 :
9893 3), // 1
9894 hex->face(4)->child(0)->line(
9895 (hex->face(4)->refinement_case() ==
9897 1 :
9898 3), // 2
9899 hex->face(5)->child(0)->line(
9900 (hex->face(5)->refinement_case() ==
9902 1 :
9903 3), // 3
9904
9905 hex->face(2)
9906 ->isotropic_child(
9908 0, f_or[2], f_fl[2], f_ro[2]))
9909 ->line(
9911 3, f_or[2], f_fl[2], f_ro[2])), // 4
9912 hex->face(2)
9913 ->isotropic_child(
9915 3, f_or[2], f_fl[2], f_ro[2]))
9916 ->line(
9918 2, f_or[2], f_fl[2], f_ro[2])), // 5
9919 hex->face(2)
9920 ->isotropic_child(
9922 0, f_or[2], f_fl[2], f_ro[2]))
9923 ->line(
9925 1, f_or[2], f_fl[2], f_ro[2])), // 6
9926 hex->face(2)
9927 ->isotropic_child(
9929 3, f_or[2], f_fl[2], f_ro[2]))
9930 ->line(
9932 0, f_or[2], f_fl[2], f_ro[2])), // 7
9933
9934 hex->face(3)
9935 ->isotropic_child(
9937 0, f_or[3], f_fl[3], f_ro[3]))
9938 ->line(
9940 3, f_or[3], f_fl[3], f_ro[3])), // 8
9941 hex->face(3)
9942 ->isotropic_child(
9944 3, f_or[3], f_fl[3], f_ro[3]))
9945 ->line(
9947 2, f_or[3], f_fl[3], f_ro[3])), // 9
9948 hex->face(3)
9949 ->isotropic_child(
9951 0, f_or[3], f_fl[3], f_ro[3]))
9952 ->line(
9954 1, f_or[3], f_fl[3], f_ro[3])), // 10
9955 hex->face(3)
9956 ->isotropic_child(
9958 3, f_or[3], f_fl[3], f_ro[3]))
9959 ->line(
9961 0, f_or[3], f_fl[3], f_ro[3])), // 11
9962
9963 new_lines[0] // 12
9964 };
9965
9966 unsigned int line_indices[13];
9967 for (unsigned int i = 0; i < 13; ++i)
9968 line_indices[i] = lines[i]->index();
9969
9970 // the orientation of lines for the inner quads
9971 // is quite tricky. as these lines are newly
9972 // created ones and thus have no parents, they
9973 // cannot inherit this property. set up an array
9974 // and fill it with the respective values
9975 bool line_orientation[13];
9976
9977 // the middle vertices of the
9978 // lines of our front face
9979 const unsigned int middle_vertices[4] = {
9980 hex->line(8)->child(0)->vertex_index(1),
9981 hex->line(9)->child(0)->vertex_index(1),
9982 hex->line(2)->child(0)->vertex_index(1),
9983 hex->line(6)->child(0)->vertex_index(1),
9984 };
9985
9986 // note: for lines 0 to 3 the orientation of the
9987 // line is 'true', if vertex 0 is on the front
9988 for (unsigned int i = 0; i < 4; ++i)
9989 if (lines[i]->vertex_index(0) == middle_vertices[i])
9990 line_orientation[i] = true;
9991 else
9992 {
9993 // it must be the other way round then
9994 Assert(lines[i]->vertex_index(1) ==
9995 middle_vertices[i],
9997 line_orientation[i] = false;
9998 }
9999
10000 // note: for lines 4 to 11 (inner lines of the
10001 // outer quads) the following holds: the second
10002 // vertex of the even lines in standard
10003 // orientation is the vertex in the middle of
10004 // the quad, whereas for odd lines the first
10005 // vertex is the same middle vertex.
10006 for (unsigned int i = 4; i < 12; ++i)
10007 if (lines[i]->vertex_index((i + 1) % 2) ==
10008 middle_vertex_index<dim, spacedim>(
10009 hex->face(1 + i / 4)))
10010 line_orientation[i] = true;
10011 else
10012 {
10013 // it must be the other way
10014 // round then
10015 Assert(lines[i]->vertex_index(i % 2) ==
10016 (middle_vertex_index<dim, spacedim>(
10017 hex->face(1 + i / 4))),
10019 line_orientation[i] = false;
10020 }
10021 // for the last line the line orientation is
10022 // always true, since it was just constructed
10023 // that way
10024 line_orientation[12] = true;
10025
10026 // set up the 4 quads, numbered as follows (left
10027 // quad numbering, right line numbering
10028 // extracted from above), the drawings denote
10029 // middle planes
10030 //
10031 // * *
10032 // /| /|
10033 // / | 3 9
10034 // y/ * / *
10035 // * 3/| * /|
10036 // | / |x 5 12|8
10037 // |/ * |/ *
10038 // * 2/ * /
10039 // | / 4 2
10040 // |/ |/
10041 // * *
10042 //
10043 // y
10044 // *----*----* *-10-*-11-*
10045 // / / / / / /
10046 // / 0 / 1 / 0 12 1
10047 // / / / / / /
10048 // *----*----*x *--6-*--7-*
10049
10050 new_quads[0]->set_bounding_object_indices(
10051 {line_indices[0],
10052 line_indices[12],
10053 line_indices[6],
10054 line_indices[10]});
10055 new_quads[1]->set_bounding_object_indices(
10056 {line_indices[12],
10057 line_indices[1],
10058 line_indices[7],
10059 line_indices[11]});
10060 new_quads[2]->set_bounding_object_indices(
10061 {line_indices[4],
10062 line_indices[8],
10063 line_indices[2],
10064 line_indices[12]});
10065 new_quads[3]->set_bounding_object_indices(
10066 {line_indices[5],
10067 line_indices[9],
10068 line_indices[12],
10069 line_indices[3]});
10070
10071 new_quads[0]->set_line_orientation(
10072 0, line_orientation[0]);
10073 new_quads[0]->set_line_orientation(
10074 2, line_orientation[6]);
10075 new_quads[0]->set_line_orientation(
10076 3, line_orientation[10]);
10077
10078 new_quads[1]->set_line_orientation(
10079 1, line_orientation[1]);
10080 new_quads[1]->set_line_orientation(
10081 2, line_orientation[7]);
10082 new_quads[1]->set_line_orientation(
10083 3, line_orientation[11]);
10084
10085 new_quads[2]->set_line_orientation(
10086 0, line_orientation[4]);
10087 new_quads[2]->set_line_orientation(
10088 1, line_orientation[8]);
10089 new_quads[2]->set_line_orientation(
10090 2, line_orientation[2]);
10091
10092 new_quads[3]->set_line_orientation(
10093 0, line_orientation[5]);
10094 new_quads[3]->set_line_orientation(
10095 1, line_orientation[9]);
10096 new_quads[3]->set_line_orientation(
10097 3, line_orientation[3]);
10098
10099 // the quads are numbered as follows:
10100 //
10101 // planes in the interior of the old hex:
10102 //
10103 // *
10104 // /|
10105 // / | x
10106 // /3 * *-------* *----*----*
10107 // * /| | | / / /
10108 // | / | | | / 0 / 1 /
10109 // |/ * | | / / /
10110 // * 2/ *-------*y *----*----*x
10111 // | /
10112 // |/
10113 // *
10114 //
10115 // children of the faces
10116 // of the old hex
10117 // *---*---* *---*---*
10118 // /|13 | 15| / / /|
10119 // / | | | /18 / 19/ |
10120 // / *---*---* / / / *
10121 // * 5/| | | *---*---* 7/|
10122 // | / |12 | 14| | 9 | 11| / |
10123 // |/4 *---*---* | | |/6 *
10124 // * / / / *---*---* /
10125 // | /16 / 17/ | | | /
10126 // |/ / / | 8 | 10|/
10127 // *---*---* *---*---*
10128 //
10129 // note that we have to take care of the
10130 // orientation of faces.
10131 const int quad_indices[20] = {
10132 new_quads[0]->index(), // 0
10133 new_quads[1]->index(),
10134 new_quads[2]->index(),
10135 new_quads[3]->index(),
10136
10137 hex->face(0)->child_index(
10138 child_at_origin[hex->face(0)->refinement_case() -
10139 1][f_fl[0]][f_ro[0]]), // 4
10140 hex->face(0)->child_index(
10141 1 -
10142 child_at_origin[hex->face(0)->refinement_case() -
10143 1][f_fl[0]][f_ro[0]]),
10144
10145 hex->face(1)->child_index(
10146 child_at_origin[hex->face(1)->refinement_case() -
10147 1][f_fl[1]][f_ro[1]]), // 6
10148 hex->face(1)->child_index(
10149 1 -
10150 child_at_origin[hex->face(1)->refinement_case() -
10151 1][f_fl[1]][f_ro[1]]),
10152
10153 hex->face(2)->isotropic_child_index(
10155 0, f_or[2], f_fl[2], f_ro[2])), // 8
10156 hex->face(2)->isotropic_child_index(
10158 1, f_or[2], f_fl[2], f_ro[2])),
10159 hex->face(2)->isotropic_child_index(
10161 2, f_or[2], f_fl[2], f_ro[2])),
10162 hex->face(2)->isotropic_child_index(
10164 3, f_or[2], f_fl[2], f_ro[2])),
10165
10166 hex->face(3)->isotropic_child_index(
10168 0, f_or[3], f_fl[3], f_ro[3])), // 12
10169 hex->face(3)->isotropic_child_index(
10171 1, f_or[3], f_fl[3], f_ro[3])),
10172 hex->face(3)->isotropic_child_index(
10174 2, f_or[3], f_fl[3], f_ro[3])),
10175 hex->face(3)->isotropic_child_index(
10177 3, f_or[3], f_fl[3], f_ro[3])),
10178
10179 hex->face(4)->child_index(
10180 child_at_origin[hex->face(4)->refinement_case() -
10181 1][f_fl[4]][f_ro[4]]), // 16
10182 hex->face(4)->child_index(
10183 1 -
10184 child_at_origin[hex->face(4)->refinement_case() -
10185 1][f_fl[4]][f_ro[4]]),
10186
10187 hex->face(5)->child_index(
10188 child_at_origin[hex->face(5)->refinement_case() -
10189 1][f_fl[5]][f_ro[5]]), // 18
10190 hex->face(5)->child_index(
10191 1 -
10192 child_at_origin[hex->face(5)->refinement_case() -
10193 1][f_fl[5]][f_ro[5]])};
10194
10195 // due to the exchange of x and y for the front
10196 // and back face, we order the children
10197 // according to
10198 //
10199 // *---*---*
10200 // | 1 | 3 |
10201 // *---*---*
10202 // | 0 | 2 |
10203 // *---*---*
10204 new_hexes[0]->set_bounding_object_indices(
10205 {quad_indices[4],
10206 quad_indices[2],
10207 quad_indices[8],
10208 quad_indices[12],
10209 quad_indices[16],
10210 quad_indices[0]});
10211 new_hexes[1]->set_bounding_object_indices(
10212 {quad_indices[5],
10213 quad_indices[3],
10214 quad_indices[9],
10215 quad_indices[13],
10216 quad_indices[0],
10217 quad_indices[18]});
10218 new_hexes[2]->set_bounding_object_indices(
10219 {quad_indices[2],
10220 quad_indices[6],
10221 quad_indices[10],
10222 quad_indices[14],
10223 quad_indices[17],
10224 quad_indices[1]});
10225 new_hexes[3]->set_bounding_object_indices(
10226 {quad_indices[3],
10227 quad_indices[7],
10228 quad_indices[11],
10229 quad_indices[15],
10230 quad_indices[1],
10231 quad_indices[19]});
10232 break;
10233 }
10234
10236 {
10237 //----------------------------
10238 //
10239 // RefinementCase<dim>::cut_yz
10240 //
10241 // the refined cube will look like this:
10242 //
10243 // *---------*
10244 // / /|
10245 // *---------* |
10246 // / /| |
10247 // *---------* |/|
10248 // | | * |
10249 // | |/| *
10250 // *---------* |/
10251 // | | *
10252 // | |/
10253 // *---------*
10254 //
10255
10256 // first, create the new
10257 // internal line
10258 new_lines[0]->set_bounding_object_indices(
10259
10260 {middle_vertex_index<dim, spacedim>(hex->face(0)),
10261 middle_vertex_index<dim, spacedim>(hex->face(1))});
10262
10263 // again, first collect some data about the
10264 // indices of the lines, with the following
10265 // numbering: (note that face 0 and 1 each are
10266 // shown twice for better readability)
10267
10268 // face 0: left plane
10269 // * *
10270 // /| /|
10271 // * | * |
10272 // /| * /| *
10273 // * 5/| * |7|
10274 // | * | | * |
10275 // |/| * |6| *
10276 // * 4/ * |/
10277 // | * | *
10278 // |/ |/
10279 // * *
10280 // face 1: right plane
10281 // * *
10282 // /| /|
10283 // * | * |
10284 // /| * /| *
10285 // * 9/| * |11
10286 // | * | | * |
10287 // |/| * |10 *
10288 // * 8/ * |/
10289 // | * | *
10290 // |/ |/
10291 // * *
10292 // face 2: front plane
10293 // (note: x,y exchanged)
10294 // *-------*
10295 // | |
10296 // *---0---*
10297 // | |
10298 // *-------*
10299 // face 3: back plane
10300 // (note: x,y exchanged)
10301 // *-------*
10302 // | |
10303 // *---1---*
10304 // | |
10305 // *-------*
10306 // face 4: bottom plane
10307 // *-------*
10308 // / /
10309 // *---2---*
10310 // / /
10311 // *-------*
10312 // face 5: top plane
10313 // *-------*
10314 // / /
10315 // *---3---*
10316 // / /
10317 // *-------*
10318 // middle planes
10319 // *-------* *-------*
10320 // / / | |
10321 // *---12--* | |
10322 // / / | |
10323 // *-------* *-------*
10324
10325 // set up a list of line iterators first. from
10326 // this, construct lists of line_indices and
10327 // line orientations later on
10328 const typename Triangulation<
10329 dim,
10330 spacedim>::raw_line_iterator lines[13] = {
10331 hex->face(2)->child(0)->line(
10332 (hex->face(2)->refinement_case() ==
10334 1 :
10335 3), // 0
10336 hex->face(3)->child(0)->line(
10337 (hex->face(3)->refinement_case() ==
10339 1 :
10340 3), // 1
10341 hex->face(4)->child(0)->line(
10342 (hex->face(4)->refinement_case() ==
10344 1 :
10345 3), // 2
10346 hex->face(5)->child(0)->line(
10347 (hex->face(5)->refinement_case() ==
10349 1 :
10350 3), // 3
10351
10352 hex->face(0)
10353 ->isotropic_child(
10355 0, f_or[0], f_fl[0], f_ro[0]))
10356 ->line(
10358 1, f_or[0], f_fl[0], f_ro[0])), // 4
10359 hex->face(0)
10360 ->isotropic_child(
10362 3, f_or[0], f_fl[0], f_ro[0]))
10363 ->line(
10365 0, f_or[0], f_fl[0], f_ro[0])), // 5
10366 hex->face(0)
10367 ->isotropic_child(
10369 0, f_or[0], f_fl[0], f_ro[0]))
10370 ->line(
10372 3, f_or[0], f_fl[0], f_ro[0])), // 6
10373 hex->face(0)
10374 ->isotropic_child(
10376 3, f_or[0], f_fl[0], f_ro[0]))
10377 ->line(
10379 2, f_or[0], f_fl[0], f_ro[0])), // 7
10380
10381 hex->face(1)
10382 ->isotropic_child(
10384 0, f_or[1], f_fl[1], f_ro[1]))
10385 ->line(
10387 1, f_or[1], f_fl[1], f_ro[1])), // 8
10388 hex->face(1)
10389 ->isotropic_child(
10391 3, f_or[1], f_fl[1], f_ro[1]))
10392 ->line(
10394 0, f_or[1], f_fl[1], f_ro[1])), // 9
10395 hex->face(1)
10396 ->isotropic_child(
10398 0, f_or[1], f_fl[1], f_ro[1]))
10399 ->line(
10401 3, f_or[1], f_fl[1], f_ro[1])), // 10
10402 hex->face(1)
10403 ->isotropic_child(
10405 3, f_or[1], f_fl[1], f_ro[1]))
10406 ->line(
10408 2, f_or[1], f_fl[1], f_ro[1])), // 11
10409
10410 new_lines[0] // 12
10411 };
10412
10413 unsigned int line_indices[13];
10414
10415 for (unsigned int i = 0; i < 13; ++i)
10416 line_indices[i] = lines[i]->index();
10417
10418 // the orientation of lines for the inner quads
10419 // is quite tricky. as these lines are newly
10420 // created ones and thus have no parents, they
10421 // cannot inherit this property. set up an array
10422 // and fill it with the respective values
10423 bool line_orientation[13];
10424
10425 // the middle vertices of the lines of our front
10426 // face
10427 const unsigned int middle_vertices[4] = {
10428 hex->line(8)->child(0)->vertex_index(1),
10429 hex->line(10)->child(0)->vertex_index(1),
10430 hex->line(0)->child(0)->vertex_index(1),
10431 hex->line(4)->child(0)->vertex_index(1),
10432 };
10433
10434 // note: for lines 0 to 3 the orientation of the
10435 // line is 'true', if vertex 0 is on the front
10436 for (unsigned int i = 0; i < 4; ++i)
10437 if (lines[i]->vertex_index(0) == middle_vertices[i])
10438 line_orientation[i] = true;
10439 else
10440 {
10441 // it must be the other way round then
10442 Assert(lines[i]->vertex_index(1) ==
10443 middle_vertices[i],
10445 line_orientation[i] = false;
10446 }
10447
10448 // note: for lines 4 to 11 (inner lines of the
10449 // outer quads) the following holds: the second
10450 // vertex of the even lines in standard
10451 // orientation is the vertex in the middle of
10452 // the quad, whereas for odd lines the first
10453 // vertex is the same middle vertex.
10454 for (unsigned int i = 4; i < 12; ++i)
10455 if (lines[i]->vertex_index((i + 1) % 2) ==
10456 middle_vertex_index<dim, spacedim>(
10457 hex->face(i / 4 - 1)))
10458 line_orientation[i] = true;
10459 else
10460 {
10461 // it must be the other way
10462 // round then
10463 Assert(lines[i]->vertex_index(i % 2) ==
10464 (middle_vertex_index<dim, spacedim>(
10465 hex->face(i / 4 - 1))),
10467 line_orientation[i] = false;
10468 }
10469 // for the last line the line orientation is
10470 // always true, since it was just constructed
10471 // that way
10472 line_orientation[12] = true;
10473
10474 // set up the 4 quads, numbered as follows (left
10475 // quad numbering, right line numbering
10476 // extracted from above)
10477 //
10478 // x
10479 // *-------* *---3---*
10480 // | 3 | 5 9
10481 // *-------* *---12--*
10482 // | 2 | 4 8
10483 // *-------*y *---2---*
10484 //
10485 // y
10486 // *---------* *----1----*
10487 // / 1 / 7 11
10488 // *---------* *----12---*
10489 // / 0 / 6 10
10490 // *---------*x *----0----*
10491
10492 new_quads[0]->set_bounding_object_indices(
10493 {line_indices[6],
10494 line_indices[10],
10495 line_indices[0],
10496 line_indices[12]});
10497 new_quads[1]->set_bounding_object_indices(
10498 {line_indices[7],
10499 line_indices[11],
10500 line_indices[12],
10501 line_indices[1]});
10502 new_quads[2]->set_bounding_object_indices(
10503 {line_indices[2],
10504 line_indices[12],
10505 line_indices[4],
10506 line_indices[8]});
10507 new_quads[3]->set_bounding_object_indices(
10508 {line_indices[12],
10509 line_indices[3],
10510 line_indices[5],
10511 line_indices[9]});
10512
10513 new_quads[0]->set_line_orientation(
10514 0, line_orientation[6]);
10515 new_quads[0]->set_line_orientation(
10516 1, line_orientation[10]);
10517 new_quads[0]->set_line_orientation(
10518 2, line_orientation[0]);
10519
10520 new_quads[1]->set_line_orientation(
10521 0, line_orientation[7]);
10522 new_quads[1]->set_line_orientation(
10523 1, line_orientation[11]);
10524 new_quads[1]->set_line_orientation(
10525 3, line_orientation[1]);
10526
10527 new_quads[2]->set_line_orientation(
10528 0, line_orientation[2]);
10529 new_quads[2]->set_line_orientation(
10530 2, line_orientation[4]);
10531 new_quads[2]->set_line_orientation(
10532 3, line_orientation[8]);
10533
10534 new_quads[3]->set_line_orientation(
10535 1, line_orientation[3]);
10536 new_quads[3]->set_line_orientation(
10537 2, line_orientation[5]);
10538 new_quads[3]->set_line_orientation(
10539 3, line_orientation[9]);
10540
10541 // the quads are numbered as follows:
10542 //
10543 // planes in the interior of the old hex:
10544 //
10545 // *
10546 // /|
10547 // / | x
10548 // / | *-------* *---------*
10549 // * | | 3 | / 1 /
10550 // | | *-------* *---------*
10551 // | * | 2 | / 0 /
10552 // | / *-------*y *---------*x
10553 // | /
10554 // |/
10555 // *
10556 //
10557 // children of the faces
10558 // of the old hex
10559 // *-------* *-------*
10560 // /| | / 19 /|
10561 // * | 15 | *-------* |
10562 // /|7*-------* / 18 /|11
10563 // * |/| | *-------* |/|
10564 // |6* | 14 | | 10* |
10565 // |/|5*-------* | 13 |/|9*
10566 // * |/ 17 / *-------* |/
10567 // |4*-------* | |8*
10568 // |/ 16 / | 12 |/
10569 // *-------* *-------*
10570 //
10571 // note that we have to take care of the
10572 // orientation of faces.
10573 const int quad_indices[20] = {
10574 new_quads[0]->index(), // 0
10575 new_quads[1]->index(),
10576 new_quads[2]->index(),
10577 new_quads[3]->index(),
10578
10579 hex->face(0)->isotropic_child_index(
10581 0, f_or[0], f_fl[0], f_ro[0])), // 4
10582 hex->face(0)->isotropic_child_index(
10584 1, f_or[0], f_fl[0], f_ro[0])),
10585 hex->face(0)->isotropic_child_index(
10587 2, f_or[0], f_fl[0], f_ro[0])),
10588 hex->face(0)->isotropic_child_index(
10590 3, f_or[0], f_fl[0], f_ro[0])),
10591
10592 hex->face(1)->isotropic_child_index(
10594 0, f_or[1], f_fl[1], f_ro[1])), // 8
10595 hex->face(1)->isotropic_child_index(
10597 1, f_or[1], f_fl[1], f_ro[1])),
10598 hex->face(1)->isotropic_child_index(
10600 2, f_or[1], f_fl[1], f_ro[1])),
10601 hex->face(1)->isotropic_child_index(
10603 3, f_or[1], f_fl[1], f_ro[1])),
10604
10605 hex->face(2)->child_index(
10606 child_at_origin[hex->face(2)->refinement_case() -
10607 1][f_fl[2]][f_ro[2]]), // 12
10608 hex->face(2)->child_index(
10609 1 -
10610 child_at_origin[hex->face(2)->refinement_case() -
10611 1][f_fl[2]][f_ro[2]]),
10612
10613 hex->face(3)->child_index(
10614 child_at_origin[hex->face(3)->refinement_case() -
10615 1][f_fl[3]][f_ro[3]]), // 14
10616 hex->face(3)->child_index(
10617 1 -
10618 child_at_origin[hex->face(3)->refinement_case() -
10619 1][f_fl[3]][f_ro[3]]),
10620
10621 hex->face(4)->child_index(
10622 child_at_origin[hex->face(4)->refinement_case() -
10623 1][f_fl[4]][f_ro[4]]), // 16
10624 hex->face(4)->child_index(
10625 1 -
10626 child_at_origin[hex->face(4)->refinement_case() -
10627 1][f_fl[4]][f_ro[4]]),
10628
10629 hex->face(5)->child_index(
10630 child_at_origin[hex->face(5)->refinement_case() -
10631 1][f_fl[5]][f_ro[5]]), // 18
10632 hex->face(5)->child_index(
10633 1 -
10634 child_at_origin[hex->face(5)->refinement_case() -
10635 1][f_fl[5]][f_ro[5]])};
10636
10637 new_hexes[0]->set_bounding_object_indices(
10638 {quad_indices[4],
10639 quad_indices[8],
10640 quad_indices[12],
10641 quad_indices[2],
10642 quad_indices[16],
10643 quad_indices[0]});
10644 new_hexes[1]->set_bounding_object_indices(
10645 {quad_indices[5],
10646 quad_indices[9],
10647 quad_indices[2],
10648 quad_indices[14],
10649 quad_indices[17],
10650 quad_indices[1]});
10651 new_hexes[2]->set_bounding_object_indices(
10652 {quad_indices[6],
10653 quad_indices[10],
10654 quad_indices[13],
10655 quad_indices[3],
10656 quad_indices[0],
10657 quad_indices[18]});
10658 new_hexes[3]->set_bounding_object_indices(
10659 {quad_indices[7],
10660 quad_indices[11],
10661 quad_indices[3],
10662 quad_indices[15],
10663 quad_indices[1],
10664 quad_indices[19]});
10665 break;
10666 }
10667
10669 {
10670 //----------------------------
10671 //
10672 // RefinementCase<dim>::cut_xyz
10673 // isotropic refinement
10674 //
10675 // the refined cube will look
10676 // like this:
10677 //
10678 // *----*----*
10679 // / / /|
10680 // *----*----* |
10681 // / / /| *
10682 // *----*----* |/|
10683 // | | | * |
10684 // | | |/| *
10685 // *----*----* |/
10686 // | | | *
10687 // | | |/
10688 // *----*----*
10689 //
10690
10691 // find the next unused vertex and set it
10692 // appropriately
10693 while (
10694 triangulation.vertices_used[next_unused_vertex] ==
10695 true)
10696 ++next_unused_vertex;
10697 Assert(
10698 next_unused_vertex < triangulation.vertices.size(),
10699 ExcMessage(
10700 "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."));
10701 triangulation.vertices_used[next_unused_vertex] =
10702 true;
10703
10704 // the new vertex is definitely in the interior,
10705 // so we need not worry about the
10706 // boundary. However we need to worry about
10707 // Manifolds. Let the cell compute its own
10708 // center, by querying the underlying manifold
10709 // object.
10710 triangulation.vertices[next_unused_vertex] =
10711 hex->center(true, true);
10712
10713 // set the data of the six lines. first collect
10714 // the indices of the seven vertices (consider
10715 // the two planes to be crossed to form the
10716 // planes cutting the hex in two vertically and
10717 // horizontally)
10718 //
10719 // *--3--* *--5--*
10720 // / / / | | |
10721 // 0--6--1 0--6--1
10722 // / / / | | |
10723 // *--2--* *--4--*
10724 // the lines are numbered
10725 // as follows:
10726 // *--*--* *--*--*
10727 // / 1 / | 5 |
10728 // *2-*-3* *2-*-3*
10729 // / 0 / | 4 |
10730 // *--*--* *--*--*
10731 //
10732 const unsigned int vertex_indices[7] = {
10733 middle_vertex_index<dim, spacedim>(hex->face(0)),
10734 middle_vertex_index<dim, spacedim>(hex->face(1)),
10735 middle_vertex_index<dim, spacedim>(hex->face(2)),
10736 middle_vertex_index<dim, spacedim>(hex->face(3)),
10737 middle_vertex_index<dim, spacedim>(hex->face(4)),
10738 middle_vertex_index<dim, spacedim>(hex->face(5)),
10739 next_unused_vertex};
10740
10741 new_lines[0]->set_bounding_object_indices(
10743 new_lines[1]->set_bounding_object_indices(
10745 new_lines[2]->set_bounding_object_indices(
10747 new_lines[3]->set_bounding_object_indices(
10749 new_lines[4]->set_bounding_object_indices(
10751 new_lines[5]->set_bounding_object_indices(
10753
10754 // again, first collect some data about the
10755 // indices of the lines, with the following
10756 // numbering: (note that face 0 and 1 each are
10757 // shown twice for better readability)
10758
10759 // face 0: left plane
10760 // * *
10761 // /| /|
10762 // * | * |
10763 // /| * /| *
10764 // * 1/| * |3|
10765 // | * | | * |
10766 // |/| * |2| *
10767 // * 0/ * |/
10768 // | * | *
10769 // |/ |/
10770 // * *
10771 // face 1: right plane
10772 // * *
10773 // /| /|
10774 // * | * |
10775 // /| * /| *
10776 // * 5/| * |7|
10777 // | * | | * |
10778 // |/| * |6| *
10779 // * 4/ * |/
10780 // | * | *
10781 // |/ |/
10782 // * *
10783 // face 2: front plane
10784 // (note: x,y exchanged)
10785 // *---*---*
10786 // | 11 |
10787 // *-8-*-9-*
10788 // | 10 |
10789 // *---*---*
10790 // face 3: back plane
10791 // (note: x,y exchanged)
10792 // *---*---*
10793 // | 15 |
10794 // *12-*-13*
10795 // | 14 |
10796 // *---*---*
10797 // face 4: bottom plane
10798 // *---*---*
10799 // / 17 /
10800 // *18-*-19*
10801 // / 16 /
10802 // *---*---*
10803 // face 5: top plane
10804 // *---*---*
10805 // / 21 /
10806 // *22-*-23*
10807 // / 20 /
10808 // *---*---*
10809 // middle planes
10810 // *---*---* *---*---*
10811 // / 25 / | 29 |
10812 // *26-*-27* *26-*-27*
10813 // / 24 / | 28 |
10814 // *---*---* *---*---*
10815
10816 // set up a list of line iterators first. from
10817 // this, construct lists of line_indices and
10818 // line orientations later on
10819 const typename Triangulation<
10820 dim,
10821 spacedim>::raw_line_iterator lines[30] = {
10822 hex->face(0)
10823 ->isotropic_child(
10825 0, f_or[0], f_fl[0], f_ro[0]))
10826 ->line(
10828 1, f_or[0], f_fl[0], f_ro[0])), // 0
10829 hex->face(0)
10830 ->isotropic_child(
10832 3, f_or[0], f_fl[0], f_ro[0]))
10833 ->line(
10835 0, f_or[0], f_fl[0], f_ro[0])), // 1
10836 hex->face(0)
10837 ->isotropic_child(
10839 0, f_or[0], f_fl[0], f_ro[0]))
10840 ->line(
10842 3, f_or[0], f_fl[0], f_ro[0])), // 2
10843 hex->face(0)
10844 ->isotropic_child(
10846 3, f_or[0], f_fl[0], f_ro[0]))
10847 ->line(
10849 2, f_or[0], f_fl[0], f_ro[0])), // 3
10850
10851 hex->face(1)
10852 ->isotropic_child(
10854 0, f_or[1], f_fl[1], f_ro[1]))
10855 ->line(
10857 1, f_or[1], f_fl[1], f_ro[1])), // 4
10858 hex->face(1)
10859 ->isotropic_child(
10861 3, f_or[1], f_fl[1], f_ro[1]))
10862 ->line(
10864 0, f_or[1], f_fl[1], f_ro[1])), // 5
10865 hex->face(1)
10866 ->isotropic_child(
10868 0, f_or[1], f_fl[1], f_ro[1]))
10869 ->line(
10871 3, f_or[1], f_fl[1], f_ro[1])), // 6
10872 hex->face(1)
10873 ->isotropic_child(
10875 3, f_or[1], f_fl[1], f_ro[1]))
10876 ->line(
10878 2, f_or[1], f_fl[1], f_ro[1])), // 7
10879
10880 hex->face(2)
10881 ->isotropic_child(
10883 0, f_or[2], f_fl[2], f_ro[2]))
10884 ->line(
10886 1, f_or[2], f_fl[2], f_ro[2])), // 8
10887 hex->face(2)
10888 ->isotropic_child(
10890 3, f_or[2], f_fl[2], f_ro[2]))
10891 ->line(
10893 0, f_or[2], f_fl[2], f_ro[2])), // 9
10894 hex->face(2)
10895 ->isotropic_child(
10897 0, f_or[2], f_fl[2], f_ro[2]))
10898 ->line(
10900 3, f_or[2], f_fl[2], f_ro[2])), // 10
10901 hex->face(2)
10902 ->isotropic_child(
10904 3, f_or[2], f_fl[2], f_ro[2]))
10905 ->line(
10907 2, f_or[2], f_fl[2], f_ro[2])), // 11
10908
10909 hex->face(3)
10910 ->isotropic_child(
10912 0, f_or[3], f_fl[3], f_ro[3]))
10913 ->line(
10915 1, f_or[3], f_fl[3], f_ro[3])), // 12
10916 hex->face(3)
10917 ->isotropic_child(
10919 3, f_or[3], f_fl[3], f_ro[3]))
10920 ->line(
10922 0, f_or[3], f_fl[3], f_ro[3])), // 13
10923 hex->face(3)
10924 ->isotropic_child(
10926 0, f_or[3], f_fl[3], f_ro[3]))
10927 ->line(
10929 3, f_or[3], f_fl[3], f_ro[3])), // 14
10930 hex->face(3)
10931 ->isotropic_child(
10933 3, f_or[3], f_fl[3], f_ro[3]))
10934 ->line(
10936 2, f_or[3], f_fl[3], f_ro[3])), // 15
10937
10938 hex->face(4)
10939 ->isotropic_child(
10941 0, f_or[4], f_fl[4], f_ro[4]))
10942 ->line(
10944 1, f_or[4], f_fl[4], f_ro[4])), // 16
10945 hex->face(4)
10946 ->isotropic_child(
10948 3, f_or[4], f_fl[4], f_ro[4]))
10949 ->line(
10951 0, f_or[4], f_fl[4], f_ro[4])), // 17
10952 hex->face(4)
10953 ->isotropic_child(
10955 0, f_or[4], f_fl[4], f_ro[4]))
10956 ->line(
10958 3, f_or[4], f_fl[4], f_ro[4])), // 18
10959 hex->face(4)
10960 ->isotropic_child(
10962 3, f_or[4], f_fl[4], f_ro[4]))
10963 ->line(
10965 2, f_or[4], f_fl[4], f_ro[4])), // 19
10966
10967 hex->face(5)
10968 ->isotropic_child(
10970 0, f_or[5], f_fl[5], f_ro[5]))
10971 ->line(
10973 1, f_or[5], f_fl[5], f_ro[5])), // 20
10974 hex->face(5)
10975 ->isotropic_child(
10977 3, f_or[5], f_fl[5], f_ro[5]))
10978 ->line(
10980 0, f_or[5], f_fl[5], f_ro[5])), // 21
10981 hex->face(5)
10982 ->isotropic_child(
10984 0, f_or[5], f_fl[5], f_ro[5]))
10985 ->line(
10987 3, f_or[5], f_fl[5], f_ro[5])), // 22
10988 hex->face(5)
10989 ->isotropic_child(
10991 3, f_or[5], f_fl[5], f_ro[5]))
10992 ->line(
10994 2, f_or[5], f_fl[5], f_ro[5])), // 23
10995
10996 new_lines[0], // 24
10997 new_lines[1], // 25
10998 new_lines[2], // 26
10999 new_lines[3], // 27
11000 new_lines[4], // 28
11001 new_lines[5] // 29
11002 };
11003
11004 unsigned int line_indices[30];
11005 for (unsigned int i = 0; i < 30; ++i)
11006 line_indices[i] = lines[i]->index();
11007
11008 // the orientation of lines for the inner quads
11009 // is quite tricky. as these lines are newly
11010 // created ones and thus have no parents, they
11011 // cannot inherit this property. set up an array
11012 // and fill it with the respective values
11013 bool line_orientation[30];
11014
11015 // note: for the first 24 lines (inner lines of
11016 // the outer quads) the following holds: the
11017 // second vertex of the even lines in standard
11018 // orientation is the vertex in the middle of
11019 // the quad, whereas for odd lines the first
11020 // vertex is the same middle vertex.
11021 for (unsigned int i = 0; i < 24; ++i)
11022 if (lines[i]->vertex_index((i + 1) % 2) ==
11023 vertex_indices[i / 4])
11024 line_orientation[i] = true;
11025 else
11026 {
11027 // it must be the other way
11028 // round then
11029 Assert(lines[i]->vertex_index(i % 2) ==
11030 vertex_indices[i / 4],
11032 line_orientation[i] = false;
11033 }
11034 // for the last 6 lines the line orientation is
11035 // always true, since they were just constructed
11036 // that way
11037 for (unsigned int i = 24; i < 30; ++i)
11038 line_orientation[i] = true;
11039
11040 // set up the 12 quads, numbered as follows
11041 // (left quad numbering, right line numbering
11042 // extracted from above)
11043 //
11044 // * *
11045 // /| 21|
11046 // * | * 15
11047 // y/|3* 20| *
11048 // * |/| * |/|
11049 // |2* |x 11 * 14
11050 // |/|1* |/| *
11051 // * |/ * |17
11052 // |0* 10 *
11053 // |/ |16
11054 // * *
11055 //
11056 // x
11057 // *---*---* *22-*-23*
11058 // | 5 | 7 | 1 29 5
11059 // *---*---* *26-*-27*
11060 // | 4 | 6 | 0 28 4
11061 // *---*---*y *18-*-19*
11062 //
11063 // y
11064 // *----*----* *-12-*-13-*
11065 // / 10 / 11 / 3 25 7
11066 // *----*----* *-26-*-27-*
11067 // / 8 / 9 / 2 24 6
11068 // *----*----*x *--8-*--9-*
11069
11070 new_quads[0]->set_bounding_object_indices(
11071 {line_indices[10],
11072 line_indices[28],
11073 line_indices[16],
11074 line_indices[24]});
11075 new_quads[1]->set_bounding_object_indices(
11076 {line_indices[28],
11077 line_indices[14],
11078 line_indices[17],
11079 line_indices[25]});
11080 new_quads[2]->set_bounding_object_indices(
11081 {line_indices[11],
11082 line_indices[29],
11083 line_indices[24],
11084 line_indices[20]});
11085 new_quads[3]->set_bounding_object_indices(
11086 {line_indices[29],
11087 line_indices[15],
11088 line_indices[25],
11089 line_indices[21]});
11090 new_quads[4]->set_bounding_object_indices(
11091 {line_indices[18],
11092 line_indices[26],
11093 line_indices[0],
11094 line_indices[28]});
11095 new_quads[5]->set_bounding_object_indices(
11096 {line_indices[26],
11097 line_indices[22],
11098 line_indices[1],
11099 line_indices[29]});
11100 new_quads[6]->set_bounding_object_indices(
11101 {line_indices[19],
11102 line_indices[27],
11103 line_indices[28],
11104 line_indices[4]});
11105 new_quads[7]->set_bounding_object_indices(
11106 {line_indices[27],
11107 line_indices[23],
11108 line_indices[29],
11109 line_indices[5]});
11110 new_quads[8]->set_bounding_object_indices(
11111 {line_indices[2],
11112 line_indices[24],
11113 line_indices[8],
11114 line_indices[26]});
11115 new_quads[9]->set_bounding_object_indices(
11116 {line_indices[24],
11117 line_indices[6],
11118 line_indices[9],
11119 line_indices[27]});
11120 new_quads[10]->set_bounding_object_indices(
11121 {line_indices[3],
11122 line_indices[25],
11123 line_indices[26],
11124 line_indices[12]});
11125 new_quads[11]->set_bounding_object_indices(
11126 {line_indices[25],
11127 line_indices[7],
11128 line_indices[27],
11129 line_indices[13]});
11130
11131 // now reset the line_orientation flags of outer
11132 // lines as they cannot be set in a loop (at
11133 // least not easily)
11134 new_quads[0]->set_line_orientation(
11135 0, line_orientation[10]);
11136 new_quads[0]->set_line_orientation(
11137 2, line_orientation[16]);
11138
11139 new_quads[1]->set_line_orientation(
11140 1, line_orientation[14]);
11141 new_quads[1]->set_line_orientation(
11142 2, line_orientation[17]);
11143
11144 new_quads[2]->set_line_orientation(
11145 0, line_orientation[11]);
11146 new_quads[2]->set_line_orientation(
11147 3, line_orientation[20]);
11148
11149 new_quads[3]->set_line_orientation(
11150 1, line_orientation[15]);
11151 new_quads[3]->set_line_orientation(
11152 3, line_orientation[21]);
11153
11154 new_quads[4]->set_line_orientation(
11155 0, line_orientation[18]);
11156 new_quads[4]->set_line_orientation(
11157 2, line_orientation[0]);
11158
11159 new_quads[5]->set_line_orientation(
11160 1, line_orientation[22]);
11161 new_quads[5]->set_line_orientation(
11162 2, line_orientation[1]);
11163
11164 new_quads[6]->set_line_orientation(
11165 0, line_orientation[19]);
11166 new_quads[6]->set_line_orientation(
11167 3, line_orientation[4]);
11168
11169 new_quads[7]->set_line_orientation(
11170 1, line_orientation[23]);
11171 new_quads[7]->set_line_orientation(
11172 3, line_orientation[5]);
11173
11174 new_quads[8]->set_line_orientation(
11175 0, line_orientation[2]);
11176 new_quads[8]->set_line_orientation(
11177 2, line_orientation[8]);
11178
11179 new_quads[9]->set_line_orientation(
11180 1, line_orientation[6]);
11181 new_quads[9]->set_line_orientation(
11182 2, line_orientation[9]);
11183
11184 new_quads[10]->set_line_orientation(
11185 0, line_orientation[3]);
11186 new_quads[10]->set_line_orientation(
11187 3, line_orientation[12]);
11188
11189 new_quads[11]->set_line_orientation(
11190 1, line_orientation[7]);
11191 new_quads[11]->set_line_orientation(
11192 3, line_orientation[13]);
11193
11194 //-------------------------------
11195 // create the eight new hexes
11196 //
11197 // again first collect some data. here, we need
11198 // the indices of a whole lotta quads.
11199
11200 // the quads are numbered as follows:
11201 //
11202 // planes in the interior of the old hex:
11203 //
11204 // *
11205 // /|
11206 // * |
11207 // /|3* *---*---* *----*----*
11208 // * |/| | 5 | 7 | / 10 / 11 /
11209 // |2* | *---*---* *----*----*
11210 // |/|1* | 4 | 6 | / 8 / 9 /
11211 // * |/ *---*---*y *----*----*x
11212 // |0*
11213 // |/
11214 // *
11215 //
11216 // children of the faces
11217 // of the old hex
11218 // *-------* *-------*
11219 // /|25 27| /34 35/|
11220 // 15| | / /19
11221 // / | | /32 33/ |
11222 // * |24 26| *-------*18 |
11223 // 1413*-------* |21 23| 17*
11224 // | /30 31/ | | /
11225 // 12/ / | |16
11226 // |/28 29/ |20 22|/
11227 // *-------* *-------*
11228 //
11229 // note that we have to
11230 // take care of the
11231 // orientation of
11232 // faces.
11233 const int quad_indices[36] = {
11234 new_quads[0]->index(), // 0
11235 new_quads[1]->index(),
11236 new_quads[2]->index(),
11237 new_quads[3]->index(),
11238 new_quads[4]->index(),
11239 new_quads[5]->index(),
11240 new_quads[6]->index(),
11241 new_quads[7]->index(),
11242 new_quads[8]->index(),
11243 new_quads[9]->index(),
11244 new_quads[10]->index(),
11245 new_quads[11]->index(), // 11
11246
11247 hex->face(0)->isotropic_child_index(
11249 0, f_or[0], f_fl[0], f_ro[0])), // 12
11250 hex->face(0)->isotropic_child_index(
11252 1, f_or[0], f_fl[0], f_ro[0])),
11253 hex->face(0)->isotropic_child_index(
11255 2, f_or[0], f_fl[0], f_ro[0])),
11256 hex->face(0)->isotropic_child_index(
11258 3, f_or[0], f_fl[0], f_ro[0])),
11259
11260 hex->face(1)->isotropic_child_index(
11262 0, f_or[1], f_fl[1], f_ro[1])), // 16
11263 hex->face(1)->isotropic_child_index(
11265 1, f_or[1], f_fl[1], f_ro[1])),
11266 hex->face(1)->isotropic_child_index(
11268 2, f_or[1], f_fl[1], f_ro[1])),
11269 hex->face(1)->isotropic_child_index(
11271 3, f_or[1], f_fl[1], f_ro[1])),
11272
11273 hex->face(2)->isotropic_child_index(
11275 0, f_or[2], f_fl[2], f_ro[2])), // 20
11276 hex->face(2)->isotropic_child_index(
11278 1, f_or[2], f_fl[2], f_ro[2])),
11279 hex->face(2)->isotropic_child_index(
11281 2, f_or[2], f_fl[2], f_ro[2])),
11282 hex->face(2)->isotropic_child_index(
11284 3, f_or[2], f_fl[2], f_ro[2])),
11285
11286 hex->face(3)->isotropic_child_index(
11288 0, f_or[3], f_fl[3], f_ro[3])), // 24
11289 hex->face(3)->isotropic_child_index(
11291 1, f_or[3], f_fl[3], f_ro[3])),
11292 hex->face(3)->isotropic_child_index(
11294 2, f_or[3], f_fl[3], f_ro[3])),
11295 hex->face(3)->isotropic_child_index(
11297 3, f_or[3], f_fl[3], f_ro[3])),
11298
11299 hex->face(4)->isotropic_child_index(
11301 0, f_or[4], f_fl[4], f_ro[4])), // 28
11302 hex->face(4)->isotropic_child_index(
11304 1, f_or[4], f_fl[4], f_ro[4])),
11305 hex->face(4)->isotropic_child_index(
11307 2, f_or[4], f_fl[4], f_ro[4])),
11308 hex->face(4)->isotropic_child_index(
11310 3, f_or[4], f_fl[4], f_ro[4])),
11311
11312 hex->face(5)->isotropic_child_index(
11314 0, f_or[5], f_fl[5], f_ro[5])), // 32
11315 hex->face(5)->isotropic_child_index(
11317 1, f_or[5], f_fl[5], f_ro[5])),
11318 hex->face(5)->isotropic_child_index(
11320 2, f_or[5], f_fl[5], f_ro[5])),
11321 hex->face(5)->isotropic_child_index(
11323 3, f_or[5], f_fl[5], f_ro[5]))};
11324
11325 // bottom children
11326 new_hexes[0]->set_bounding_object_indices(
11327 {quad_indices[12],
11328 quad_indices[0],
11329 quad_indices[20],
11330 quad_indices[4],
11331 quad_indices[28],
11332 quad_indices[8]});
11333 new_hexes[1]->set_bounding_object_indices(
11334 {quad_indices[0],
11335 quad_indices[16],
11336 quad_indices[22],
11337 quad_indices[6],
11338 quad_indices[29],
11339 quad_indices[9]});
11340 new_hexes[2]->set_bounding_object_indices(
11341 {quad_indices[13],
11342 quad_indices[1],
11343 quad_indices[4],
11344 quad_indices[24],
11345 quad_indices[30],
11346 quad_indices[10]});
11347 new_hexes[3]->set_bounding_object_indices(
11348 {quad_indices[1],
11349 quad_indices[17],
11350 quad_indices[6],
11351 quad_indices[26],
11352 quad_indices[31],
11353 quad_indices[11]});
11354
11355 // top children
11356 new_hexes[4]->set_bounding_object_indices(
11357 {quad_indices[14],
11358 quad_indices[2],
11359 quad_indices[21],
11360 quad_indices[5],
11361 quad_indices[8],
11362 quad_indices[32]});
11363 new_hexes[5]->set_bounding_object_indices(
11364 {quad_indices[2],
11365 quad_indices[18],
11366 quad_indices[23],
11367 quad_indices[7],
11368 quad_indices[9],
11369 quad_indices[33]});
11370 new_hexes[6]->set_bounding_object_indices(
11371 {quad_indices[15],
11372 quad_indices[3],
11373 quad_indices[5],
11374 quad_indices[25],
11375 quad_indices[10],
11376 quad_indices[34]});
11377 new_hexes[7]->set_bounding_object_indices(
11378 {quad_indices[3],
11379 quad_indices[19],
11380 quad_indices[7],
11381 quad_indices[27],
11382 quad_indices[11],
11383 quad_indices[35]});
11384 break;
11385 }
11386 default:
11387 // all refinement cases have been treated, there
11388 // only remains
11389 // RefinementCase<dim>::no_refinement as
11390 // untreated enumeration value. However, in that
11391 // case we should have aborted much
11392 // earlier. thus we should never get here
11394 break;
11395 } // switch (ref_case)
11396
11397 // and set face orientation flags. note that new
11398 // faces in the interior of the mother cell always
11399 // have a correctly oriented face, but the ones on
11400 // the outer faces will inherit this flag
11401 //
11402 // the flag have been set to true for all faces
11403 // initially, now go the other way round and reset
11404 // faces that are at the boundary of the mother cube
11405 //
11406 // the same is true for the face_flip and
11407 // face_rotation flags. however, the latter two are
11408 // set to false by default as this is the standard
11409 // value
11410
11411 // loop over all faces and all (relevant) subfaces
11412 // of that in order to set the correct values for
11413 // face_orientation, face_flip and face_rotation,
11414 // which are inherited from the corresponding face
11415 // of the mother cube
11416 for (const unsigned int f : GeometryInfo<dim>::face_indices())
11417 for (unsigned int s = 0;
11420 ref_case, f)),
11421 1U);
11422 ++s)
11423 {
11424 const unsigned int current_child =
11426 ref_case,
11427 f,
11428 s,
11429 f_or[f],
11430 f_fl[f],
11431 f_ro[f],
11433 ref_case, f, f_or[f], f_fl[f], f_ro[f]));
11434 new_hexes[current_child]->set_combined_face_orientation(
11435 f, f_co[f]);
11436 }
11437
11438 // now see if we have created cells that are
11439 // distorted and if so add them to our list
11440 if (check_for_distorted_cells &&
11441 has_distorted_children<dim, spacedim>(hex))
11442 cells_with_distorted_children.distorted_cells.push_back(
11443 hex);
11444
11445 // note that the refinement flag was already cleared
11446 // at the beginning of this loop
11447
11448 // inform all listeners that cell refinement is done
11449 triangulation.signals.post_refinement_on_cell(hex);
11450 }
11451 }
11452
11453 // clear user data on quads. we used some of this data to
11454 // indicate anisotropic refinemnt cases on faces. all data
11455 // should be cleared by now, but the information whether we
11456 // used indices or pointers is still present. reset it now to
11457 // enable the user to use whichever they like later on.
11458 triangulation.faces->quads.clear_user_data();
11459
11460 // return the list with distorted children
11461 return cells_with_distorted_children;
11462 }
11463
11464
11477 template <int spacedim>
11478 static void
11481
11482
11483
11484 template <int dim, int spacedim>
11485 static void
11488 {
11489 // If the codimension is one, we cannot perform this check
11490 // yet.
11491 if (spacedim > dim)
11492 return;
11493
11494 for (const auto &cell : triangulation.cell_iterators())
11495 if (cell->at_boundary() && cell->refine_flag_set() &&
11496 cell->refine_flag_set() !=
11498 {
11499 // The cell is at the boundary and it is flagged for
11500 // anisotropic refinement. Therefore, we have a closer
11501 // look
11502 const RefinementCase<dim> ref_case = cell->refine_flag_set();
11503 for (const unsigned int face_no :
11505 if (cell->face(face_no)->at_boundary())
11506 {
11507 // this is the critical face at the boundary.
11509 face_no) !=
11511 {
11512 // up to now, we do not want to refine this
11513 // cell along the face under consideration
11514 // here.
11515 const typename Triangulation<dim,
11516 spacedim>::face_iterator
11517 face = cell->face(face_no);
11518 // the new point on the boundary would be this
11519 // one.
11520 const Point<spacedim> new_bound = face->center(true);
11521 // to check it, transform to the unit cell
11522 // with a linear mapping
11523 const Point<dim> new_unit =
11524 cell->reference_cell()
11525 .template get_default_linear_mapping<dim,
11526 spacedim>()
11527 .transform_real_to_unit_cell(cell, new_bound);
11528
11529 // Now, we have to calculate the distance from
11530 // the face in the unit cell.
11531
11532 // take the correct coordinate direction (0
11533 // for faces 0 and 1, 1 for faces 2 and 3, 2
11534 // for faces 4 and 5) and subtract the correct
11535 // boundary value of the face (0 for faces 0,
11536 // 2, and 4; 1 for faces 1, 3 and 5)
11537 const double dist =
11538 std::fabs(new_unit[face_no / 2] - face_no % 2);
11539
11540 // compare this with the empirical value
11541 // allowed. if it is too big, flag the face
11542 // for isotropic refinement
11543 const double allowed = 0.25;
11544
11545 if (dist > allowed)
11546 cell->flag_for_face_refinement(face_no);
11547 } // if flagged for anistropic refinement
11548 } // if (cell->face(face)->at_boundary())
11549 } // for all cells
11550 }
11551
11552
11565 template <int dim, int spacedim>
11566 static void
11568 {
11569 Assert(dim < 3,
11570 ExcMessage("Wrong function called -- there should "
11571 "be a specialization."));
11572 }
11573
11574
11575 template <int spacedim>
11576 static void
11579 {
11580 const unsigned int dim = 3;
11581 using raw_line_iterator =
11583
11584 // variable to store whether the mesh was changed in the
11585 // present loop and in the whole process
11586 bool mesh_changed = false;
11587
11588 do
11589 {
11590 mesh_changed = false;
11591
11592 // for this following, we need to know which cells are
11593 // going to be coarsened, if we had to make a
11594 // decision. the following function sets these flags:
11596
11597 // first clear flags on lines, since we need them to determine
11598 // which lines will be refined
11600
11601 // flag those lines that are refined and will not be
11602 // coarsened and those that will be refined
11603 for (const auto &cell : triangulation.cell_iterators())
11604 if (cell->refine_flag_set())
11605 {
11606 const std::array<unsigned int, 12> line_indices =
11607 TriaAccessorImplementation::Implementation::
11608 get_line_indices_of_cell(*cell);
11609 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11611 cell->refine_flag_set(), l) ==
11613 {
11614 raw_line_iterator line(&triangulation,
11615 0,
11616 line_indices[l]);
11617 // flag a line, that will be refined
11618 line->set_user_flag();
11619 }
11620 }
11621 else if (cell->has_children() &&
11622 !cell->child(0)->coarsen_flag_set())
11623 {
11624 const std::array<unsigned int, 12> line_indices =
11625 TriaAccessorImplementation::Implementation::
11626 get_line_indices_of_cell(*cell);
11627 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11629 cell->refinement_case(), l) ==
11631 {
11632 raw_line_iterator line(&triangulation,
11633 0,
11634 line_indices[l]);
11635 // flag a line, that is refined and will stay so
11636 line->set_user_flag();
11637 }
11638 }
11639 else if (cell->has_children() &&
11640 cell->child(0)->coarsen_flag_set())
11641 cell->set_user_flag();
11642
11643
11644 // now check whether there are cells with lines that are
11645 // more than once refined or that will be more than once
11646 // refined. The first thing should never be the case, in
11647 // the second case we flag the cell for refinement
11649 cell = triangulation.last_active();
11650 cell != triangulation.end();
11651 --cell)
11652 {
11653 const std::array<unsigned int, 12> line_indices =
11654 TriaAccessorImplementation::Implementation::
11655 get_line_indices_of_cell(*cell);
11656 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11657 {
11658 raw_line_iterator line(&triangulation, 0, line_indices[l]);
11659 if (line->has_children())
11660 {
11661 // if this line is refined, its children should
11662 // not have further children
11663 //
11664 // however, if any of the children is flagged
11665 // for further refinement, we need to refine
11666 // this cell also (at least, if the cell is not
11667 // already flagged)
11668 bool offending_line_found = false;
11669
11670 for (unsigned int c = 0; c < 2; ++c)
11671 {
11672 Assert(line->child(c)->has_children() == false,
11674
11675 if (line->child(c)->user_flag_set() &&
11677 cell->refine_flag_set(), l) ==
11679 {
11680 // tag this cell for refinement
11681 cell->clear_coarsen_flag();
11682 // if anisotropic coarsening is allowed:
11683 // extend the refine_flag in the needed
11684 // direction, else set refine_flag
11685 // (isotropic)
11688 allow_anisotropic_smoothing)
11689 cell->flag_for_line_refinement(l);
11690 else
11691 cell->set_refine_flag();
11692
11693 for (unsigned int k = 0; k < cell->n_lines();
11694 ++k)
11696 cell->refine_flag_set(), l) ==
11698 // flag a line, that will be refined
11699 raw_line_iterator(&triangulation,
11700 0,
11701 line_indices[k])
11702 ->set_user_flag();
11703
11704 // note that we have changed the grid
11705 offending_line_found = true;
11706
11707 // it may save us several loop
11708 // iterations if we flag all lines of
11709 // this cell now (and not at the outset
11710 // of the next iteration) for refinement
11711 for (unsigned int k = 0; k < cell->n_lines();
11712 ++k)
11713 {
11714 const auto line =
11715 raw_line_iterator(&triangulation,
11716 0,
11717 line_indices[k]);
11718 if (!line->has_children() &&
11720 line_refinement_case(
11721 cell->refine_flag_set(), k) !=
11723 line->set_user_flag();
11724 }
11725
11726 break;
11727 }
11728 }
11729
11730 if (offending_line_found)
11731 {
11732 mesh_changed = true;
11733 break;
11734 }
11735 }
11736 }
11737 }
11738
11739
11740 // there is another thing here: if any of the lines will
11741 // be refined, then we may not coarsen the present cell
11742 // similarly, if any of the lines *is* already refined, we
11743 // may not coarsen the current cell. however, there's a
11744 // catch: if the line is refined, but the cell behind it
11745 // is going to be coarsened, then the situation
11746 // changes. if we forget this second condition, the
11747 // refine_and_coarsen_3d test will start to fail. note
11748 // that to know which cells are going to be coarsened, the
11749 // call for fix_coarsen_flags above is necessary
11752 cell != triangulation.end();
11753 --cell)
11754 if (cell->user_flag_set())
11755 {
11756 const std::array<unsigned int, 12> line_indices =
11757 TriaAccessorImplementation::Implementation::
11758 get_line_indices_of_cell(*cell);
11759 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11760 {
11761 raw_line_iterator line(&triangulation,
11762 0,
11763 line_indices[l]);
11764 if (line->has_children() &&
11765 (line->child(0)->user_flag_set() ||
11766 line->child(1)->user_flag_set()))
11767 {
11768 for (unsigned int c = 0; c < cell->n_children(); ++c)
11769 cell->child(c)->clear_coarsen_flag();
11770 cell->clear_user_flag();
11771 for (unsigned int k = 0; k < cell->n_lines(); ++k)
11773 cell->refinement_case(), k) ==
11775 // flag a line, that is refined and will
11776 // stay so
11777 raw_line_iterator(&triangulation,
11778 0,
11779 line_indices[k])
11780 ->set_user_flag();
11781 mesh_changed = true;
11782 break;
11783 }
11784 }
11785 }
11786 }
11787 while (mesh_changed == true);
11788 }
11789
11790
11791
11798 template <int dim, int spacedim>
11799 static bool
11802 {
11803 // in 1d, coarsening is always allowed since we don't enforce
11804 // the 2:1 constraint there
11805 if (dim == 1)
11806 return true;
11807
11808 const RefinementCase<dim> ref_case = cell->refinement_case();
11809 for (const unsigned int n : GeometryInfo<dim>::face_indices())
11810 {
11811 // if the cell is not refined along that face, coarsening
11812 // will not change anything, so do nothing. the same
11813 // applies, if the face is at the boundary
11814 const RefinementCase<dim - 1> face_ref_case =
11815 GeometryInfo<dim>::face_refinement_case(cell->refinement_case(),
11816 n);
11817
11818 const unsigned int n_subfaces =
11819 GeometryInfo<dim - 1>::n_children(face_ref_case);
11820
11821 if (n_subfaces == 0 || cell->at_boundary(n))
11822 continue;
11823 for (unsigned int c = 0; c < n_subfaces; ++c)
11824 {
11826 child = cell->child(
11828
11830 child_neighbor = child->neighbor(n);
11831 if (!child->neighbor_is_coarser(n))
11832 {
11833 // in 2d, if the child's neighbor is coarser, then it has
11834 // no children. however, in 3d it might be
11835 // otherwise. consider for example, that our face might be
11836 // refined with cut_x, but the neighbor is refined with
11837 // cut_xy at that face. then the neighbor pointers of the
11838 // children of our cell will point to the common neighbor
11839 // cell, not to its children. what we really want to know
11840 // in the following is, whether the neighbor cell is
11841 // refined twice with reference to our cell. that only
11842 // has to be asked, if the child's neighbor is not a
11843 // coarser one. we check whether some of the children on
11844 // the neighbor are not flagged for coarsening, in that
11845 // case we may not coarsen. it is enough to check the
11846 // first child because we have already fixed the coarsen
11847 // flags on finer levels
11848 if (child_neighbor->has_children() &&
11849 !(child_neighbor->child(0)->is_active() &&
11850 child_neighbor->child(0)->coarsen_flag_set()))
11851 return false;
11852
11853 // the same applies, if the neighbors children are not
11854 // refined but will be after refinement
11855 if (child_neighbor->refine_flag_set())
11856 return false;
11857 }
11858 }
11859 }
11860 return true;
11861 }
11862 };
11863
11864
11869 {
11870 template <int spacedim>
11871 static void
11874
11875 template <int dim, int spacedim>
11877 {
11878 std::vector<std::pair<unsigned int, unsigned int>> adjacent_cells(
11880 {numbers::invalid_unsigned_int, numbers::invalid_unsigned_int});
11881
11882 const auto set_entry = [&](const auto &face_index, const auto &cell) {
11883 const std::pair<unsigned int, unsigned int> cell_pair = {
11884 cell->level(), cell->index()};
11885 unsigned int index;
11886
11887 if (adjacent_cells[2 * face_index].first ==
11889 adjacent_cells[2 * face_index].second ==
11891 {
11892 index = 2 * face_index + 0;
11893 }
11894 else
11895 {
11896 Assert(((adjacent_cells[2 * face_index + 1].first ==
11898 (adjacent_cells[2 * face_index + 1].second ==
11901 index = 2 * face_index + 1;
11902 }
11903
11904 adjacent_cells[index] = cell_pair;
11905 };
11906
11907 const auto get_entry =
11908 [&](const auto &face_index,
11909 const auto &cell) -> TriaIterator<CellAccessor<dim, spacedim>> {
11910 auto test = adjacent_cells[2 * face_index];
11911
11912 if (test == std::pair<unsigned int, unsigned int>(cell->level(),
11913 cell->index()))
11914 test = adjacent_cells[2 * face_index + 1];
11915
11916 if ((test.first != numbers::invalid_unsigned_int) &&
11917 (test.second != numbers::invalid_unsigned_int))
11919 test.first,
11920 test.second);
11921 else
11923 };
11924
11925 for (const auto &cell : triangulation.cell_iterators())
11926 for (const auto &face : cell->face_iterators())
11927 {
11928 set_entry(face->index(), cell);
11929
11930 if (cell->is_active() && face->has_children())
11931 for (unsigned int c = 0; c < face->n_children(); ++c)
11932 set_entry(face->child(c)->index(), cell);
11933 }
11934
11935 for (const auto &cell : triangulation.cell_iterators())
11936 for (auto f : cell->face_indices())
11937 cell->set_neighbor(f, get_entry(cell->face(f)->index(), cell));
11938 }
11939
11940 template <int dim, int spacedim>
11941 static void
11945 std::vector<unsigned int> &line_cell_count,
11946 std::vector<unsigned int> &quad_cell_count)
11947 {
11949 (void)triangulation;
11950 (void)cell;
11951 (void)line_cell_count;
11952 (void)quad_cell_count;
11953 }
11954
11955 template <int dim, int spacedim>
11958 const bool check_for_distorted_cells)
11959 {
11960 return Implementation::execute_refinement_isotropic(
11961 triangulation, check_for_distorted_cells);
11962 }
11963
11964 template <int dim, int spacedim>
11965 static void
11968 {
11969 // nothing to do since anisotropy is not supported
11970 (void)triangulation;
11971 }
11972
11973 template <int dim, int spacedim>
11974 static void
11977 {
11978 Implementation::prepare_refinement_dim_dependent(triangulation);
11979 }
11980
11981 template <int dim, int spacedim>
11982 static bool
11985 {
11987
11988 return false;
11989 }
11990 };
11991
11992
11993 template <int dim, int spacedim>
11996 {
11997 static const FlatManifold<dim, spacedim> flat_manifold;
11998 return flat_manifold;
11999 }
12000 } // namespace TriangulationImplementation
12001} // namespace internal
12002
12003#ifndef DOXYGEN
12004
12005template <int dim, int spacedim>
12008
12009
12010
12011template <int dim, int spacedim>
12014 const MeshSmoothing smooth_grid,
12015 const bool check_for_distorted_cells)
12016 : cell_attached_data({0, 0, {}, {}})
12017 , smooth_grid(smooth_grid)
12018 , anisotropic_refinement(false)
12019 , check_for_distorted_cells(check_for_distorted_cells)
12020{
12021 if (dim == 1)
12022 {
12023 vertex_to_boundary_id_map_1d =
12024 std::make_unique<std::map<unsigned int, types::boundary_id>>();
12025 vertex_to_manifold_id_map_1d =
12026 std::make_unique<std::map<unsigned int, types::manifold_id>>();
12027 }
12028
12029 // connect the any_change signal to the other top level signals
12030 signals.create.connect(signals.any_change);
12031 signals.post_refinement.connect(signals.any_change);
12032 signals.clear.connect(signals.any_change);
12033 signals.mesh_movement.connect(signals.any_change);
12034}
12035
12036
12037
12038template <int dim, int spacedim>
12041 Triangulation<dim, spacedim> &&tria) noexcept
12042 : Subscriptor(std::move(tria))
12043 , smooth_grid(tria.smooth_grid)
12044 , reference_cells(std::move(tria.reference_cells))
12045 , periodic_face_pairs_level_0(std::move(tria.periodic_face_pairs_level_0))
12046 , periodic_face_map(std::move(tria.periodic_face_map))
12047 , levels(std::move(tria.levels))
12048 , faces(std::move(tria.faces))
12049 , vertices(std::move(tria.vertices))
12050 , vertices_used(std::move(tria.vertices_used))
12051 , manifolds(std::move(tria.manifolds))
12052 , anisotropic_refinement(tria.anisotropic_refinement)
12053 , check_for_distorted_cells(tria.check_for_distorted_cells)
12054 , number_cache(std::move(tria.number_cache))
12055 , vertex_to_boundary_id_map_1d(std::move(tria.vertex_to_boundary_id_map_1d))
12056 , vertex_to_manifold_id_map_1d(std::move(tria.vertex_to_manifold_id_map_1d))
12057{
12059
12060 if (tria.policy)
12061 this->policy = tria.policy->clone();
12062}
12063
12064
12065template <int dim, int spacedim>
12068 Triangulation<dim, spacedim> &&tria) noexcept
12069{
12070 Subscriptor::operator=(std::move(tria));
12071
12072 smooth_grid = tria.smooth_grid;
12073 reference_cells = std::move(tria.reference_cells);
12074 periodic_face_pairs_level_0 = std::move(tria.periodic_face_pairs_level_0);
12075 periodic_face_map = std::move(tria.periodic_face_map);
12076 levels = std::move(tria.levels);
12077 faces = std::move(tria.faces);
12078 vertices = std::move(tria.vertices);
12079 vertices_used = std::move(tria.vertices_used);
12080 manifolds = std::move(tria.manifolds);
12081 anisotropic_refinement = tria.anisotropic_refinement;
12082 number_cache = tria.number_cache;
12083 vertex_to_boundary_id_map_1d = std::move(tria.vertex_to_boundary_id_map_1d);
12084 vertex_to_manifold_id_map_1d = std::move(tria.vertex_to_manifold_id_map_1d);
12085
12087
12088 if (tria.policy)
12089 this->policy = tria.policy->clone();
12090
12091 return *this;
12092}
12093
12094
12095
12096template <int dim, int spacedim>
12099{
12100 // notify listeners that the triangulation is going down...
12101 try
12102 {
12103 signals.clear();
12104 }
12105 catch (...)
12106 {}
12107
12108 levels.clear();
12109
12110 // the vertex_to_boundary_id_map_1d field should be unused except in
12111 // 1d. double check this here, as destruction is a good place to
12112 // ensure that what we've done over the course of the lifetime of
12113 // this object makes sense
12114 AssertNothrow((dim == 1) || (vertex_to_boundary_id_map_1d == nullptr),
12116
12117 // the vertex_to_manifold_id_map_1d field should be also unused
12118 // except in 1d. check this as well
12119 AssertNothrow((dim == 1) || (vertex_to_manifold_id_map_1d == nullptr),
12121}
12122
12123
12124
12125template <int dim, int spacedim>
12128{
12129 // notify listeners that the triangulation is going down...
12130 signals.clear();
12131
12132 // ...and then actually clear all content of it
12133 clear_despite_subscriptions();
12134 periodic_face_pairs_level_0.clear();
12135 periodic_face_map.clear();
12136 reference_cells.clear();
12137
12138 cell_attached_data = {0, 0, {}, {}};
12139 data_serializer.clear();
12140}
12141
12142template <int dim, int spacedim>
12145{
12146 return MPI_COMM_SELF;
12147}
12148
12149
12150
12151template <int dim, int spacedim>
12153std::weak_ptr<const Utilities::MPI::Partitioner> Triangulation<dim, spacedim>::
12155{
12156 return number_cache.active_cell_index_partitioner;
12157}
12158
12159
12160
12161template <int dim, int spacedim>
12163std::weak_ptr<const Utilities::MPI::Partitioner> Triangulation<dim, spacedim>::
12164 global_level_cell_index_partitioner(const unsigned int level) const
12165{
12166 AssertIndexRange(level, this->n_levels());
12167
12168 return number_cache.level_cell_index_partitioners[level];
12169}
12170
12171
12172
12173template <int dim, int spacedim>
12176 const MeshSmoothing mesh_smoothing)
12177{
12178 smooth_grid = mesh_smoothing;
12179}
12180
12181
12182
12183template <int dim, int spacedim>
12187{
12188 return smooth_grid;
12189}
12190
12191
12192
12193template <int dim, int spacedim>
12196 const types::manifold_id m_number,
12197 const Manifold<dim, spacedim> &manifold_object)
12198{
12200
12201 manifolds[m_number] = manifold_object.clone();
12202}
12203
12204
12205
12206template <int dim, int spacedim>
12209 const types::manifold_id m_number)
12210{
12212
12213 // delete the entry located at number.
12214 manifolds[m_number] =
12216 spacedim>()
12217 .clone();
12218}
12219
12220
12221template <int dim, int spacedim>
12224{
12225 for (auto &m : manifolds)
12226 m.second = internal::TriangulationImplementation::
12227 get_default_flat_manifold<dim, spacedim>()
12228 .clone();
12229}
12230
12231
12232template <int dim, int spacedim>
12235 const types::manifold_id m_number)
12236{
12237 Assert(
12238 n_cells() > 0,
12239 ExcMessage(
12240 "Error: set_all_manifold_ids() can not be called on an empty Triangulation."));
12241
12242 for (const auto &cell : this->active_cell_iterators())
12243 cell->set_all_manifold_ids(m_number);
12244}
12245
12246
12247template <int dim, int spacedim>
12250 const types::manifold_id m_number)
12251{
12252 Assert(
12253 n_cells() > 0,
12254 ExcMessage(
12255 "Error: set_all_manifold_ids_on_boundary() can not be called on an empty Triangulation."));
12256
12257 for (const auto &cell : this->active_cell_iterators())
12258 for (auto f : GeometryInfo<dim>::face_indices())
12259 if (cell->face(f)->at_boundary())
12260 cell->face(f)->set_all_manifold_ids(m_number);
12261}
12262
12263
12264template <int dim, int spacedim>
12267 const types::boundary_id b_id,
12268 const types::manifold_id m_number)
12269{
12270 Assert(
12271 n_cells() > 0,
12272 ExcMessage(
12273 "Error: set_all_manifold_ids_on_boundary() can not be called on an empty Triangulation."));
12274
12275 bool boundary_found = false;
12276
12277 for (const auto &cell : this->active_cell_iterators())
12278 {
12279 // loop on faces
12280 for (auto f : GeometryInfo<dim>::face_indices())
12281 if (cell->face(f)->at_boundary() &&
12282 cell->face(f)->boundary_id() == b_id)
12283 {
12284 boundary_found = true;
12285 cell->face(f)->set_manifold_id(m_number);
12286 }
12287
12288 // loop on edges if dim >= 3
12289 if (dim >= 3)
12290 for (unsigned int e = 0; e < GeometryInfo<dim>::lines_per_cell; ++e)
12291 if (cell->line(e)->at_boundary() &&
12292 cell->line(e)->boundary_id() == b_id)
12293 {
12294 boundary_found = true;
12295 cell->line(e)->set_manifold_id(m_number);
12296 }
12297 }
12298
12299 (void)boundary_found;
12300 Assert(boundary_found, ExcBoundaryIdNotFound(b_id));
12301}
12302
12303
12304
12305template <int dim, int spacedim>
12308 const types::manifold_id m_number) const
12309{
12310 // check if flat manifold has been queried
12311 if (m_number == numbers::flat_manifold_id)
12314
12315 // look, if there is a manifold stored at
12316 // manifold_id number.
12317 const auto it = manifolds.find(m_number);
12318
12319 if (it != manifolds.end())
12320 {
12321 // if we have found an entry, return it
12322 return *(it->second);
12323 }
12324
12325 Assert(
12326 false,
12327 ExcMessage(
12328 "No manifold of the manifold id " + std::to_string(m_number) +
12329 " has been attached to the triangulation. "
12330 "Please attach the right manifold with Triangulation::set_manifold()."));
12331
12334}
12335
12336
12337
12338template <int dim, int spacedim>
12340std::vector<types::boundary_id> Triangulation<dim, spacedim>::get_boundary_ids()
12341 const
12342{
12343 // in 1d, we store a map of all used boundary indicators. use it for
12344 // our purposes
12345 if (dim == 1)
12346 {
12347 std::vector<types::boundary_id> boundary_ids;
12348 for (std::map<unsigned int, types::boundary_id>::const_iterator p =
12349 vertex_to_boundary_id_map_1d->begin();
12350 p != vertex_to_boundary_id_map_1d->end();
12351 ++p)
12352 boundary_ids.push_back(p->second);
12353
12354 return boundary_ids;
12355 }
12356 else
12357 {
12358 std::set<types::boundary_id> b_ids;
12359 for (auto cell : active_cell_iterators())
12360 if (cell->is_locally_owned())
12361 for (const unsigned int face : cell->face_indices())
12362 if (cell->at_boundary(face))
12363 b_ids.insert(cell->face(face)->boundary_id());
12364 std::vector<types::boundary_id> boundary_ids(b_ids.begin(), b_ids.end());
12365 return boundary_ids;
12366 }
12367}
12368
12369
12370
12371template <int dim, int spacedim>
12373std::vector<types::manifold_id> Triangulation<dim, spacedim>::get_manifold_ids()
12374 const
12375{
12376 std::set<types::manifold_id> m_ids;
12377 for (const auto &cell : active_cell_iterators())
12378 if (cell->is_locally_owned())
12379 {
12380 m_ids.insert(cell->manifold_id());
12381 for (const auto &face : cell->face_iterators())
12382 m_ids.insert(face->manifold_id());
12383 if (dim == 3)
12384 {
12385 const auto line_indices = internal::TriaAccessorImplementation::
12386 Implementation::get_line_indices_of_cell(*cell);
12387 for (unsigned int l = 0; l < cell->n_lines(); ++l)
12388 {
12389 raw_line_iterator line(this, 0, line_indices[l]);
12390 m_ids.insert(line->manifold_id());
12391 }
12392 }
12393 }
12394 return {m_ids.begin(), m_ids.end()};
12395}
12396
12397#endif
12398/*-----------------------------------------------------------------*/
12399
12400#ifndef DOXYGEN
12401
12402template <int dim, int spacedim>
12405 const Triangulation<dim, spacedim> &other_tria)
12406{
12407 Assert((vertices.empty()) && (levels.empty()) && (faces == nullptr),
12408 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
12409 Assert((other_tria.levels.size() != 0) && (other_tria.vertices.size() != 0) &&
12410 (dim == 1 || other_tria.faces != nullptr),
12411 ExcMessage(
12412 "When calling Triangulation::copy_triangulation(), "
12413 "the target triangulation must be empty but the source "
12414 "triangulation (the argument to this function) must contain "
12415 "something. Here, it seems like the source does not "
12416 "contain anything at all."));
12417
12418
12419 // copy normal elements
12420 vertices = other_tria.vertices;
12421 vertices_used = other_tria.vertices_used;
12422 anisotropic_refinement = other_tria.anisotropic_refinement;
12423 smooth_grid = other_tria.smooth_grid;
12424 reference_cells = other_tria.reference_cells;
12425
12426 if (dim > 1)
12427 faces = std::make_unique<internal::TriangulationImplementation::TriaFaces>(
12428 *other_tria.faces);
12429
12430 for (const auto &p : other_tria.manifolds)
12431 set_manifold(p.first, *p.second);
12432
12433
12434 levels.reserve(other_tria.levels.size());
12435 for (unsigned int level = 0; level < other_tria.levels.size(); ++level)
12436 levels.push_back(
12437 std::make_unique<internal::TriangulationImplementation::TriaLevel>(
12438 *other_tria.levels[level]));
12439
12440 number_cache = other_tria.number_cache;
12441
12442 if (dim == 1)
12443 {
12444 vertex_to_boundary_id_map_1d =
12445 std::make_unique<std::map<unsigned int, types::boundary_id>>(
12446 *other_tria.vertex_to_boundary_id_map_1d);
12447
12448 vertex_to_manifold_id_map_1d =
12449 std::make_unique<std::map<unsigned int, types::manifold_id>>(
12450 *other_tria.vertex_to_manifold_id_map_1d);
12451 }
12452
12453 if (other_tria.policy)
12454 this->policy = other_tria.policy->clone();
12455
12456 // periodic faces
12457 this->periodic_face_pairs_level_0.reserve(
12458 other_tria.periodic_face_pairs_level_0.size());
12459
12460 for (const auto &other_entry : other_tria.periodic_face_pairs_level_0)
12461 {
12462 auto entry = other_entry;
12463 entry.cell[0] =
12464 cell_iterator(this, entry.cell[0]->level(), entry.cell[0]->index());
12465 entry.cell[1] =
12466 cell_iterator(this, entry.cell[1]->level(), entry.cell[1]->index());
12467 periodic_face_pairs_level_0.emplace_back(entry);
12468 }
12469
12470 for (auto [first_cell_, second_cell_and_orientation] :
12471 other_tria.periodic_face_map)
12472 {
12473 auto first_cell = first_cell_; // make copy since key is const
12474 first_cell.first = cell_iterator(this,
12475 first_cell.first->level(),
12476 first_cell.first->index());
12477 second_cell_and_orientation.first.first =
12478 cell_iterator(this,
12479 second_cell_and_orientation.first.first->level(),
12480 second_cell_and_orientation.first.first->index());
12481
12482 this->periodic_face_map[first_cell] = second_cell_and_orientation;
12483 }
12484
12485 // inform those who are listening on other_tria of the copy operation
12486 other_tria.signals.copy(*this);
12487 // also inform all listeners of the current triangulation that the
12488 // triangulation has been created
12489 signals.create();
12490
12491 // note that we need not copy the
12492 // subscriptor!
12493}
12494
12495
12496
12497template <int dim, int spacedim>
12500{
12501 this->update_reference_cells();
12502
12503 if (this->all_reference_cells_are_hyper_cube())
12504 {
12505 this->policy =
12507 dim,
12508 spacedim,
12510 }
12511 else
12512 {
12513 this->policy =
12515 dim,
12516 spacedim,
12518 }
12519}
12520
12521
12522
12523template <int dim, int spacedim>
12526 const std::vector<Point<spacedim>> &v,
12527 const std::vector<CellData<dim>> &cells,
12528 const SubCellData &subcelldata)
12529{
12530 Assert((vertices.empty()) && (levels.empty()) && (faces == nullptr),
12531 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
12532 // check that no forbidden arrays
12533 // are used
12534 Assert(subcelldata.check_consistency(dim), ExcInternalError());
12535
12536 // try to create a triangulation; if this fails, we still want to
12537 // throw an exception but if we just do so we'll get into trouble
12538 // because sometimes other objects are already attached to it:
12539 try
12540 {
12542 create_triangulation(v, cells, subcelldata, *this);
12543 }
12544 catch (...)
12545 {
12546 clear_despite_subscriptions();
12547 throw;
12548 }
12549
12550 reset_policy();
12551
12552 // update our counts of the various elements of a triangulation, and set
12553 // active_cell_indices of all cells
12554 reset_cell_vertex_indices_cache();
12556 *this, levels.size(), number_cache);
12557 reset_active_cell_indices();
12558 reset_global_cell_indices();
12559
12560 // now verify that there are indeed no distorted cells. as per the
12561 // documentation of this class, we first collect all distorted cells
12562 // and then throw an exception if there are any
12563 if (check_for_distorted_cells)
12564 {
12565 DistortedCellList distorted_cells = collect_distorted_coarse_cells(*this);
12566 // throw the array (and fill the various location fields) if
12567 // there are distorted cells. otherwise, just fall off the end
12568 // of the function
12569 AssertThrow(distorted_cells.distorted_cells.empty(), distorted_cells);
12570 }
12571
12572
12573 /*
12574 When the triangulation is a manifold (dim < spacedim) and made of
12575 quadrilaterals, the normal field provided from the map class depends on
12576 the order of the vertices. It may happen that this normal field is
12577 discontinuous. The following code takes care that this is not the case by
12578 setting the cell direction flag on those cell that produce the wrong
12579 orientation.
12580
12581 To determine if 2 neighbors have the same or opposite orientation we use
12582 a truth table. Its entries are indexed by the local indices of the
12583 common face. For example if two elements share a face, and this face is
12584 face 0 for element 0 and face 1 for element 1, then table(0,1) will tell
12585 whether the orientation are the same (true) or opposite (false).
12586
12587 Even though there may be a combinatorial/graph theory argument to get this
12588 table in any dimension, I tested by hand all the different possible cases
12589 in 1D and 2D to generate the table.
12590
12591 Assuming that a surface respects the standard orientation for 2d meshes,
12592 the truth tables are symmetric and their true values are the following
12593
12594 - 1D curves: (0,1)
12595 - 2D surface: (0,1),(0,2),(1,3),(2,3)
12596
12597 We store this data using an n_faces x n_faces full matrix, which is
12598 actually much bigger than the minimal data required, but it makes the code
12599 more readable.
12600
12601 */
12602 if ((dim == spacedim - 1) && all_reference_cells_are_hyper_cube())
12603 {
12606 switch (dim)
12607 {
12608 case 1:
12609 {
12610 const bool values[][2] = {{false, true}, {true, false}};
12611 for (const unsigned int i : GeometryInfo<dim>::face_indices())
12612 for (const unsigned int j : GeometryInfo<dim>::face_indices())
12613 correct(i, j) = values[i][j];
12614 break;
12615 }
12616 case 2:
12617 {
12618 const bool values[][4] = {{false, true, true, false},
12619 {true, false, false, true},
12620 {true, false, false, true},
12621 {false, true, true, false}};
12622 for (const unsigned int i : GeometryInfo<dim>::face_indices())
12623 for (const unsigned int j : GeometryInfo<dim>::face_indices())
12624 correct(i, j) = (values[i][j]);
12625 break;
12626 }
12627 default:
12629 }
12630
12631
12632 std::list<active_cell_iterator> this_round, next_round;
12633 active_cell_iterator neighbor;
12634
12635 // Start with the first cell and (arbitrarily) decide that its
12636 // direction flag should be 'true':
12637 this_round.push_back(begin_active());
12638 begin_active()->set_direction_flag(true);
12639 begin_active()->set_user_flag();
12640
12641 while (this_round.size() > 0)
12642 {
12643 for (const auto &cell : this_round)
12644 {
12645 for (const unsigned int i : cell->face_indices())
12646 {
12647 if (cell->face(i)->at_boundary() == false)
12648 {
12649 // Consider the i'th neighbor of a cell for
12650 // which we have already set the direction:
12651 neighbor = cell->neighbor(i);
12652
12653 const unsigned int nb_of_nb =
12654 cell->neighbor_of_neighbor(i);
12655
12656 // If we already saw this neighboring cell,
12657 // check that everything is fine:
12658 if (neighbor->user_flag_set())
12659 {
12660 Assert(
12661 !(correct(i, nb_of_nb) ^
12662 (neighbor->direction_flag() ==
12663 cell->direction_flag())),
12664 ExcMessage(
12665 "The triangulation you are trying to create is not orientable."));
12666 }
12667 else
12668 {
12669 // We had not seen this cell yet. Set its
12670 // orientation flag (if necessary), mark it
12671 // as treated via the user flag, and push it
12672 // onto the list of cells to start work from
12673 // the next time around:
12674 if (correct(i, nb_of_nb) ^
12675 (neighbor->direction_flag() ==
12676 cell->direction_flag()))
12677 neighbor->set_direction_flag(
12678 !neighbor->direction_flag());
12679 neighbor->set_user_flag();
12680 next_round.push_back(neighbor);
12681 }
12682 }
12683 }
12684 }
12685
12686 // Before we quit let's check that if the triangulation is
12687 // disconnected that we still get all cells by starting
12688 // again from the first cell we haven't treated yet -- that
12689 // is, the first cell of the next disconnected component we
12690 // had not yet touched.
12691 if (next_round.empty())
12692 for (const auto &cell : this->active_cell_iterators())
12693 if (cell->user_flag_set() == false)
12694 {
12695 next_round.push_back(cell);
12696 cell->set_direction_flag(true);
12697 cell->set_user_flag();
12698 break;
12699 }
12700
12701 // Go on to the next round:
12702 next_round.swap(this_round);
12703 next_round.clear();
12704 }
12705 clear_user_flags();
12706 }
12707
12708 this->update_cell_relations();
12709
12710 // inform all listeners that the triangulation has been created
12711 signals.create();
12712}
12713
12714
12715
12716template <int dim, int spacedim>
12720{
12721 // 1) create coarse grid
12723 construction_data.coarse_cells,
12724 SubCellData());
12725
12726 // create a copy of cell_infos such that we can sort them
12727 auto cell_infos = construction_data.cell_infos;
12728
12729 // sort cell_infos on each level separately
12730 for (auto &cell_info : cell_infos)
12731 std::sort(
12732 cell_info.begin(),
12733 cell_info.end(),
12736 const CellId a_id(a.id);
12737 const CellId b_id(b.id);
12738
12739 const auto a_coarse_cell_index =
12740 this->coarse_cell_id_to_coarse_cell_index(a_id.get_coarse_cell_id());
12741 const auto b_coarse_cell_index =
12742 this->coarse_cell_id_to_coarse_cell_index(b_id.get_coarse_cell_id());
12743
12744 // according to their coarse-cell index and if that is
12745 // same according to their cell id (the result is that
12746 // cells on each level are sorted according to their
12747 // index on that level - what we need in the following
12748 // operations)
12749 if (a_coarse_cell_index != b_coarse_cell_index)
12750 return a_coarse_cell_index < b_coarse_cell_index;
12751 else
12752 return a_id < b_id;
12753 });
12754
12755 // 2) create all levels via a sequence of refinements. note that
12756 // we must make sure that we actually have cells on this level,
12757 // which is not clear in a parallel context for some processes
12758 for (unsigned int level = 0;
12759 level < cell_infos.size() && !cell_infos[level].empty();
12760 ++level)
12761 {
12762 // a) set manifold ids here (because new vertices have to be
12763 // positioned correctly during each refinement step)
12764 {
12765 auto cell = this->begin(level);
12766 auto cell_info = cell_infos[level].begin();
12767 for (; cell_info != cell_infos[level].end(); ++cell_info)
12768 {
12769 while (cell_info->id != cell->id().template to_binary<dim>())
12770 ++cell;
12771 if (dim == 2)
12772 for (const auto face : cell->face_indices())
12773 cell->face(face)->set_manifold_id(
12774 cell_info->manifold_line_ids[face]);
12775 else if (dim == 3)
12776 {
12777 for (const auto face : cell->face_indices())
12778 cell->face(face)->set_manifold_id(
12779 cell_info->manifold_quad_ids[face]);
12780
12781 const auto line_indices = internal::TriaAccessorImplementation::
12782 Implementation::get_line_indices_of_cell(*cell);
12783 for (unsigned int l = 0; l < cell->n_lines(); ++l)
12784 {
12785 raw_line_iterator line(this, 0, line_indices[l]);
12786 line->set_manifold_id(cell_info->manifold_line_ids[l]);
12787 }
12788 }
12789
12790 cell->set_manifold_id(cell_info->manifold_id);
12791 }
12792 }
12793
12794 // b) perform refinement on all levels but on the finest
12795 if (level + 1 != cell_infos.size())
12796 {
12797 // find cells that should have children and mark them for
12798 // refinement
12799 auto coarse_cell = this->begin(level);
12800 auto fine_cell_info = cell_infos[level + 1].begin();
12801
12802 // loop over all cells on the next level
12803 for (; fine_cell_info != cell_infos[level + 1].end();
12804 ++fine_cell_info)
12805 {
12806 // find the parent of that cell
12807 while (
12808 !coarse_cell->id().is_parent_of(CellId(fine_cell_info->id)))
12809 ++coarse_cell;
12810
12811 // set parent for refinement
12812 coarse_cell->set_refine_flag();
12813 }
12814
12815 // execute refinement
12816 ::Triangulation<dim,
12817 spacedim>::execute_coarsening_and_refinement();
12818 }
12819 }
12820
12821 // 3) set boundary ids
12822 for (unsigned int level = 0;
12823 level < cell_infos.size() && !cell_infos[level].empty();
12824 ++level)
12825 {
12826 auto cell = this->begin(level);
12827 auto cell_info = cell_infos[level].begin();
12828 for (; cell_info != cell_infos[level].end(); ++cell_info)
12829 {
12830 // find cell that has the correct cell
12831 while (cell_info->id != cell->id().template to_binary<dim>())
12832 ++cell;
12833
12834 // boundary ids
12835 for (auto pair : cell_info->boundary_ids)
12836 if (cell->face(pair.first)->at_boundary())
12837 cell->face(pair.first)->set_boundary_id(pair.second);
12838 }
12839 }
12840
12841 // inform all listeners that the triangulation has been created
12842 signals.create();
12843}
12844
12845
12846template <int dim, int spacedim>
12849{
12850 AssertThrow(dim + 1 == spacedim,
12851 ExcMessage(
12852 "This function can only be called if dim == spacedim-1."));
12853 for (const auto &cell : this->active_cell_iterators())
12854 cell->set_direction_flag(!cell->direction_flag());
12855}
12856
12857
12858
12859template <int dim, int spacedim>
12862{
12863 Assert(n_cells() > 0,
12864 ExcMessage("Error: An empty Triangulation can not be refined."));
12865
12866 for (const auto &cell : this->active_cell_iterators())
12867 {
12868 cell->clear_coarsen_flag();
12869 cell->set_refine_flag();
12870 cell->set_refine_choice();
12871 }
12872}
12873
12874
12875
12876template <int dim, int spacedim>
12878void Triangulation<dim, spacedim>::refine_global(const unsigned int times)
12879{
12880 for (unsigned int i = 0; i < times; ++i)
12881 {
12882 set_all_refine_flags();
12883 execute_coarsening_and_refinement();
12884 }
12885}
12886
12887
12888
12889template <int dim, int spacedim>
12891void Triangulation<dim, spacedim>::coarsen_global(const unsigned int times)
12892{
12893 for (unsigned int i = 0; i < times; ++i)
12894 {
12895 for (const auto &cell : this->active_cell_iterators())
12896 {
12897 cell->clear_refine_flag();
12898 cell->set_coarsen_flag();
12899 }
12900 execute_coarsening_and_refinement();
12901 }
12902}
12903
12904
12905#endif
12906/*-------------------- refine/coarsen flags -------------------------*/
12907
12908#ifndef DOXYGEN
12909
12910template <int dim, int spacedim>
12912void Triangulation<dim, spacedim>::save_refine_flags(std::vector<bool> &v) const
12913{
12914 v.resize(dim * n_active_cells(), false);
12915 std::vector<bool>::iterator i = v.begin();
12916
12917 for (const auto &cell : this->active_cell_iterators())
12918 for (unsigned int j = 0; j < dim; ++j, ++i)
12919 if (cell->refine_flag_set() & (1 << j))
12920 *i = true;
12921
12922 Assert(i == v.end(), ExcInternalError());
12923}
12924
12925
12926
12927template <int dim, int spacedim>
12929void Triangulation<dim, spacedim>::save_refine_flags(std::ostream &out) const
12930{
12931 std::vector<bool> v;
12932 save_refine_flags(v);
12933 write_bool_vector(mn_tria_refine_flags_begin,
12934 v,
12936 out);
12937}
12938
12939
12940
12941template <int dim, int spacedim>
12944{
12945 std::vector<bool> v;
12946 read_bool_vector(mn_tria_refine_flags_begin, v, mn_tria_refine_flags_end, in);
12947 load_refine_flags(v);
12948}
12949
12950
12951
12952template <int dim, int spacedim>
12954void Triangulation<dim, spacedim>::load_refine_flags(const std::vector<bool> &v)
12955{
12956 AssertThrow(v.size() == dim * n_active_cells(), ExcGridReadError());
12957
12958 std::vector<bool>::const_iterator i = v.begin();
12959 for (const auto &cell : this->active_cell_iterators())
12960 {
12961 unsigned int ref_case = 0;
12962
12963 for (unsigned int j = 0; j < dim; ++j, ++i)
12964 if (*i == true)
12965 ref_case += 1 << j;
12967 ExcGridReadError());
12968 if (ref_case > 0)
12969 cell->set_refine_flag(RefinementCase<dim>(ref_case));
12970 else
12971 cell->clear_refine_flag();
12972 }
12973
12974 Assert(i == v.end(), ExcInternalError());
12975}
12976
12977
12978
12979template <int dim, int spacedim>
12982 std::vector<bool> &v) const
12983{
12984 v.resize(n_active_cells(), false);
12985 std::vector<bool>::iterator i = v.begin();
12986 for (const auto &cell : this->active_cell_iterators())
12987 {
12988 *i = cell->coarsen_flag_set();
12989 ++i;
12990 }
12991
12992 Assert(i == v.end(), ExcInternalError());
12993}
12994
12995
12996
12997template <int dim, int spacedim>
12999void Triangulation<dim, spacedim>::save_coarsen_flags(std::ostream &out) const
13000{
13001 std::vector<bool> v;
13002 save_coarsen_flags(v);
13003 write_bool_vector(mn_tria_coarsen_flags_begin,
13004 v,
13006 out);
13007}
13008
13009
13010
13011template <int dim, int spacedim>
13014{
13015 std::vector<bool> v;
13016 read_bool_vector(mn_tria_coarsen_flags_begin,
13017 v,
13019 in);
13020 load_coarsen_flags(v);
13021}
13022
13023
13024
13025template <int dim, int spacedim>
13028 const std::vector<bool> &v)
13029{
13030 Assert(v.size() == n_active_cells(), ExcGridReadError());
13031
13032 std::vector<bool>::const_iterator i = v.begin();
13033 for (const auto &cell : this->active_cell_iterators())
13034 {
13035 if (*i == true)
13036 cell->set_coarsen_flag();
13037 else
13038 cell->clear_coarsen_flag();
13039 ++i;
13040 }
13041
13042 Assert(i == v.end(), ExcInternalError());
13043}
13044
13045
13046template <int dim, int spacedim>
13049{
13050 return anisotropic_refinement;
13051}
13052
13053
13054#endif
13055
13056namespace internal
13057{
13058 namespace
13059 {
13060 std::vector<std::vector<bool>>
13061 extract_raw_coarsen_flags(
13062 const std::vector<std::unique_ptr<
13064 {
13065 std::vector<std::vector<bool>> coarsen_flags(levels.size());
13066 for (unsigned int level = 0; level < levels.size(); ++level)
13067 coarsen_flags[level] = levels[level]->coarsen_flags;
13068 return coarsen_flags;
13069 }
13070
13071 std::vector<std::vector<std::uint8_t>>
13072 extract_raw_refine_flags(
13073 const std::vector<std::unique_ptr<
13075 {
13076 std::vector<std::vector<std::uint8_t>> refine_flags(levels.size());
13077 for (unsigned int level = 0; level < levels.size(); ++level)
13078 refine_flags[level] = levels[level]->refine_flags;
13079 return refine_flags;
13080 }
13081 } // namespace
13082} // namespace internal
13083
13084
13085/*-------------------- user data/flags -------------------------*/
13086
13087
13088namespace
13089{
13090 // clear user data of cells
13091 void
13092 clear_user_data(std::vector<std::unique_ptr<
13094 {
13095 for (auto &level : levels)
13096 level->cells.clear_user_data();
13097 }
13098
13099
13100 // clear user data of faces
13101 void
13103 {
13104 if (faces->dim == 2)
13105 {
13106 faces->lines.clear_user_data();
13107 }
13108
13109
13110 if (faces->dim == 3)
13111 {
13112 faces->lines.clear_user_data();
13113 faces->quads.clear_user_data();
13114 }
13115 }
13116} // namespace
13117
13118#ifndef DOXYGEN
13119
13120template <int dim, int spacedim>
13123{
13124 // let functions in anonymous namespace do their work
13125 ::clear_user_data(levels);
13126 if (dim > 1)
13127 ::clear_user_data(faces.get());
13128}
13129
13130
13131
13132namespace
13133{
13134 void
13135 clear_user_flags_line(
13136 unsigned int dim,
13137 std::vector<
13138 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
13139 &levels,
13141 {
13142 if (dim == 1)
13143 {
13144 for (const auto &level : levels)
13145 level->cells.clear_user_flags();
13146 }
13147 else if (dim == 2 || dim == 3)
13148 {
13149 faces->lines.clear_user_flags();
13150 }
13151 else
13152 {
13154 }
13155 }
13156} // namespace
13157
13158
13159template <int dim, int spacedim>
13162{
13163 ::clear_user_flags_line(dim, levels, faces.get());
13164}
13165
13166
13167
13168namespace
13169{
13170 void
13171 clear_user_flags_quad(
13172 unsigned int dim,
13173 std::vector<
13174 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
13175 &levels,
13177 {
13178 if (dim == 1)
13179 {
13180 // nothing to do in 1d
13181 }
13182 else if (dim == 2)
13183 {
13184 for (const auto &level : levels)
13185 level->cells.clear_user_flags();
13186 }
13187 else if (dim == 3)
13188 {
13189 faces->quads.clear_user_flags();
13190 }
13191 else
13192 {
13194 }
13195 }
13196} // namespace
13197
13198
13199template <int dim, int spacedim>
13202{
13203 ::clear_user_flags_quad(dim, levels, faces.get());
13204}
13205
13206
13207
13208namespace
13209{
13210 void
13211 clear_user_flags_hex(
13212 unsigned int dim,
13213 std::vector<
13214 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
13215 &levels,
13217 {
13218 if (dim == 1)
13219 {
13220 // nothing to do in 1d
13221 }
13222 else if (dim == 2)
13223 {
13224 // nothing to do in 2d
13225 }
13226 else if (dim == 3)
13227 {
13228 for (const auto &level : levels)
13229 level->cells.clear_user_flags();
13230 }
13231 else
13232 {
13234 }
13235 }
13236} // namespace
13237
13238
13239template <int dim, int spacedim>
13242{
13243 ::clear_user_flags_hex(dim, levels, faces.get());
13244}
13245
13246
13247
13248template <int dim, int spacedim>
13251{
13252 clear_user_flags_line();
13253 clear_user_flags_quad();
13254 clear_user_flags_hex();
13255}
13256
13257
13258
13259template <int dim, int spacedim>
13261void Triangulation<dim, spacedim>::save_user_flags(std::ostream &out) const
13262{
13263 save_user_flags_line(out);
13264
13265 if (dim >= 2)
13266 save_user_flags_quad(out);
13267
13268 if (dim >= 3)
13269 save_user_flags_hex(out);
13270
13271 if (dim >= 4)
13273}
13274
13275
13276
13277template <int dim, int spacedim>
13279void Triangulation<dim, spacedim>::save_user_flags(std::vector<bool> &v) const
13280{
13281 // clear vector and append
13282 // all the stuff later on
13283 v.clear();
13284
13285 std::vector<bool> tmp;
13286
13287 save_user_flags_line(tmp);
13288 v.insert(v.end(), tmp.begin(), tmp.end());
13289
13290 if (dim >= 2)
13291 {
13292 save_user_flags_quad(tmp);
13293 v.insert(v.end(), tmp.begin(), tmp.end());
13294 }
13295
13296 if (dim >= 3)
13297 {
13298 save_user_flags_hex(tmp);
13299 v.insert(v.end(), tmp.begin(), tmp.end());
13300 }
13301
13302 if (dim >= 4)
13304}
13305
13306
13307
13308template <int dim, int spacedim>
13311{
13312 load_user_flags_line(in);
13313
13314 if (dim >= 2)
13315 load_user_flags_quad(in);
13316
13317 if (dim >= 3)
13318 load_user_flags_hex(in);
13319
13320 if (dim >= 4)
13322}
13323
13324
13325
13326template <int dim, int spacedim>
13328void Triangulation<dim, spacedim>::load_user_flags(const std::vector<bool> &v)
13329{
13330 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
13331 std::vector<bool> tmp;
13332
13333 // first extract the flags
13334 // belonging to lines
13335 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
13336 // and set the lines
13337 load_user_flags_line(tmp);
13338
13339 if (dim >= 2)
13340 {
13341 tmp.clear();
13342 tmp.insert(tmp.end(),
13343 v.begin() + n_lines(),
13344 v.begin() + n_lines() + n_quads());
13345 load_user_flags_quad(tmp);
13346 }
13347
13348 if (dim >= 3)
13349 {
13350 tmp.clear();
13351 tmp.insert(tmp.end(),
13352 v.begin() + n_lines() + n_quads(),
13353 v.begin() + n_lines() + n_quads() + n_hexs());
13354 load_user_flags_hex(tmp);
13355 }
13356
13357 if (dim >= 4)
13359}
13360
13361
13362
13363template <int dim, int spacedim>
13366 std::vector<bool> &v) const
13367{
13368 v.resize(n_lines(), false);
13369 std::vector<bool>::iterator i = v.begin();
13370 line_iterator line = begin_line(), endl = end_line();
13371 for (; line != endl; ++line, ++i)
13372 *i = line->user_flag_set();
13373
13374 Assert(i == v.end(), ExcInternalError());
13375}
13376
13377
13378
13379template <int dim, int spacedim>
13381void Triangulation<dim, spacedim>::save_user_flags_line(std::ostream &out) const
13382{
13383 std::vector<bool> v;
13384 save_user_flags_line(v);
13385 write_bool_vector(mn_tria_line_user_flags_begin,
13386 v,
13388 out);
13389}
13390
13391
13392
13393template <int dim, int spacedim>
13396{
13397 std::vector<bool> v;
13398 read_bool_vector(mn_tria_line_user_flags_begin,
13399 v,
13401 in);
13402 load_user_flags_line(v);
13403}
13404
13405
13406
13407template <int dim, int spacedim>
13410 const std::vector<bool> &v)
13411{
13412 Assert(v.size() == n_lines(), ExcGridReadError());
13413
13414 line_iterator line = begin_line(), endl = end_line();
13415 std::vector<bool>::const_iterator i = v.begin();
13416 for (; line != endl; ++line, ++i)
13417 if (*i == true)
13418 line->set_user_flag();
13419 else
13420 line->clear_user_flag();
13421
13422 Assert(i == v.end(), ExcInternalError());
13423}
13424
13425#endif
13426
13427namespace
13428{
13429 template <typename Iterator>
13430 bool
13431 get_user_flag(const Iterator &i)
13432 {
13433 return i->user_flag_set();
13434 }
13435
13436
13437
13438 template <int structdim, int dim, int spacedim>
13439 bool
13441 {
13443 return false;
13444 }
13445
13446
13447
13448 template <typename Iterator>
13449 void
13450 set_user_flag(const Iterator &i)
13451 {
13452 i->set_user_flag();
13453 }
13454
13455
13456
13457 template <int structdim, int dim, int spacedim>
13458 void
13460 {
13462 }
13463
13464
13465
13466 template <typename Iterator>
13467 void
13468 clear_user_flag(const Iterator &i)
13469 {
13470 i->clear_user_flag();
13471 }
13472
13473
13474
13475 template <int structdim, int dim, int spacedim>
13476 void
13477 clear_user_flag(
13479 {
13481 }
13482} // namespace
13483
13484#ifndef DOXYGEN
13485
13486template <int dim, int spacedim>
13489 std::vector<bool> &v) const
13490{
13491 v.resize(n_quads(), false);
13492
13493 if (dim >= 2)
13494 {
13495 std::vector<bool>::iterator i = v.begin();
13496 quad_iterator quad = begin_quad(), endq = end_quad();
13497 for (; quad != endq; ++quad, ++i)
13498 *i = get_user_flag(quad);
13499
13500 Assert(i == v.end(), ExcInternalError());
13501 }
13502}
13503
13504
13505
13506template <int dim, int spacedim>
13508void Triangulation<dim, spacedim>::save_user_flags_quad(std::ostream &out) const
13509{
13510 std::vector<bool> v;
13511 save_user_flags_quad(v);
13512 write_bool_vector(mn_tria_quad_user_flags_begin,
13513 v,
13515 out);
13516}
13517
13518
13519
13520template <int dim, int spacedim>
13523{
13524 std::vector<bool> v;
13525 read_bool_vector(mn_tria_quad_user_flags_begin,
13526 v,
13528 in);
13529 load_user_flags_quad(v);
13530}
13531
13532
13533
13534template <int dim, int spacedim>
13537 const std::vector<bool> &v)
13538{
13539 Assert(v.size() == n_quads(), ExcGridReadError());
13540
13541 if (dim >= 2)
13542 {
13543 quad_iterator quad = begin_quad(), endq = end_quad();
13544 std::vector<bool>::const_iterator i = v.begin();
13545 for (; quad != endq; ++quad, ++i)
13546 if (*i == true)
13547 set_user_flag(quad);
13548 else
13549 clear_user_flag(quad);
13550
13551 Assert(i == v.end(), ExcInternalError());
13552 }
13553}
13554
13555
13556
13557template <int dim, int spacedim>
13560 std::vector<bool> &v) const
13561{
13562 v.resize(n_hexs(), false);
13563
13564 if (dim >= 3)
13565 {
13566 std::vector<bool>::iterator i = v.begin();
13567 hex_iterator hex = begin_hex(), endh = end_hex();
13568 for (; hex != endh; ++hex, ++i)
13569 *i = get_user_flag(hex);
13570
13571 Assert(i == v.end(), ExcInternalError());
13572 }
13573}
13574
13575
13576
13577template <int dim, int spacedim>
13579void Triangulation<dim, spacedim>::save_user_flags_hex(std::ostream &out) const
13580{
13581 std::vector<bool> v;
13582 save_user_flags_hex(v);
13583 write_bool_vector(mn_tria_hex_user_flags_begin,
13584 v,
13586 out);
13587}
13588
13589
13590
13591template <int dim, int spacedim>
13594{
13595 std::vector<bool> v;
13596 read_bool_vector(mn_tria_hex_user_flags_begin,
13597 v,
13599 in);
13600 load_user_flags_hex(v);
13601}
13602
13603
13604
13605template <int dim, int spacedim>
13608 const std::vector<bool> &v)
13609{
13610 Assert(v.size() == n_hexs(), ExcGridReadError());
13611
13612 if (dim >= 3)
13613 {
13614 hex_iterator hex = begin_hex(), endh = end_hex();
13615 std::vector<bool>::const_iterator i = v.begin();
13616 for (; hex != endh; ++hex, ++i)
13617 if (*i == true)
13618 set_user_flag(hex);
13619 else
13620 clear_user_flag(hex);
13621
13622 Assert(i == v.end(), ExcInternalError());
13623 }
13624}
13625
13626
13627
13628template <int dim, int spacedim>
13631 std::vector<unsigned int> &v) const
13632{
13633 // clear vector and append all the
13634 // stuff later on
13635 v.clear();
13636
13637 std::vector<unsigned int> tmp;
13638
13639 save_user_indices_line(tmp);
13640 v.insert(v.end(), tmp.begin(), tmp.end());
13641
13642 if (dim >= 2)
13643 {
13644 save_user_indices_quad(tmp);
13645 v.insert(v.end(), tmp.begin(), tmp.end());
13646 }
13647
13648 if (dim >= 3)
13649 {
13650 save_user_indices_hex(tmp);
13651 v.insert(v.end(), tmp.begin(), tmp.end());
13652 }
13653
13654 if (dim >= 4)
13656}
13657
13658
13659
13660template <int dim, int spacedim>
13663 const std::vector<unsigned int> &v)
13664{
13665 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
13666 std::vector<unsigned int> tmp;
13667
13668 // first extract the indices
13669 // belonging to lines
13670 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
13671 // and set the lines
13672 load_user_indices_line(tmp);
13673
13674 if (dim >= 2)
13675 {
13676 tmp.clear();
13677 tmp.insert(tmp.end(),
13678 v.begin() + n_lines(),
13679 v.begin() + n_lines() + n_quads());
13680 load_user_indices_quad(tmp);
13681 }
13682
13683 if (dim >= 3)
13684 {
13685 tmp.clear();
13686 tmp.insert(tmp.end(),
13687 v.begin() + n_lines() + n_quads(),
13688 v.begin() + n_lines() + n_quads() + n_hexs());
13689 load_user_indices_hex(tmp);
13690 }
13691
13692 if (dim >= 4)
13694}
13695
13696
13697
13698template <int dim, int spacedim>
13700void Triangulation<dim, spacedim>::save(const std::string &file_basename) const
13701{
13702 // Save triangulation information.
13703 std::ofstream ofs(file_basename + "_triangulation.data");
13704 boost::archive::text_oarchive oa(ofs, boost::archive::no_header);
13705 save(oa, 0);
13706
13707 // Save attached data.
13708 {
13709 std::ofstream ifs(file_basename + ".info");
13710 ifs
13711 << "version nproc n_attached_fixed_size_objs n_attached_variable_size_objs n_active_cells"
13712 << std::endl
13714 << " " << 1 << " " << this->cell_attached_data.pack_callbacks_fixed.size()
13715 << " " << this->cell_attached_data.pack_callbacks_variable.size() << " "
13716 << this->n_global_active_cells() << std::endl;
13717 }
13718
13719 this->save_attached_data(0, this->n_global_active_cells(), file_basename);
13720}
13721
13722
13723
13724template <int dim, int spacedim>
13726void Triangulation<dim, spacedim>::load(const std::string &file_basename)
13727{
13728 // Load triangulation information.
13729 std::ifstream ifs(file_basename + "_triangulation.data");
13730 AssertThrow(ifs.fail() == false, ExcIO());
13731
13732 boost::archive::text_iarchive ia(ifs, boost::archive::no_header);
13733 load(ia, 0);
13734
13735 // Load attached data.
13736 unsigned int version, numcpus, attached_count_fixed, attached_count_variable,
13737 n_global_active_cells;
13738 {
13739 std::ifstream ifs(std::string(file_basename) + ".info");
13740 AssertThrow(ifs.fail() == false, ExcIO());
13741 std::string firstline;
13742 getline(ifs, firstline);
13743 ifs >> version >> numcpus >> attached_count_fixed >>
13744 attached_count_variable >> n_global_active_cells;
13745 }
13746
13747 AssertThrow(numcpus == 1,
13748 ExcMessage("Incompatible number of CPUs found in .info file."));
13749
13750 const auto expected_version =
13752 spacedim>::version_number;
13753 AssertThrow(version == expected_version,
13754 ExcMessage(
13755 "The information saved in the file you are trying "
13756 "to read the triangulation from was written with an "
13757 "incompatible file format version and cannot be read."));
13758 Assert(this->n_global_active_cells() == n_global_active_cells,
13759 ExcMessage("The number of cells of the triangulation differs "
13760 "from the number of cells written into the .info file."));
13761
13762 // Clear all of the callback data, as explained in the documentation of
13763 // register_data_attach().
13764 this->cell_attached_data.n_attached_data_sets = 0;
13765 this->cell_attached_data.n_attached_deserialize =
13766 attached_count_fixed + attached_count_variable;
13767
13768 this->load_attached_data(0,
13769 this->n_global_active_cells(),
13770 this->n_active_cells(),
13771 file_basename,
13772 attached_count_fixed,
13773 attached_count_variable);
13774
13775 this->update_cell_relations();
13776}
13777
13778#endif
13779namespace
13780{
13781 template <typename Iterator>
13782 unsigned int
13783 get_user_index(const Iterator &i)
13784 {
13785 return i->user_index();
13786 }
13787
13788
13789
13790 template <int structdim, int dim, int spacedim>
13791 unsigned int
13792 get_user_index(
13794 {
13797 }
13798
13799
13800
13801 template <typename Iterator>
13802 void
13803 set_user_index(const Iterator &i, const unsigned int x)
13804 {
13805 i->set_user_index(x);
13806 }
13807
13808
13809
13810 template <int structdim, int dim, int spacedim>
13811 void
13812 set_user_index(
13814 const unsigned int)
13815 {
13817 }
13818} // namespace
13819
13820#ifndef DOXYGEN
13821
13822template <int dim, int spacedim>
13825 std::vector<unsigned int> &v) const
13826{
13827 v.resize(n_lines(), 0);
13828 std::vector<unsigned int>::iterator i = v.begin();
13829 line_iterator line = begin_line(), endl = end_line();
13830 for (; line != endl; ++line, ++i)
13831 *i = line->user_index();
13832}
13833
13834
13835
13836template <int dim, int spacedim>
13839 const std::vector<unsigned int> &v)
13840{
13841 Assert(v.size() == n_lines(), ExcGridReadError());
13842
13843 line_iterator line = begin_line(), endl = end_line();
13844 std::vector<unsigned int>::const_iterator i = v.begin();
13845 for (; line != endl; ++line, ++i)
13846 line->set_user_index(*i);
13847}
13848
13849
13850template <int dim, int spacedim>
13853 std::vector<unsigned int> &v) const
13854{
13855 v.resize(n_quads(), 0);
13856
13857 if (dim >= 2)
13858 {
13859 std::vector<unsigned int>::iterator i = v.begin();
13860 quad_iterator quad = begin_quad(), endq = end_quad();
13861 for (; quad != endq; ++quad, ++i)
13862 *i = get_user_index(quad);
13863 }
13864}
13865
13866
13867
13868template <int dim, int spacedim>
13871 const std::vector<unsigned int> &v)
13872{
13873 Assert(v.size() == n_quads(), ExcGridReadError());
13874
13875 if (dim >= 2)
13876 {
13877 quad_iterator quad = begin_quad(), endq = end_quad();
13878 std::vector<unsigned int>::const_iterator i = v.begin();
13879 for (; quad != endq; ++quad, ++i)
13880 set_user_index(quad, *i);
13881 }
13882}
13883
13884
13885template <int dim, int spacedim>
13888 std::vector<unsigned int> &v) const
13889{
13890 v.resize(n_hexs(), 0);
13891
13892 if (dim >= 3)
13893 {
13894 std::vector<unsigned int>::iterator i = v.begin();
13895 hex_iterator hex = begin_hex(), endh = end_hex();
13896 for (; hex != endh; ++hex, ++i)
13897 *i = get_user_index(hex);
13898 }
13899}
13900
13901
13902
13903template <int dim, int spacedim>
13906 const std::vector<unsigned int> &v)
13907{
13908 Assert(v.size() == n_hexs(), ExcGridReadError());
13909
13910 if (dim >= 3)
13911 {
13912 hex_iterator hex = begin_hex(), endh = end_hex();
13913 std::vector<unsigned int>::const_iterator i = v.begin();
13914 for (; hex != endh; ++hex, ++i)
13915 set_user_index(hex, *i);
13916 }
13917}
13918
13919#endif
13920
13921
13922//---------------- user pointers ----------------------------------------//
13923
13924
13925namespace
13926{
13927 template <typename Iterator>
13928 void *
13929 get_user_pointer(const Iterator &i)
13930 {
13931 return i->user_pointer();
13932 }
13933
13934
13935
13936 template <int structdim, int dim, int spacedim>
13937 void *
13938 get_user_pointer(
13940 {
13942 return nullptr;
13943 }
13944
13945
13946
13947 template <typename Iterator>
13948 void
13949 set_user_pointer(const Iterator &i, void *x)
13950 {
13951 i->set_user_pointer(x);
13952 }
13953
13954
13955
13956 template <int structdim, int dim, int spacedim>
13957 void
13958 set_user_pointer(
13960 void *)
13961 {
13963 }
13964} // namespace
13965
13966#ifndef DOXYGEN
13967
13968template <int dim, int spacedim>
13971 std::vector<void *> &v) const
13972{
13973 // clear vector and append all the
13974 // stuff later on
13975 v.clear();
13976
13977 std::vector<void *> tmp;
13978
13979 save_user_pointers_line(tmp);
13980 v.insert(v.end(), tmp.begin(), tmp.end());
13981
13982 if (dim >= 2)
13983 {
13984 save_user_pointers_quad(tmp);
13985 v.insert(v.end(), tmp.begin(), tmp.end());
13986 }
13987
13988 if (dim >= 3)
13989 {
13990 save_user_pointers_hex(tmp);
13991 v.insert(v.end(), tmp.begin(), tmp.end());
13992 }
13993
13994 if (dim >= 4)
13996}
13997
13998
13999
14000template <int dim, int spacedim>
14003 const std::vector<void *> &v)
14004{
14005 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
14006 std::vector<void *> tmp;
14007
14008 // first extract the pointers
14009 // belonging to lines
14010 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
14011 // and set the lines
14012 load_user_pointers_line(tmp);
14013
14014 if (dim >= 2)
14015 {
14016 tmp.clear();
14017 tmp.insert(tmp.end(),
14018 v.begin() + n_lines(),
14019 v.begin() + n_lines() + n_quads());
14020 load_user_pointers_quad(tmp);
14021 }
14022
14023 if (dim >= 3)
14024 {
14025 tmp.clear();
14026 tmp.insert(tmp.end(),
14027 v.begin() + n_lines() + n_quads(),
14028 v.begin() + n_lines() + n_quads() + n_hexs());
14029 load_user_pointers_hex(tmp);
14030 }
14031
14032 if (dim >= 4)
14034}
14035
14036
14037
14038template <int dim, int spacedim>
14041 std::vector<void *> &v) const
14042{
14043 v.resize(n_lines(), nullptr);
14044 std::vector<void *>::iterator i = v.begin();
14045 line_iterator line = begin_line(), endl = end_line();
14046 for (; line != endl; ++line, ++i)
14047 *i = line->user_pointer();
14048}
14049
14050
14051
14052template <int dim, int spacedim>
14055 const std::vector<void *> &v)
14056{
14057 Assert(v.size() == n_lines(), ExcGridReadError());
14058
14059 line_iterator line = begin_line(), endl = end_line();
14060 std::vector<void *>::const_iterator i = v.begin();
14061 for (; line != endl; ++line, ++i)
14062 line->set_user_pointer(*i);
14063}
14064
14065
14066
14067template <int dim, int spacedim>
14070 std::vector<void *> &v) const
14071{
14072 v.resize(n_quads(), nullptr);
14073
14074 if (dim >= 2)
14075 {
14076 std::vector<void *>::iterator i = v.begin();
14077 quad_iterator quad = begin_quad(), endq = end_quad();
14078 for (; quad != endq; ++quad, ++i)
14079 *i = get_user_pointer(quad);
14080 }
14081}
14082
14083
14084
14085template <int dim, int spacedim>
14088 const std::vector<void *> &v)
14089{
14090 Assert(v.size() == n_quads(), ExcGridReadError());
14091
14092 if (dim >= 2)
14093 {
14094 quad_iterator quad = begin_quad(), endq = end_quad();
14095 std::vector<void *>::const_iterator i = v.begin();
14096 for (; quad != endq; ++quad, ++i)
14097 set_user_pointer(quad, *i);
14098 }
14099}
14100
14101
14102template <int dim, int spacedim>
14105 std::vector<void *> &v) const
14106{
14107 v.resize(n_hexs(), nullptr);
14108
14109 if (dim >= 3)
14110 {
14111 std::vector<void *>::iterator i = v.begin();
14112 hex_iterator hex = begin_hex(), endh = end_hex();
14113 for (; hex != endh; ++hex, ++i)
14114 *i = get_user_pointer(hex);
14115 }
14116}
14117
14118
14119
14120template <int dim, int spacedim>
14123 const std::vector<void *> &v)
14124{
14125 Assert(v.size() == n_hexs(), ExcGridReadError());
14126
14127 if (dim >= 3)
14128 {
14129 hex_iterator hex = begin_hex(), endh = end_hex();
14130 std::vector<void *>::const_iterator i = v.begin();
14131 for (; hex != endh; ++hex, ++i)
14132 set_user_pointer(hex, *i);
14133 }
14134}
14135
14136#endif
14137
14138/*------------------------ Cell iterator functions ------------------------*/
14139
14140#ifndef DOXYGEN
14141
14142template <int dim, int spacedim>
14145 Triangulation<dim, spacedim>::begin_raw(const unsigned int level) const
14146{
14147 switch (dim)
14148 {
14149 case 1:
14150 return begin_raw_line(level);
14151 case 2:
14152 return begin_raw_quad(level);
14153 case 3:
14154 return begin_raw_hex(level);
14155 default:
14157 return raw_cell_iterator();
14158 }
14159}
14160
14161
14162
14163template <int dim, int spacedim>
14166 Triangulation<dim, spacedim>::begin(const unsigned int level) const
14167{
14168 switch (dim)
14169 {
14170 case 1:
14171 return begin_line(level);
14172 case 2:
14173 return begin_quad(level);
14174 case 3:
14175 return begin_hex(level);
14176 default:
14177 Assert(false, ExcImpossibleInDim(dim));
14178 return cell_iterator();
14179 }
14180}
14181
14182
14183
14184template <int dim, int spacedim>
14187 Triangulation<dim, spacedim>::begin_active(const unsigned int level) const
14188{
14189 switch (dim)
14190 {
14191 case 1:
14192 return begin_active_line(level);
14193 case 2:
14194 return begin_active_quad(level);
14195 case 3:
14196 return begin_active_hex(level);
14197 default:
14199 return active_cell_iterator();
14200 }
14201}
14202
14203
14204
14205template <int dim, int spacedim>
14209{
14210 const unsigned int level = levels.size() - 1;
14211 if (levels[level]->cells.n_objects() == 0)
14212 return end(level);
14213
14214 // find the last raw iterator on
14215 // this level
14216 raw_cell_iterator ri(const_cast<Triangulation<dim, spacedim> *>(this),
14217 level,
14218 levels[level]->cells.n_objects() - 1);
14219
14220 // then move to the last used one
14221 if (ri->used() == true)
14222 return ri;
14223 while ((--ri).state() == IteratorState::valid)
14224 if (ri->used() == true)
14225 return ri;
14226 return ri;
14227}
14228
14229
14230
14231template <int dim, int spacedim>
14235{
14236 // get the last used cell
14237 cell_iterator cell = last();
14238
14239 if (cell != end())
14240 {
14241 // then move to the last active one
14242 if (cell->is_active() == true)
14243 return cell;
14244 while ((--cell).state() == IteratorState::valid)
14245 if (cell->is_active() == true)
14246 return cell;
14247 }
14248 return cell;
14249}
14250
14251
14252
14253template <int dim, int spacedim>
14257 const CellId &cell_id) const
14258{
14259 Assert(
14260 this->contains_cell(cell_id),
14261 ExcMessage(
14262 "CellId is invalid for this triangulation.\n"
14263 "Either the provided CellId does not correspond to a cell in this "
14264 "triangulation object, or, in case you are using a parallel "
14265 "triangulation, may correspond to an artificial cell that is less "
14266 "refined on this processor. In the case of "
14267 "parallel::fullydistributed::Triangulation, the corresponding coarse "
14268 "cell might not be accessible by the current process."));
14269
14270 cell_iterator cell(
14271 this, 0, coarse_cell_id_to_coarse_cell_index(cell_id.get_coarse_cell_id()));
14272
14273 for (const auto &child_index : cell_id.get_child_indices())
14274 cell = cell->child(static_cast<unsigned int>(child_index));
14275
14276 return cell;
14277}
14278
14279
14280
14281template <int dim, int spacedim>
14283bool Triangulation<dim, spacedim>::contains_cell(const CellId &cell_id) const
14284{
14285 const auto coarse_cell_index =
14286 coarse_cell_id_to_coarse_cell_index(cell_id.get_coarse_cell_id());
14287
14288 if (coarse_cell_index == numbers::invalid_unsigned_int)
14289 return false;
14290
14291 cell_iterator cell(this, 0, coarse_cell_index);
14292
14293 for (const auto &child_index : cell_id.get_child_indices())
14294 {
14295 if (cell->has_children() == false)
14296 return false;
14297 cell = cell->child(static_cast<unsigned int>(child_index));
14298 }
14299
14300 return true;
14301}
14302
14303
14304
14305template <int dim, int spacedim>
14309{
14310 return cell_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14311 -1,
14312 -1);
14313}
14314
14315
14316
14317template <int dim, int spacedim>
14320 Triangulation<dim, spacedim>::end_raw(const unsigned int level) const
14321{
14322 // This function may be called on parallel triangulations on levels
14323 // that exist globally, but not on the local portion of the
14324 // triangulation. In that case, just return the end iterator.
14325 //
14326 // We need to use levels.size() instead of n_levels() because the
14327 // latter function uses the cache, but we need to be able to call
14328 // this function at a time when the cache is not currently up to
14329 // date.
14330 if (level >= levels.size())
14331 {
14332 Assert(level < n_global_levels(),
14333 ExcInvalidLevel(level, n_global_levels()));
14334 return end();
14335 }
14336
14337 // Query whether the given level is valid for the local portion of the
14338 // triangulation.
14339 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14340 if (level < levels.size() - 1)
14341 return begin_raw(level + 1);
14342 else
14343 return end();
14344}
14345
14346
14347template <int dim, int spacedim>
14350 Triangulation<dim, spacedim>::end(const unsigned int level) const
14351{
14352 // This function may be called on parallel triangulations on levels
14353 // that exist globally, but not on the local portion of the
14354 // triangulation. In that case, just return the end iterator.
14355 //
14356 // We need to use levels.size() instead of n_levels() because the
14357 // latter function uses the cache, but we need to be able to call
14358 // this function at a time when the cache is not currently up to
14359 // date.
14360 if (level >= levels.size())
14361 {
14362 Assert(level < n_global_levels(),
14363 ExcInvalidLevel(level, n_global_levels()));
14364 return end();
14365 }
14366
14367 // Query whether the given level is valid for the local portion of the
14368 // triangulation.
14369 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14370 if (level < levels.size() - 1)
14371 return begin(level + 1);
14372 else
14373 return end();
14374}
14375
14376
14377template <int dim, int spacedim>
14380 Triangulation<dim, spacedim>::end_active(const unsigned int level) const
14381{
14382 // This function may be called on parallel triangulations on levels
14383 // that exist globally, but not on the local portion of the
14384 // triangulation. In that case, just return the end iterator.
14385 //
14386 // We need to use levels.size() instead of n_levels() because the
14387 // latter function uses the cache, but we need to be able to call
14388 // this function at a time when the cache is not currently up to
14389 // date.
14390 if (level >= levels.size())
14391 {
14392 Assert(level < n_global_levels(),
14393 ExcInvalidLevel(level, n_global_levels()));
14394 return end();
14395 }
14396
14397 // Query whether the given level is valid for the local portion of the
14398 // triangulation.
14399 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14400 return (level >= levels.size() - 1 ? active_cell_iterator(end()) :
14401 begin_active(level + 1));
14402}
14403
14404
14405
14406template <int dim, int spacedim>
14410 const
14411{
14413 begin(), end());
14414}
14415
14416
14417template <int dim, int spacedim>
14420 active_cell_iterator> Triangulation<dim, spacedim>::
14422{
14423 return IteratorRange<
14425 end());
14426}
14427
14428
14429
14430template <int dim, int spacedim>
14433 cell_iterator> Triangulation<dim, spacedim>::
14434 cell_iterators_on_level(const unsigned int level) const
14435{
14437 begin(level), end(level));
14438}
14439
14440
14441
14442template <int dim, int spacedim>
14445 active_cell_iterator> Triangulation<dim, spacedim>::
14446 active_cell_iterators_on_level(const unsigned int level) const
14447{
14448 return IteratorRange<
14450 begin_active(level), end_active(level));
14451}
14452#endif
14453
14454/*------------------------ Face iterator functions ------------------------*/
14455
14456#ifndef DOXYGEN
14457
14458template <int dim, int spacedim>
14462{
14463 switch (dim)
14464 {
14465 case 1:
14466 Assert(false, ExcImpossibleInDim(1));
14467 return raw_face_iterator();
14468 case 2:
14469 return begin_line();
14470 case 3:
14471 return begin_quad();
14472 default:
14474 return face_iterator();
14475 }
14476}
14477
14478
14479
14480template <int dim, int spacedim>
14484{
14485 switch (dim)
14486 {
14487 case 1:
14488 Assert(false, ExcImpossibleInDim(1));
14489 return raw_face_iterator();
14490 case 2:
14491 return begin_active_line();
14492 case 3:
14493 return begin_active_quad();
14494 default:
14496 return active_face_iterator();
14497 }
14498}
14499
14500
14501
14502template <int dim, int spacedim>
14506{
14507 switch (dim)
14508 {
14509 case 1:
14510 Assert(false, ExcImpossibleInDim(1));
14511 return raw_face_iterator();
14512 case 2:
14513 return end_line();
14514 case 3:
14515 return end_quad();
14516 default:
14518 return raw_face_iterator();
14519 }
14520}
14521
14522
14523
14524template <int dim, int spacedim>
14527 active_face_iterator> Triangulation<dim, spacedim>::
14529{
14530 return IteratorRange<
14532 begin_active_face(), end_face());
14533}
14534
14535/*------------------------ Vertex iterator functions ------------------------*/
14536
14537
14538template <int dim, int spacedim>
14542{
14543 vertex_iterator i =
14544 raw_vertex_iterator(const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
14545 if (i.state() != IteratorState::valid)
14546 return i;
14547 // This loop will end because every triangulation has used vertices.
14548 while (i->used() == false)
14549 if ((++i).state() != IteratorState::valid)
14550 return i;
14551 return i;
14552}
14553
14554
14555
14556template <int dim, int spacedim>
14560{
14561 // every vertex is active
14562 return begin_vertex();
14563}
14564
14565
14566
14567template <int dim, int spacedim>
14571{
14572 return raw_vertex_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14573 -1,
14575}
14576
14577#endif
14578
14579
14580/*------------------------ Line iterator functions ------------------------*/
14581
14582#ifndef DOXYGEN
14583
14584template <int dim, int spacedim>
14587 Triangulation<dim, spacedim>::begin_raw_line(const unsigned int level) const
14588{
14589 // This function may be called on parallel triangulations on levels
14590 // that exist globally, but not on the local portion of the
14591 // triangulation. In that case, just return the end iterator.
14592 //
14593 // We need to use levels.size() instead of n_levels() because the
14594 // latter function uses the cache, but we need to be able to call
14595 // this function at a time when the cache is not currently up to
14596 // date.
14597 if (level >= levels.size())
14598 {
14599 Assert(level < n_global_levels(),
14600 ExcInvalidLevel(level, n_global_levels()));
14601 return end_line();
14602 }
14603
14604 switch (dim)
14605 {
14606 case 1:
14607 // Query whether the given level is valid for the local portion of the
14608 // triangulation.
14609 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14610
14611 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
14612 return end_line();
14613
14614 return raw_line_iterator(
14615 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
14616
14617 default:
14618 Assert(level == 0, ExcFacesHaveNoLevel());
14619 return raw_line_iterator(
14620 const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
14621 }
14622}
14623
14624
14625template <int dim, int spacedim>
14628 Triangulation<dim, spacedim>::begin_line(const unsigned int level) const
14629{
14630 // level is checked in begin_raw
14631 raw_line_iterator ri = begin_raw_line(level);
14632 if (ri.state() != IteratorState::valid)
14633 return ri;
14634 while (ri->used() == false)
14635 if ((++ri).state() != IteratorState::valid)
14636 return ri;
14637 return ri;
14638}
14639
14640
14641
14642template <int dim, int spacedim>
14646 const unsigned int level) const
14647{
14648 // level is checked in begin_raw
14649 line_iterator i = begin_line(level);
14650 if (i.state() != IteratorState::valid)
14651 return i;
14652 while (i->has_children())
14653 if ((++i).state() != IteratorState::valid)
14654 return i;
14655 return i;
14656}
14657
14658
14659
14660template <int dim, int spacedim>
14664{
14665 return raw_line_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14666 -1,
14667 -1);
14668}
14669
14670#endif
14671
14672/*------------------------ Quad iterator functions ------------------------*/
14673
14674#ifndef DOXYGEN
14675
14676template <int dim, int spacedim>
14679 Triangulation<dim, spacedim>::begin_raw_quad(const unsigned int level) const
14680{
14681 // This function may be called on parallel triangulations on levels
14682 // that exist globally, but not on the local portion of the
14683 // triangulation. In that case, just return the end iterator.
14684 //
14685 // We need to use levels.size() instead of n_levels() because the
14686 // latter function uses the cache, but we need to be able to call
14687 // this function at a time when the cache is not currently up to
14688 // date.
14689 if (level >= levels.size())
14690 {
14691 Assert(level < n_global_levels(),
14692 ExcInvalidLevel(level, n_global_levels()));
14693 return end_quad();
14694 }
14695
14696 switch (dim)
14697 {
14698 case 1:
14699 Assert(false, ExcImpossibleInDim(1));
14700 return raw_hex_iterator();
14701 case 2:
14702 {
14703 // Query whether the given level is valid for the local portion of the
14704 // triangulation.
14705 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14706
14707 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
14708 return end_quad();
14709
14710 return raw_quad_iterator(
14711 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
14712 }
14713
14714 case 3:
14715 {
14716 Assert(level == 0, ExcFacesHaveNoLevel());
14717
14718 return raw_quad_iterator(
14719 const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
14720 }
14721
14722
14723 default:
14725 return raw_hex_iterator();
14726 }
14727}
14728
14729
14730
14731template <int dim, int spacedim>
14734 Triangulation<dim, spacedim>::begin_quad(const unsigned int level) const
14735{
14736 // level is checked in begin_raw
14737 raw_quad_iterator ri = begin_raw_quad(level);
14738 if (ri.state() != IteratorState::valid)
14739 return ri;
14740 while (ri->used() == false)
14741 if ((++ri).state() != IteratorState::valid)
14742 return ri;
14743 return ri;
14744}
14745
14746
14747
14748template <int dim, int spacedim>
14752 const unsigned int level) const
14753{
14754 // level is checked in begin_raw
14755 quad_iterator i = begin_quad(level);
14756 if (i.state() != IteratorState::valid)
14757 return i;
14758 while (i->has_children())
14759 if ((++i).state() != IteratorState::valid)
14760 return i;
14761 return i;
14762}
14763
14764
14765
14766template <int dim, int spacedim>
14770{
14771 return raw_quad_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14772 -1,
14773 -1);
14774}
14775
14776#endif
14777
14778/*------------------------ Hex iterator functions ------------------------*/
14779
14780#ifndef DOXYGEN
14781
14782template <int dim, int spacedim>
14785 Triangulation<dim, spacedim>::begin_raw_hex(const unsigned int level) const
14786{
14787 // This function may be called on parallel triangulations on levels
14788 // that exist globally, but not on the local portion of the
14789 // triangulation. In that case, just return the end iterator.
14790 //
14791 // We need to use levels.size() instead of n_levels() because the
14792 // latter function uses the cache, but we need to be able to call
14793 // this function at a time when the cache is not currently up to
14794 // date.
14795 if (level >= levels.size())
14796 {
14797 Assert(level < n_global_levels(),
14798 ExcInvalidLevel(level, n_global_levels()));
14799 return end_hex();
14800 }
14801
14802 switch (dim)
14803 {
14804 case 1:
14805 case 2:
14806 Assert(false, ExcImpossibleInDim(1));
14807 return raw_hex_iterator();
14808 case 3:
14809 {
14810 // Query whether the given level is valid for the local portion of the
14811 // triangulation.
14812 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14813
14814 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
14815 return end_hex();
14816
14817 return raw_hex_iterator(
14818 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
14819 }
14820
14821 default:
14823 return raw_hex_iterator();
14824 }
14825}
14826
14827
14828
14829template <int dim, int spacedim>
14832 Triangulation<dim, spacedim>::begin_hex(const unsigned int level) const
14833{
14834 // level is checked in begin_raw
14835 raw_hex_iterator ri = begin_raw_hex(level);
14836 if (ri.state() != IteratorState::valid)
14837 return ri;
14838 while (ri->used() == false)
14839 if ((++ri).state() != IteratorState::valid)
14840 return ri;
14841 return ri;
14842}
14843
14844
14845
14846template <int dim, int spacedim>
14850{
14851 // level is checked in begin_raw
14852 hex_iterator i = begin_hex(level);
14853 if (i.state() != IteratorState::valid)
14854 return i;
14855 while (i->has_children())
14856 if ((++i).state() != IteratorState::valid)
14857 return i;
14858 return i;
14859}
14860
14861
14862
14863template <int dim, int spacedim>
14867{
14868 return raw_hex_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14869 -1,
14870 -1);
14871}
14872
14873#endif
14874
14875// -------------------------------- number of cells etc ---------------
14876
14877
14878namespace internal
14879{
14880 namespace TriangulationImplementation
14881 {
14882 inline unsigned int
14884 {
14885 return c.n_lines;
14886 }
14887
14888
14889 inline unsigned int
14892 {
14893 return c.n_active_lines;
14894 }
14895
14896
14897 inline unsigned int
14899 {
14900 return c.n_quads;
14901 }
14902
14903
14904 inline unsigned int
14907 {
14908 return c.n_active_quads;
14909 }
14910
14911
14912 inline unsigned int
14914 {
14915 return c.n_hexes;
14916 }
14917
14918
14919 inline unsigned int
14922 {
14923 return c.n_active_hexes;
14924 }
14925 } // namespace TriangulationImplementation
14926} // namespace internal
14927
14928#ifndef DOXYGEN
14929
14930template <int dim, int spacedim>
14932unsigned int Triangulation<dim, spacedim>::n_cells() const
14933{
14935}
14936
14937
14938template <int dim, int spacedim>
14941{
14943}
14944
14945template <int dim, int spacedim>
14949{
14950 return n_active_cells();
14951}
14952
14953template <int dim, int spacedim>
14957{
14958 return n_cells(0);
14959}
14960
14961template <int dim, int spacedim>
14963unsigned int Triangulation<dim, spacedim>::n_faces() const
14964{
14965 switch (dim)
14966 {
14967 case 1:
14968 return n_used_vertices();
14969 case 2:
14970 return n_lines();
14971 case 3:
14972 return n_quads();
14973 default:
14975 }
14976 return 0;
14977}
14978
14979
14980template <int dim, int spacedim>
14983{
14984 switch (dim)
14985 {
14986 case 1:
14987 return n_vertices();
14988 case 2:
14989 return n_raw_lines();
14990 case 3:
14991 return n_raw_quads();
14992 default:
14994 }
14995 return 0;
14996}
14997
14998
14999template <int dim, int spacedim>
15002{
15003 switch (dim)
15004 {
15005 case 1:
15006 return n_used_vertices();
15007 case 2:
15008 return n_active_lines();
15009 case 3:
15010 return n_active_quads();
15011 default:
15013 }
15014 return 0;
15015}
15016
15017
15018template <int dim, int spacedim>
15021 const unsigned int level) const
15022{
15023 switch (dim)
15024 {
15025 case 1:
15026 return n_raw_lines(level);
15027 case 2:
15028 return n_raw_quads(level);
15029 case 3:
15030 return n_raw_hexs(level);
15031 default:
15033 }
15034 return 0;
15035}
15036
15037
15038
15039template <int dim, int spacedim>
15042 const unsigned int level) const
15043{
15044 switch (dim)
15045 {
15046 case 1:
15047 return n_lines(level);
15048 case 2:
15049 return n_quads(level);
15050 case 3:
15051 return n_hexs(level);
15052 default:
15054 }
15055 return 0;
15056}
15057
15058
15059
15060template <int dim, int spacedim>
15063 const unsigned int level) const
15064{
15065 switch (dim)
15066 {
15067 case 1:
15068 return n_active_lines(level);
15069 case 2:
15070 return n_active_quads(level);
15071 case 3:
15072 return n_active_hexs(level);
15073 default:
15075 }
15076 return 0;
15077}
15078
15079
15080template <int dim, int spacedim>
15083{
15084 if (anisotropic_refinement == false)
15085 {
15086 for (unsigned int lvl = 0; lvl < n_global_levels() - 1; ++lvl)
15087 if (n_active_cells(lvl) != 0)
15088 return true;
15089 }
15090 else
15091 {
15092 for (const auto &cell : active_cell_iterators())
15093 for (const auto &i : cell->face_indices())
15094 if (cell->face(i)->has_children())
15095 return true;
15096 }
15097 return false;
15098}
15099
15100
15101template <int dim, int spacedim>
15103unsigned int Triangulation<dim, spacedim>::n_lines() const
15104{
15105 return number_cache.n_lines;
15106}
15107
15108
15109
15110template <int dim, int spacedim>
15113 const unsigned int level) const
15114{
15115 if (dim == 1)
15116 {
15117 AssertIndexRange(level, n_levels());
15118 return levels[level]->cells.n_objects();
15119 }
15120
15121 Assert(false, ExcFacesHaveNoLevel());
15122 return 0;
15123}
15124
15125
15126template <int dim, int spacedim>
15129{
15130 if (dim == 1)
15131 {
15133 return 0;
15134 }
15135
15136 return faces->lines.n_objects();
15137}
15138
15139
15140template <int dim, int spacedim>
15143 const unsigned int level) const
15144{
15145 AssertIndexRange(level, number_cache.n_lines_level.size());
15146 Assert(dim == 1, ExcFacesHaveNoLevel());
15147 return number_cache.n_lines_level[level];
15148}
15149
15150
15151template <int dim, int spacedim>
15154{
15155 return number_cache.n_active_lines;
15156}
15157
15158
15159template <int dim, int spacedim>
15162 const unsigned int level) const
15163{
15164 AssertIndexRange(level, number_cache.n_lines_level.size());
15165 Assert(dim == 1, ExcFacesHaveNoLevel());
15166
15167 return number_cache.n_active_lines_level[level];
15168}
15169#endif
15170
15171template <>
15172unsigned int
15174{
15175 return 0;
15176}
15177
15178
15179template <>
15180unsigned int
15181Triangulation<1, 1>::n_quads(const unsigned int) const
15182{
15183 return 0;
15184}
15185
15186
15187template <>
15188unsigned int
15189Triangulation<1, 1>::n_raw_quads(const unsigned int) const
15190{
15191 return 0;
15192}
15193
15194
15195template <>
15196unsigned int
15197Triangulation<1, 1>::n_raw_hexs(const unsigned int) const
15198{
15199 return 0;
15200}
15201
15202
15203template <>
15204unsigned int
15206{
15207 return 0;
15208}
15209
15210
15211template <>
15212unsigned int
15214{
15215 return 0;
15216}
15217
15218
15219
15220template <>
15221unsigned int
15223{
15224 return 0;
15225}
15226
15227
15228template <>
15229unsigned int
15230Triangulation<1, 2>::n_quads(const unsigned int) const
15231{
15232 return 0;
15233}
15234
15235
15236template <>
15237unsigned int
15238Triangulation<1, 2>::n_raw_quads(const unsigned int) const
15239{
15240 return 0;
15241}
15242
15243
15244template <>
15245unsigned int
15246Triangulation<1, 2>::n_raw_hexs(const unsigned int) const
15247{
15248 return 0;
15249}
15250
15251
15252template <>
15253unsigned int
15255{
15256 return 0;
15257}
15258
15259
15260template <>
15261unsigned int
15263{
15264 return 0;
15265}
15266
15267
15268template <>
15269unsigned int
15271{
15272 return 0;
15273}
15274
15275
15276template <>
15277unsigned int
15278Triangulation<1, 3>::n_quads(const unsigned int) const
15279{
15280 return 0;
15281}
15282
15283
15284template <>
15285unsigned int
15286Triangulation<1, 3>::n_raw_quads(const unsigned int) const
15287{
15288 return 0;
15289}
15290
15291
15292template <>
15293unsigned int
15294Triangulation<1, 3>::n_raw_hexs(const unsigned int) const
15295{
15296 return 0;
15297}
15298
15299
15300template <>
15301unsigned int
15303{
15304 return 0;
15305}
15306
15307
15308template <>
15309unsigned int
15311{
15312 return 0;
15313}
15314
15315#ifndef DOXYGEN
15316
15317template <int dim, int spacedim>
15319unsigned int Triangulation<dim, spacedim>::n_quads() const
15320{
15321 return number_cache.n_quads;
15322}
15323
15324
15325template <int dim, int spacedim>
15328 const unsigned int level) const
15329{
15330 Assert(dim == 2, ExcFacesHaveNoLevel());
15331 AssertIndexRange(level, number_cache.n_quads_level.size());
15332 return number_cache.n_quads_level[level];
15333}
15334
15335#endif
15336
15337template <>
15338unsigned int
15340{
15341 AssertIndexRange(level, n_levels());
15342 return levels[level]->cells.n_objects();
15343}
15344
15345
15346
15347template <>
15348unsigned int
15350{
15351 AssertIndexRange(level, n_levels());
15352 return levels[level]->cells.n_objects();
15353}
15354
15355
15356template <>
15357unsigned int
15358Triangulation<3, 3>::n_raw_quads(const unsigned int) const
15359{
15360 Assert(false, ExcFacesHaveNoLevel());
15361 return 0;
15362}
15363
15364#ifndef DOXYGEN
15365
15366template <int dim, int spacedim>
15369{
15371 return 0;
15372}
15373
15374#endif
15375
15376template <>
15377unsigned int
15379{
15380 return faces->quads.n_objects();
15381}
15382
15383#ifndef DOXYGEN
15384
15385template <int dim, int spacedim>
15388{
15389 return number_cache.n_active_quads;
15390}
15391
15392
15393template <int dim, int spacedim>
15396 const unsigned int level) const
15397{
15398 AssertIndexRange(level, number_cache.n_quads_level.size());
15399 Assert(dim == 2, ExcFacesHaveNoLevel());
15400
15401 return number_cache.n_active_quads_level[level];
15402}
15403
15404
15405template <int dim, int spacedim>
15407unsigned int Triangulation<dim, spacedim>::n_hexs() const
15408{
15409 return 0;
15410}
15411
15412
15413
15414template <int dim, int spacedim>
15416unsigned int Triangulation<dim, spacedim>::n_hexs(const unsigned int) const
15417{
15418 return 0;
15419}
15420
15421
15422
15423template <int dim, int spacedim>
15425unsigned int Triangulation<dim, spacedim>::n_raw_hexs(const unsigned int) const
15426{
15427 return 0;
15428}
15429
15430
15431template <int dim, int spacedim>
15434{
15435 return 0;
15436}
15437
15438
15439
15440template <int dim, int spacedim>
15443 const unsigned int) const
15444{
15445 return 0;
15446}
15447
15448#endif
15449
15450template <>
15451unsigned int
15453{
15454 return number_cache.n_hexes;
15455}
15456
15457
15458
15459template <>
15460unsigned int
15461Triangulation<3, 3>::n_hexs(const unsigned int level) const
15462{
15463 AssertIndexRange(level, number_cache.n_hexes_level.size());
15464
15465 return number_cache.n_hexes_level[level];
15466}
15467
15468
15469
15470template <>
15471unsigned int
15473{
15474 AssertIndexRange(level, n_levels());
15475 return levels[level]->cells.n_objects();
15476}
15477
15478
15479template <>
15480unsigned int
15482{
15483 return number_cache.n_active_hexes;
15484}
15485
15486
15487
15488template <>
15489unsigned int
15491{
15492 AssertIndexRange(level, number_cache.n_hexes_level.size());
15493
15494 return number_cache.n_active_hexes_level[level];
15495}
15496
15497#ifndef DOXYGEN
15498
15499template <int dim, int spacedim>
15502{
15503 return std::count(vertices_used.begin(), vertices_used.end(), true);
15504}
15505
15506
15507
15508template <int dim, int spacedim>
15510const std::vector<bool> &Triangulation<dim, spacedim>::get_used_vertices() const
15511{
15512 return vertices_used;
15513}
15514
15515#endif
15516
15517template <>
15518unsigned int
15520{
15521 return 2;
15522}
15523
15524
15525
15526template <>
15527unsigned int
15529{
15530 return 2;
15531}
15532
15533
15534template <>
15535unsigned int
15537{
15538 return 2;
15539}
15540
15541#ifndef DOXYGEN
15542
15543template <int dim, int spacedim>
15546{
15547 cell_iterator cell = begin(0),
15548 endc = (n_levels() > 1 ? begin(1) : cell_iterator(end()));
15549 // store the largest index of the
15550 // vertices used on level 0
15551 unsigned int max_vertex_index = 0;
15552 for (; cell != endc; ++cell)
15553 for (const unsigned int vertex : GeometryInfo<dim>::vertex_indices())
15554 if (cell->vertex_index(vertex) > max_vertex_index)
15555 max_vertex_index = cell->vertex_index(vertex);
15556
15557 // store the number of times a cell
15558 // touches a vertex. An unsigned
15559 // int should suffice, even for
15560 // larger dimensions
15561 std::vector<unsigned short int> usage_count(max_vertex_index + 1, 0);
15562 // touch a vertex's usage count
15563 // every time we find an adjacent
15564 // element
15565 for (cell = begin(); cell != endc; ++cell)
15566 for (const unsigned int vertex : GeometryInfo<dim>::vertex_indices())
15567 ++usage_count[cell->vertex_index(vertex)];
15568
15570 static_cast<unsigned int>(
15571 *std::max_element(usage_count.begin(), usage_count.end())));
15572}
15573
15574
15575
15576template <int dim, int spacedim>
15580{
15582}
15583
15584
15585
15586template <int dim, int spacedim>
15589{
15590 return *this;
15591}
15592
15593
15594
15595template <int dim, int spacedim>
15599{
15600 return *this;
15601}
15602
15603
15604
15605template <int dim, int spacedim>
15609 &periodicity_vector)
15610{
15611 periodic_face_pairs_level_0.insert(periodic_face_pairs_level_0.end(),
15612 periodicity_vector.begin(),
15613 periodicity_vector.end());
15614
15615 // Now initialize periodic_face_map
15616 update_periodic_face_map();
15617}
15618
15619
15620
15621template <int dim, int spacedim>
15623const typename std::map<
15624 std::pair<typename Triangulation<dim, spacedim>::cell_iterator, unsigned int>,
15625 std::pair<std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
15626 unsigned int>,
15627 unsigned char>>
15629{
15630 return periodic_face_map;
15631}
15632
15633
15634template <int dim, int spacedim>
15637{
15638 // We only update the cell relations here for serial triangulations.
15639 // For other triangulations, this is done at other stages of
15640 // mesh creation and mesh refinement.
15642 this))
15643 return;
15644
15645 this->local_cell_relations.clear();
15646 this->local_cell_relations.reserve(this->n_active_cells());
15647
15648 for (const auto &cell : this->active_cell_iterators())
15649 this->local_cell_relations.emplace_back(
15650 cell, ::CellStatus::cell_will_persist);
15651}
15652
15653
15654
15655template <int dim, int spacedim>
15658{
15659 // Call our version of prepare_coarsening_and_refinement() even if a derived
15660 // class like parallel::distributed::Triangulation overrides it. Their
15661 // function will be called in their execute_coarsening_and_refinement()
15662 // function. Even in a distributed computation our job here is to reconstruct
15663 // the local part of the mesh and as such checking our flags is enough.
15665
15666 // verify a case with which we have had
15667 // some difficulty in the past (see the
15668 // deal.II/coarsening_* tests)
15669 if (smooth_grid & limit_level_difference_at_vertices)
15670 Assert(satisfies_level1_at_vertex_rule(*this) == true, ExcInternalError());
15671
15672 // Inform all listeners about beginning of refinement.
15673 signals.pre_refinement();
15674
15675 execute_coarsening();
15676
15677 const DistortedCellList cells_with_distorted_children = execute_refinement();
15678
15679 reset_cell_vertex_indices_cache();
15680
15681 // verify a case with which we have had
15682 // some difficulty in the past (see the
15683 // deal.II/coarsening_* tests)
15684 if (smooth_grid & limit_level_difference_at_vertices)
15685 Assert(satisfies_level1_at_vertex_rule(*this) == true, ExcInternalError());
15686
15687 // finally build up neighbor connectivity information, and set
15688 // active cell indices
15689 this->policy->update_neighbors(*this);
15690 reset_active_cell_indices();
15691
15692 reset_global_cell_indices(); // TODO: better place?
15693
15694 // Inform all listeners about end of refinement.
15695 signals.post_refinement();
15696
15697 AssertThrow(cells_with_distorted_children.distorted_cells.empty(),
15698 cells_with_distorted_children);
15699
15700 update_periodic_face_map();
15701
15702 if (this->cell_attached_data.n_attached_data_sets == 0)
15703 this->update_cell_relations();
15704
15705# ifdef DEBUG
15706
15707 // In debug mode, we want to check for some consistency of the
15708 // result of this function. Because there are multiple exit
15709 // paths, put this check into a ScopeExit object that is
15710 // executed on each of the exit paths.
15711 //
15712 // Specifically, check on exit of this function that if a quad
15713 // cell has been refined, all of its children have neighbors
15714 // in all directions in which the parent cell has neighbors as
15715 // well. The children's neighbors are either the parent
15716 // neighbor or the parent neighbor's children, or simply one of
15717 // the other children of the current cell. This check is
15718 // useful because if one creates a triangulation with an
15719 // inconsistently ordered set of cells (e.g., because one has
15720 // forgotten to call GridTools::consistently_order_cells()),
15721 // then this relatively simple invariant is violated -- so the
15722 // check here can be used to catch that case, at least
15723 // sometimes.
15724 //
15725 // In 1d, this situation cannot happen. In 3d, we have explicit
15726 // orientation flags to ensure that it is not necessary to re-orient
15727 // cells at the beginning. But in both cases, the invariant should
15728 // still hold as long as the cell is a hypercube.
15729 for (const auto &cell : cell_iterators())
15730 {
15731 if (cell->has_children() && cell->reference_cell().is_hyper_cube())
15732 for (const unsigned int f : cell->face_indices())
15733 if (cell->at_boundary(f) == false)
15734 {
15735 for (const auto &child : cell->child_iterators())
15736 {
15737 Assert(
15738 child->at_boundary(f) == false,
15739 ExcMessage(
15740 "We ended up with a triangulation whose child cells "
15741 "are not connected to their neighbors as expected. "
15742 "When you created the triangulation, did you forget "
15743 "to call GridTools::consistently_order_cells() "
15744 "before calling Triangulation::create_triangulation()?"));
15745 }
15746 }
15747 }
15748# endif
15749}
15750
15751
15752
15753template <int dim, int spacedim>
15756{
15757 unsigned int active_cell_index = 0;
15758 for (raw_cell_iterator cell = begin_raw(); cell != end(); ++cell)
15759 if ((cell->used() == false) || cell->has_children())
15760 cell->set_active_cell_index(numbers::invalid_unsigned_int);
15761 else
15762 {
15763 cell->set_active_cell_index(active_cell_index);
15764 ++active_cell_index;
15765 }
15766
15767 Assert(active_cell_index == n_active_cells(), ExcInternalError());
15768}
15769
15770
15771
15772template <int dim, int spacedim>
15775{
15776 {
15778 for (const auto &cell : active_cell_iterators())
15779 cell->set_global_active_cell_index(cell_index++);
15780 }
15781
15782 for (unsigned int l = 0; l < levels.size(); ++l)
15783 {
15785 for (const auto &cell : cell_iterators_on_level(l))
15786 cell->set_global_level_cell_index(cell_index++);
15787 }
15788}
15789
15790
15791
15792template <int dim, int spacedim>
15795{
15796 for (unsigned int l = 0; l < levels.size(); ++l)
15797 {
15798 constexpr unsigned int max_vertices_per_cell = 1 << dim;
15799 std::vector<unsigned int> &cache = levels[l]->cell_vertex_indices_cache;
15800 cache.clear();
15801 cache.resize(levels[l]->refine_flags.size() * max_vertices_per_cell,
15803 for (const auto &cell : cell_iterators_on_level(l))
15804 {
15805 const unsigned int my_index = cell->index() * max_vertices_per_cell;
15806
15807 // to reduce the cost of this function when passing down into quads,
15808 // then lines, then vertices, we use a more low-level access method
15809 // for hexahedral cells, where we can streamline most of the logic
15810 const ReferenceCell ref_cell = cell->reference_cell();
15811 if (ref_cell == ReferenceCells::Hexahedron)
15812 for (unsigned int face = 4; face < 6; ++face)
15813 {
15814 const auto face_iter = cell->face(face);
15815 const std::array<bool, 2> line_orientations{
15816 {face_iter->line_orientation(0),
15817 face_iter->line_orientation(1)}};
15818 std::array<unsigned int, 4> raw_vertex_indices{
15819 {face_iter->line(0)->vertex_index(1 - line_orientations[0]),
15820 face_iter->line(1)->vertex_index(1 - line_orientations[1]),
15821 face_iter->line(0)->vertex_index(line_orientations[0]),
15822 face_iter->line(1)->vertex_index(line_orientations[1])}};
15823
15824 const unsigned char combined_orientation =
15825 levels[l]->face_orientations.get_combined_orientation(
15826 cell->index() * GeometryInfo<3>::faces_per_cell + face);
15827 std::array<unsigned int, 4> vertex_order{
15828 {ref_cell.standard_to_real_face_vertex(0,
15829 face,
15830 combined_orientation),
15832 face,
15833 combined_orientation),
15835 face,
15836 combined_orientation),
15838 3, face, combined_orientation)}};
15839
15840 const unsigned int index = my_index + 4 * (face - 4);
15841 for (unsigned int i = 0; i < 4; ++i)
15842 cache[index + i] = raw_vertex_indices[vertex_order[i]];
15843 }
15844 else if (ref_cell == ReferenceCells::Quadrilateral)
15845 {
15846 const std::array<bool, 2> line_orientations{
15847 {cell->line_orientation(0), cell->line_orientation(1)}};
15848 std::array<unsigned int, 4> raw_vertex_indices{
15849 {cell->line(0)->vertex_index(1 - line_orientations[0]),
15850 cell->line(1)->vertex_index(1 - line_orientations[1]),
15851 cell->line(0)->vertex_index(line_orientations[0]),
15852 cell->line(1)->vertex_index(line_orientations[1])}};
15853 for (unsigned int i = 0; i < 4; ++i)
15854 cache[my_index + i] = raw_vertex_indices[i];
15855 }
15856 else
15857 for (const unsigned int i : cell->vertex_indices())
15858 cache[my_index + i] = internal::TriaAccessorImplementation::
15859 Implementation::vertex_index(*cell, i);
15860 }
15861 }
15862}
15863
15864
15865
15866template <int dim, int spacedim>
15869{
15870 // first empty the currently stored objects
15871 periodic_face_map.clear();
15872
15873 typename std::vector<
15875 for (it = periodic_face_pairs_level_0.begin();
15876 it != periodic_face_pairs_level_0.end();
15877 ++it)
15878 {
15879 update_periodic_face_map_recursively<dim, spacedim>(it->cell[0],
15880 it->cell[1],
15881 it->face_idx[0],
15882 it->face_idx[1],
15883 it->orientation,
15884 periodic_face_map);
15885
15886 const auto face_reference_cell =
15887 it->cell[0]->reference_cell().face_reference_cell(it->face_idx[0]);
15888 // for the other way, we need to invert the orientation
15889 update_periodic_face_map_recursively<dim, spacedim>(
15890 it->cell[1],
15891 it->cell[0],
15892 it->face_idx[1],
15893 it->face_idx[0],
15894 face_reference_cell.get_inverse_combined_orientation(it->orientation),
15895 periodic_face_map);
15896 }
15897
15898 // check consistency
15899 typename std::map<std::pair<cell_iterator, unsigned int>,
15900 std::pair<std::pair<cell_iterator, unsigned int>,
15901 unsigned char>>::const_iterator it_test;
15902 for (it_test = periodic_face_map.begin(); it_test != periodic_face_map.end();
15903 ++it_test)
15904 {
15906 it_test->first.first;
15908 it_test->second.first.first;
15909 if (cell_1->level() == cell_2->level())
15910 {
15911 // if both cells have the same neighbor, then the same pair
15912 // order swapped has to be in the map
15913 Assert(periodic_face_map[it_test->second.first].first ==
15914 it_test->first,
15916 }
15917 }
15918}
15919
15920
15921
15922template <int dim, int spacedim>
15925{
15926 std::set<ReferenceCell> reference_cells_set;
15927 for (auto cell : active_cell_iterators())
15928 if (cell->is_locally_owned())
15929 reference_cells_set.insert(cell->reference_cell());
15930
15931 this->reference_cells =
15932 std::vector<ReferenceCell>(reference_cells_set.begin(),
15933 reference_cells_set.end());
15934}
15935
15936
15937
15938template <int dim, int spacedim>
15940const std::vector<ReferenceCell>
15942{
15943 return this->reference_cells;
15944}
15945
15946
15947
15948template <int dim, int spacedim>
15951{
15952 Assert(this->reference_cells.size() > 0,
15953 ExcMessage("You can't ask about the kinds of reference "
15954 "cells used by this triangulation if the "
15955 "triangulation doesn't yet have any cells in it."));
15956 return (this->reference_cells.size() == 1 &&
15957 this->reference_cells[0].is_hyper_cube());
15958}
15959
15960
15961
15962template <int dim, int spacedim>
15965{
15966 Assert(this->reference_cells.size() > 0,
15967 ExcMessage("You can't ask about the kinds of reference "
15968 "cells used by this triangulation if the "
15969 "triangulation doesn't yet have any cells in it."));
15970 return (this->reference_cells.size() == 1 &&
15971 this->reference_cells[0].is_simplex());
15972}
15973
15974
15975
15976template <int dim, int spacedim>
15979{
15980 Assert(this->reference_cells.size() > 0,
15981 ExcMessage("You can't ask about the kinds of reference "
15982 "cells used by this triangulation if the "
15983 "triangulation doesn't yet have any cells in it."));
15984 return reference_cells.size() > 1 ||
15985 ((reference_cells[0].is_hyper_cube() == false) &&
15986 (reference_cells[0].is_simplex() == false));
15987}
15988
15989
15990
15991template <int dim, int spacedim>
15994 const std::function<std::vector<char>(const cell_iterator &,
15995 const ::CellStatus)>
15996 &pack_callback,
15997 const bool returns_variable_size_data)
15998{
15999 unsigned int handle = numbers::invalid_unsigned_int;
16000
16001 // Add new callback function to the corresponding register.
16002 // Encode handles according to returns_variable_size_data.
16003 if (returns_variable_size_data)
16004 {
16005 handle = 2 * this->cell_attached_data.pack_callbacks_variable.size();
16006 this->cell_attached_data.pack_callbacks_variable.push_back(pack_callback);
16007 }
16008 else
16009 {
16010 handle = 2 * this->cell_attached_data.pack_callbacks_fixed.size() + 1;
16011 this->cell_attached_data.pack_callbacks_fixed.push_back(pack_callback);
16012 }
16013
16014 // Increase overall counter.
16015 ++this->cell_attached_data.n_attached_data_sets;
16016
16017 return handle;
16018}
16019
16020
16021
16022template <int dim, int spacedim>
16025 const unsigned int handle,
16026 const std::function<
16027 void(const cell_iterator &,
16028 const ::CellStatus,
16029 const boost::iterator_range<std::vector<char>::const_iterator> &)>
16030 &unpack_callback)
16031{
16032 // perform unpacking
16033 this->data_serializer.unpack_data(this->local_cell_relations,
16034 handle,
16035 unpack_callback);
16036
16037 // decrease counters
16038 --this->cell_attached_data.n_attached_data_sets;
16039 if (this->cell_attached_data.n_attached_deserialize > 0)
16040 --this->cell_attached_data.n_attached_deserialize;
16041
16042 // important: only remove data if we are not in the deserialization
16043 // process. There, each SolutionTransfer registers and unpacks before
16044 // the next one does this, so n_attached_data_sets is only 1 here. This
16045 // would destroy the saved data before the second SolutionTransfer can
16046 // get it. This created a bug that is documented in
16047 // tests/mpi/p4est_save_03 with more than one SolutionTransfer.
16048
16049 if (this->cell_attached_data.n_attached_data_sets == 0 &&
16050 this->cell_attached_data.n_attached_deserialize == 0)
16051 {
16052 // everybody got their data, time for cleanup!
16053 this->cell_attached_data.pack_callbacks_fixed.clear();
16054 this->cell_attached_data.pack_callbacks_variable.clear();
16055 this->data_serializer.clear();
16056
16057 // reset all cell_status entries after coarsening/refinement
16058 for (auto &cell_rel : this->local_cell_relations)
16059 cell_rel.second = ::CellStatus::cell_will_persist;
16060 }
16061}
16062
16063
16064
16065template <int dim, int spacedim>
16068 const unsigned int global_first_cell,
16069 const unsigned int global_num_cells,
16070 const std::string &file_basename) const
16071{
16072 // cast away constness
16073 auto tria = const_cast<Triangulation<dim, spacedim> *>(this);
16074
16075 if (this->cell_attached_data.n_attached_data_sets > 0)
16076 {
16077 // pack attached data first
16079 tria->local_cell_relations,
16080 tria->cell_attached_data.pack_callbacks_fixed,
16081 tria->cell_attached_data.pack_callbacks_variable,
16082 this->get_communicator());
16083
16084 // then store buffers in file
16085 tria->data_serializer.save(global_first_cell,
16086 global_num_cells,
16087 file_basename,
16088 this->get_communicator());
16089
16090 // and release the memory afterwards
16091 tria->data_serializer.clear();
16092 }
16093
16094 // clear all of the callback data, as explained in the documentation of
16095 // register_data_attach()
16096 {
16097 tria->cell_attached_data.n_attached_data_sets = 0;
16098 tria->cell_attached_data.pack_callbacks_fixed.clear();
16099 tria->cell_attached_data.pack_callbacks_variable.clear();
16100 }
16101}
16102
16103
16104template <int dim, int spacedim>
16107 const unsigned int global_first_cell,
16108 const unsigned int global_num_cells,
16109 const unsigned int local_num_cells,
16110 const std::string &file_basename,
16111 const unsigned int n_attached_deserialize_fixed,
16112 const unsigned int n_attached_deserialize_variable)
16113{
16114 // load saved data, if any was stored
16115 if (this->cell_attached_data.n_attached_deserialize > 0)
16116 {
16117 this->data_serializer.load(global_first_cell,
16118 global_num_cells,
16119 local_num_cells,
16120 file_basename,
16121 n_attached_deserialize_fixed,
16122 n_attached_deserialize_variable,
16123 this->get_communicator());
16124
16125 this->data_serializer.unpack_cell_status(this->local_cell_relations);
16126
16127 // the CellStatus of all stored cells should always be
16128 // CellStatus::cell_will_persist.
16129 for (const auto &cell_rel : this->local_cell_relations)
16130 {
16131 (void)cell_rel;
16132 Assert((cell_rel.second == // cell_status
16135 }
16136 }
16137}
16138
16139
16140template <int dim, int spacedim>
16143{
16144 levels.clear();
16145 faces.reset();
16146
16147 vertices.clear();
16148 vertices_used.clear();
16149
16150 manifolds.clear();
16151
16152 // In 1d, also reset vertex-to-(boundary|manifold) maps to empty maps
16153 if (dim == 1)
16154 {
16155 Assert(vertex_to_boundary_id_map_1d != nullptr, ExcInternalError());
16156 vertex_to_boundary_id_map_1d->clear();
16157
16158 Assert(vertex_to_manifold_id_map_1d != nullptr, ExcInternalError());
16159 vertex_to_manifold_id_map_1d->clear();
16160 }
16161 else
16162 {
16163 // For dim>1, these maps should simply not exist.
16164 Assert(vertex_to_boundary_id_map_1d == nullptr, ExcInternalError());
16165 Assert(vertex_to_manifold_id_map_1d == nullptr, ExcInternalError());
16166 }
16167
16168
16170}
16171
16172
16173
16174template <int dim, int spacedim>
16178{
16179 const DistortedCellList cells_with_distorted_children =
16180 this->policy->execute_refinement(*this, check_for_distorted_cells);
16181
16182
16183
16184 // re-compute number of lines
16186 *this, levels.size(), number_cache);
16187
16188# ifdef DEBUG
16189 for (const auto &level : levels)
16190 monitor_memory(level->cells, dim);
16191
16192 // check whether really all refinement flags are reset (also of
16193 // previously non-active cells which we may not have touched. If the
16194 // refinement flag of a non-active cell is set, something went wrong
16195 // since the cell-accessors should have caught this)
16196 for (const auto &cell : this->cell_iterators())
16197 Assert(!cell->refine_flag_set(), ExcInternalError());
16198# endif
16199
16200 return cells_with_distorted_children;
16201}
16202
16203
16204
16205template <int dim, int spacedim>
16208{
16209 // first find out if there are any cells at all to be coarsened in the
16210 // loop below
16211 const cell_iterator endc = end();
16212 bool do_coarsen = false;
16213 if (levels.size() >= 2)
16214 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
16215 if (!cell->is_active() && cell->child(0)->coarsen_flag_set())
16216 {
16217 do_coarsen = true;
16218 break;
16219 }
16220
16221 if (!do_coarsen)
16222 return;
16223
16224 // create a vector counting for each line and quads how many cells contain
16225 // the respective object. this is used later to decide which lines can be
16226 // deleted after coarsening a cell.
16227 std::vector<unsigned int> line_cell_count(dim > 1 ? this->n_raw_lines() : 0);
16228 std::vector<unsigned int> quad_cell_count(dim > 2 ? this->n_raw_quads() : 0);
16229 if (dim > 1)
16230 for (const auto &cell : this->cell_iterators())
16231 {
16232 if (dim > 2)
16233 {
16234 const auto line_indices = internal::TriaAccessorImplementation::
16235 Implementation::get_line_indices_of_cell(*cell);
16236 // avoid a compiler warning by fixing the max number of
16237 // loop iterations to 12
16238 const unsigned int n_lines = std::min(cell->n_lines(), 12u);
16239 for (unsigned int l = 0; l < n_lines; ++l)
16240 ++line_cell_count[line_indices[l]];
16241 for (const unsigned int q : cell->face_indices())
16242 ++quad_cell_count[cell->face_index(q)];
16243 }
16244 else
16245 for (unsigned int l = 0; l < cell->n_lines(); ++l)
16246 ++line_cell_count[cell->line(l)->index()];
16247 }
16248
16249 // Since the loop goes over used cells we only need not worry about
16250 // deleting some cells since the ++operator will then just hop over them
16251 // if we should hit one. Do the loop in the reverse way since we may
16252 // only delete some cells if their neighbors have already been deleted
16253 // (if the latter are on a higher level for example). In effect, only
16254 // those cells are deleted of which originally all children were flagged
16255 // and for which all children are on the same refinement level. Note
16256 // that because of the effects of
16257 // @p{fix_coarsen_flags}, of a cell either all or no children must be
16258 // flagged for coarsening, so it is ok to only check the first child
16259 //
16260 // since we delete the *children* of cells, we can ignore cells on the
16261 // highest level, i.e., level must be less than or equal to
16262 // n_levels()-2.
16263 if (levels.size() >= 2)
16264 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
16265 if (!cell->is_active() && cell->child(0)->coarsen_flag_set())
16266 {
16267 for (unsigned int child = 0; child < cell->n_children(); ++child)
16268 {
16269 Assert(cell->child(child)->coarsen_flag_set(),
16271 cell->child(child)->clear_coarsen_flag();
16272 }
16273 // inform all listeners that cell coarsening is going to happen
16274 signals.pre_coarsening_on_cell(cell);
16275 // use a separate function, since this is dimension specific
16276 this->policy->delete_children(*this,
16277 cell,
16278 line_cell_count,
16279 quad_cell_count);
16280 }
16281
16282 // re-compute number of lines and quads
16284 *this, levels.size(), number_cache);
16285}
16286
16287
16288
16289template <int dim, int spacedim>
16292{
16293 // copy a piece of code from prepare_coarsening_and_refinement that
16294 // ensures that the level difference at vertices is limited if so
16295 // desired. we need this code here since at least in 1d we don't
16296 // call the dimension-independent version of
16297 // prepare_coarsening_and_refinement function. in 2d and 3d, having
16298 // this hunk here makes our lives a bit easier as well as it takes
16299 // care of these cases earlier than it would otherwise happen.
16300 //
16301 // the main difference to the code in p_c_and_r is that here we
16302 // absolutely have to make sure that we get things right, i.e. that
16303 // in particular we set flags right if
16304 // limit_level_difference_at_vertices is set. to do so we iterate
16305 // until the flags don't change any more
16306 auto previous_coarsen_flags = internal::extract_raw_coarsen_flags(levels);
16307
16308 bool continue_iterating = true;
16309
16310 do
16311 {
16312 if (smooth_grid & limit_level_difference_at_vertices)
16313 {
16314 Assert(!anisotropic_refinement,
16315 ExcMessage("In case of anisotropic refinement the "
16316 "limit_level_difference_at_vertices flag for "
16317 "mesh smoothing must not be set!"));
16318
16319 // store highest level one of the cells adjacent to a vertex
16320 // belongs to
16321 std::vector<int> vertex_level(vertices.size(), 0);
16322 for (const auto &cell : this->active_cell_iterators())
16323 {
16324 if (cell->refine_flag_set())
16325 for (const unsigned int vertex :
16327 vertex_level[cell->vertex_index(vertex)] =
16328 std::max(vertex_level[cell->vertex_index(vertex)],
16329 cell->level() + 1);
16330 else if (!cell->coarsen_flag_set())
16331 for (const unsigned int vertex :
16333 vertex_level[cell->vertex_index(vertex)] =
16334 std::max(vertex_level[cell->vertex_index(vertex)],
16335 cell->level());
16336 else
16337 {
16338 // if coarsen flag is set then tentatively assume
16339 // that the cell will be coarsened. this isn't
16340 // always true (the coarsen flag could be removed
16341 // again) and so we may make an error here. we try
16342 // to correct this by iterating over the entire
16343 // process until we are converged
16344 Assert(cell->coarsen_flag_set(), ExcInternalError());
16345 for (const unsigned int vertex :
16347 vertex_level[cell->vertex_index(vertex)] =
16348 std::max(vertex_level[cell->vertex_index(vertex)],
16349 cell->level() - 1);
16350 }
16351 }
16352
16353
16354 // loop over all cells in reverse order. do so because we
16355 // can then update the vertex levels on the adjacent
16356 // vertices and maybe already flag additional cells in this
16357 // loop
16358 //
16359 // note that not only may we have to add additional
16360 // refinement flags, but we will also have to remove
16361 // coarsening flags on cells adjacent to vertices that will
16362 // see refinement
16363 active_cell_iterator endc = end();
16364 for (active_cell_iterator cell = last_active(); cell != endc; --cell)
16365 if (cell->refine_flag_set() == false)
16366 {
16367 for (const unsigned int vertex :
16369 if (vertex_level[cell->vertex_index(vertex)] >=
16370 cell->level() + 1)
16371 {
16372 // remove coarsen flag...
16373 cell->clear_coarsen_flag();
16374
16375 // ...and if necessary also refine the current
16376 // cell, at the same time updating the level
16377 // information about vertices
16378 if (vertex_level[cell->vertex_index(vertex)] >
16379 cell->level() + 1)
16380 {
16381 cell->set_refine_flag();
16382
16383 for (const unsigned int v :
16385 vertex_level[cell->vertex_index(v)] =
16386 std::max(vertex_level[cell->vertex_index(v)],
16387 cell->level() + 1);
16388 }
16389
16390 // continue and see whether we may, for example,
16391 // go into the inner 'if' above based on a
16392 // different vertex
16393 }
16394 }
16395 }
16396
16397 // loop over all cells and remove the coarsen flags for those cells that
16398 // have sister cells not marked for coarsening, or where some neighbors
16399 // are more refined.
16400
16401 // Coarsen flags of cells with no mother cell, i.e. on the
16402 // coarsest level, are deleted explicitly.
16403 for (const auto &acell : this->active_cell_iterators_on_level(0))
16404 acell->clear_coarsen_flag();
16405
16406 const cell_iterator endc = end();
16407 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
16408 {
16409 // nothing to do if we are already on the finest level
16410 if (cell->is_active())
16411 continue;
16412
16413 const unsigned int n_children = cell->n_children();
16414 unsigned int flagged_children = 0;
16415 for (unsigned int child = 0; child < n_children; ++child)
16416 {
16417 const auto child_cell = cell->child(child);
16418 if (child_cell->is_active() && child_cell->coarsen_flag_set())
16419 {
16420 ++flagged_children;
16421 // clear flag since we don't need it anymore
16422 child_cell->clear_coarsen_flag();
16423 }
16424 }
16425
16426 // flag the children for coarsening again if all children were
16427 // flagged and if the policy allows it
16428 if (flagged_children == n_children &&
16429 this->policy->coarsening_allowed(cell))
16430 for (unsigned int c = 0; c < n_children; ++c)
16431 {
16432 Assert(cell->child(c)->refine_flag_set() == false,
16434
16435 cell->child(c)->set_coarsen_flag();
16436 }
16437 }
16438
16439 // now see if anything has changed in the last iteration of this
16440 // function
16441 auto current_coarsen_flags = internal::extract_raw_coarsen_flags(levels);
16442
16443 continue_iterating = (current_coarsen_flags != previous_coarsen_flags);
16444 previous_coarsen_flags.swap(current_coarsen_flags);
16445 }
16446 while (continue_iterating == true);
16447}
16448
16449#endif
16450
16451// TODO: merge the following 3 functions since they are the same
16452template <>
16453bool
16455{
16456 // save the flags to determine whether something was changed in the
16457 // course of this function
16458 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
16459
16460 // do nothing in 1d, except setting the coarsening flags correctly
16461 fix_coarsen_flags();
16462
16463 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
16464
16465 return (flags_before != flags_after);
16466}
16467
16468
16469
16470template <>
16471bool
16473{
16474 // save the flags to determine whether something was changed in the
16475 // course of this function
16476 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
16477
16478 // do nothing in 1d, except setting the coarsening flags correctly
16479 fix_coarsen_flags();
16480
16481 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
16482
16483 return (flags_before != flags_after);
16484}
16485
16486
16487
16488template <>
16489bool
16491{
16492 // save the flags to determine whether something was changed in the
16493 // course of this function
16494 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
16495
16496 // do nothing in 1d, except setting the coarsening flags correctly
16497 fix_coarsen_flags();
16498
16499 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
16500
16501 return (flags_before != flags_after);
16502}
16503
16504
16505
16506namespace
16507{
16508 // check if the given @param cell marked for coarsening would
16509 // produce an unrefined island. To break up long chains of these
16510 // cells we recursively check our neighbors in case we change this
16511 // cell. This reduces the number of outer iterations dramatically.
16512 template <int dim, int spacedim>
16513 void
16514 possibly_do_not_produce_unrefined_islands(
16516 {
16517 Assert(cell->has_children(), ExcInternalError());
16518
16519 unsigned int n_neighbors = 0;
16520 // count all neighbors that will be refined along the face of our
16521 // cell after the next step
16522 unsigned int count = 0;
16523 for (const unsigned int n : GeometryInfo<dim>::face_indices())
16524 {
16525 const typename Triangulation<dim, spacedim>::cell_iterator neighbor =
16526 cell->neighbor(n);
16527 if (neighbor.state() == IteratorState::valid)
16528 {
16529 ++n_neighbors;
16530 if (face_will_be_refined_by_neighbor(cell, n))
16531 ++count;
16532 }
16533 }
16534 // clear coarsen flags if either all existing neighbors will be
16535 // refined or all but one will be and the cell is in the interior
16536 // of the domain
16537 if (count == n_neighbors ||
16538 (count >= n_neighbors - 1 &&
16539 n_neighbors == GeometryInfo<dim>::faces_per_cell))
16540 {
16541 for (unsigned int c = 0; c < cell->n_children(); ++c)
16542 cell->child(c)->clear_coarsen_flag();
16543
16544 for (const unsigned int face : GeometryInfo<dim>::face_indices())
16545 if (!cell->at_boundary(face) &&
16546 (!cell->neighbor(face)->is_active()) &&
16547 (cell_will_be_coarsened(cell->neighbor(face))))
16548 possibly_do_not_produce_unrefined_islands<dim, spacedim>(
16549 cell->neighbor(face));
16550 }
16551 }
16552
16553
16554 // see if the current cell needs to be refined to avoid unrefined
16555 // islands.
16556 //
16557 // there are sometimes chains of cells that induce refinement of
16558 // each other. to avoid running the loop in
16559 // prepare_coarsening_and_refinement over and over again for each
16560 // one of them, at least for the isotropic refinement case we seek
16561 // to flag neighboring elements as well as necessary. this takes
16562 // care of (slightly pathological) cases like
16563 // deal.II/mesh_smoothing_03
16564 template <int dim, int spacedim>
16565 void
16566 possibly_refine_unrefined_island(
16568 const bool allow_anisotropic_smoothing)
16569 {
16570 Assert(cell->is_active(), ExcInternalError());
16571
16572#ifdef DEBUG
16573 // If this is not a parallel::distributed::Triangulation, then we really
16574 // should only get here if the cell is marked for refinement:
16576 *>(&cell->get_triangulation()) == nullptr)
16577 Assert(cell->refine_flag_set() == false, ExcInternalError());
16578 else
16579 // But if this is a p::d::Triangulation, then we don't have that
16580 // much control and we can get here because mesh smoothing is
16581 // requested but can not be honored because p4est controls
16582 // what gets refined. In that case, we can at least provide
16583 // a better error message.
16584 Assert(cell->refine_flag_set() == false,
16585 ExcMessage(
16586 "The triangulation is trying to avoid unrefined islands "
16587 "during mesh refinement/coarsening, as you had requested "
16588 " by passing the appropriate 'smoothing flags' to the "
16589 "constructor of the triangulation. However, for objects "
16590 "of type parallel::distributed::Triangulation, control "
16591 "over which cells get refined rests with p4est, not the "
16592 "deal.II triangulation, and consequently it is not "
16593 "always possible to avoid unrefined islands in the mesh. "
16594 "Please remove the constructor argument to the triangulation "
16595 "object that requests mesh smoothing."));
16596#endif
16597
16598 // now we provide two algorithms. the first one is the standard
16599 // one, coming from the time, where only isotropic refinement was
16600 // possible. it simply counts the neighbors that are or will be
16601 // refined and compares to the number of other ones. the second
16602 // one does this check independently for each direction: if all
16603 // neighbors in one direction (normally two, at the boundary only
16604 // one) are refined, the current cell is flagged to be refined in
16605 // an according direction.
16606
16607 if (allow_anisotropic_smoothing == false)
16608 {
16609 // use first algorithm
16610 unsigned int refined_neighbors = 0, unrefined_neighbors = 0;
16611 for (const unsigned int face : GeometryInfo<dim>::face_indices())
16612 if (!cell->at_boundary(face))
16613 {
16614 if (face_will_be_refined_by_neighbor(cell, face))
16615 ++refined_neighbors;
16616 else
16617 ++unrefined_neighbors;
16618 }
16619
16620 if (unrefined_neighbors < refined_neighbors)
16621 {
16622 cell->clear_coarsen_flag();
16623 cell->set_refine_flag();
16624
16625 // ok, so now we have flagged this cell. if we know that
16626 // there were any unrefined neighbors at all, see if any
16627 // of those will have to be refined as well
16628 if (unrefined_neighbors > 0)
16629 for (const unsigned int face : GeometryInfo<dim>::face_indices())
16630 if (!cell->at_boundary(face) &&
16631 (face_will_be_refined_by_neighbor(cell, face) == false) &&
16632 (cell->neighbor(face)->has_children() == false) &&
16633 (cell->neighbor(face)->refine_flag_set() == false))
16634 possibly_refine_unrefined_island<dim, spacedim>(
16635 cell->neighbor(face), allow_anisotropic_smoothing);
16636 }
16637 }
16638 else
16639 {
16640 // variable to store the cell refine case needed to fulfill
16641 // all smoothing requirements
16642 RefinementCase<dim> smoothing_cell_refinement_case =
16644
16645 // use second algorithm, do the check individually for each
16646 // direction
16647 for (unsigned int face_pair = 0;
16648 face_pair < GeometryInfo<dim>::faces_per_cell / 2;
16649 ++face_pair)
16650 {
16651 // variable to store the cell refine case needed to refine
16652 // at the current face pair in the same way as the
16653 // neighbors do...
16654 RefinementCase<dim> directional_cell_refinement_case =
16656
16657 for (unsigned int face_index = 0; face_index < 2; ++face_index)
16658 {
16659 unsigned int face = 2 * face_pair + face_index;
16660 // variable to store the refine case (to come) of the
16661 // face under consideration
16662 RefinementCase<dim - 1> expected_face_ref_case =
16663 RefinementCase<dim - 1>::no_refinement;
16664
16665 if (cell->neighbor(face).state() == IteratorState::valid)
16666 face_will_be_refined_by_neighbor<dim, spacedim>(
16667 cell, face, expected_face_ref_case);
16668 // now extract which refine case would be necessary to
16669 // achieve the same face refinement. set the
16670 // intersection with other requirements for the same
16671 // direction.
16672
16673 // note: using the intersection is not an obvious
16674 // decision, we could also argue that it is more
16675 // natural to use the union. however, intersection is
16676 // the less aggressive tactic and favours a smaller
16677 // number of refined cells over an intensive
16678 // smoothing. this way we try not to lose too much of
16679 // the effort we put in anisotropic refinement
16680 // indicators due to overly aggressive smoothing...
16681 directional_cell_refinement_case =
16682 (directional_cell_refinement_case &
16685 expected_face_ref_case,
16686 face,
16687 cell->face_orientation(face),
16688 cell->face_flip(face),
16689 cell->face_rotation(face)));
16690 } // for both face indices
16691 // if both requirements sum up to something useful, add
16692 // this to the refine case for smoothing. note: if
16693 // directional_cell_refinement_case is isotropic still,
16694 // then something went wrong...
16695 Assert(directional_cell_refinement_case <
16698 smoothing_cell_refinement_case =
16699 smoothing_cell_refinement_case | directional_cell_refinement_case;
16700 } // for all face_pairs
16701 // no we collected contributions from all directions. combine
16702 // the new flags with the existing refine case, but only if
16703 // smoothing is required
16704 if (smoothing_cell_refinement_case)
16705 {
16706 cell->clear_coarsen_flag();
16707 cell->set_refine_flag(cell->refine_flag_set() |
16708 smoothing_cell_refinement_case);
16709 }
16710 }
16711 }
16712} // namespace
16713
16714#ifndef DOXYGEN
16715template <int dim, int spacedim>
16718{
16719 // save the flags to determine whether something was changed in the
16720 // course of this function
16721 const auto coarsen_flags_before = internal::extract_raw_coarsen_flags(levels);
16722 const auto refine_flags_before = internal::extract_raw_refine_flags(levels);
16723
16724 // save the flags at the outset of each loop. we do so in order to
16725 // find out whether something was changed in the present loop, in
16726 // which case we would have to re-run the loop. the other
16727 // possibility to find this out would be to set a flag
16728 // @p{something_changed} to true each time we change something.
16729 // however, sometimes one change in one of the parts of the loop is
16730 // undone by another one, so we might end up in an endless loop. we
16731 // could be tempted to break this loop at an arbitrary number of
16732 // runs, but that would not be a clean solution, since we would
16733 // either have to 1/ break the loop too early, in which case the
16734 // promise that a second call to this function immediately after the
16735 // first one does not change anything, would be broken, or 2/ we do
16736 // as many loops as there are levels. we know that information is
16737 // transported over one level in each run of the loop, so this is
16738 // enough. Unfortunately, each loop is rather expensive, so we chose
16739 // the way presented here
16740 auto coarsen_flags_before_loop = coarsen_flags_before;
16741 auto refine_flags_before_loop = refine_flags_before;
16742
16743 // now for what is done in each loop: we have to fulfill several
16744 // tasks at the same time, namely several mesh smoothing algorithms
16745 // and mesh regularization, by which we mean that the next mesh
16746 // fulfills several requirements such as no double refinement at
16747 // each face or line, etc.
16748 //
16749 // since doing these things at once seems almost impossible (in the
16750 // first year of this library, they were done in two functions, one
16751 // for refinement and one for coarsening, and most things within
16752 // these were done at once, so the code was rather impossible to
16753 // join into this, only, function), we do them one after each
16754 // other. the order in which we do them is such that the important
16755 // tasks, namely regularization, are done last and the least
16756 // important things are done the first. the following order is
16757 // chosen:
16758 //
16759 // 0/ Only if coarsest_level_1 or patch_level_1 is set: clear all
16760 // coarsen flags on level 1 to avoid level 0 cells being created
16761 // by coarsening. As coarsen flags will never be added, this can
16762 // be done once and for all before the actual loop starts.
16763 //
16764 // 1/ do not coarsen a cell if 'most of the neighbors' will be
16765 // refined after the step. This is to prevent occurrence of
16766 // unrefined islands.
16767 //
16768 // 2/ eliminate refined islands in the interior and at the
16769 // boundary. since they don't do much harm besides increasing the
16770 // number of degrees of freedom, doing this has a rather low
16771 // priority.
16772 //
16773 // 3/ limit the level difference of neighboring cells at each
16774 // vertex.
16775 //
16776 // 4/ eliminate unrefined islands. this has higher priority since
16777 // this diminishes the approximation properties not only of the
16778 // unrefined island, but also of the surrounding patch.
16779 //
16780 // 5/ ensure patch level 1. Then the triangulation consists of
16781 // patches, i.e. of cells that are refined once. It follows that
16782 // if at least one of the children of a cell is or will be
16783 // refined than all children need to be refined. This step only
16784 // sets refinement flags and does not set coarsening flags. If
16785 // the patch_level_1 flag is set, then
16786 // eliminate_unrefined_islands, eliminate_refined_inner_islands
16787 // and eliminate_refined_boundary_islands will be fulfilled
16788 // automatically and do not need to be enforced separately.
16789 //
16790 // 6/ take care of the requirement that no double refinement is done
16791 // at each face
16792 //
16793 // 7/ take care that no double refinement is done at each line in 3d
16794 // or higher dimensions.
16795 //
16796 // 8/ make sure that all children of each cell are either flagged
16797 // for coarsening or none of the children is
16798 //
16799 // For some of these steps, it is known that they interact. Namely,
16800 // it is not possible to guarantee that after step 6 another step 5
16801 // would have no effect; the same holds for the opposite order and
16802 // also when taking into account step 7. however, it is important to
16803 // guarantee that step five or six do not undo something that step 5
16804 // did, and step 7 not something of step 6, otherwise the
16805 // requirements will not be satisfied even if the loop
16806 // terminates. this is accomplished by the fact that steps 5 and 6
16807 // only *add* refinement flags and delete coarsening flags
16808 // (therefore, step 6 can't undo something that step 4 already did),
16809 // and step 7 only deletes coarsening flags, never adds some. step 7
16810 // needs also take care that it won't tag cells for refinement for
16811 // which some neighbors are more refined or will be refined.
16812
16813 //------------------------------------
16814 // STEP 0:
16815 // Only if coarsest_level_1 or patch_level_1 is set: clear all
16816 // coarsen flags on level 1 to avoid level 0 cells being created
16817 // by coarsening.
16818 if (((smooth_grid & coarsest_level_1) || (smooth_grid & patch_level_1)) &&
16819 n_levels() >= 2)
16820 {
16821 for (const auto &cell : active_cell_iterators_on_level(1))
16822 cell->clear_coarsen_flag();
16823 }
16824
16825 bool mesh_changed_in_this_loop = false;
16826 do
16827 {
16828 //------------------------------------
16829 // STEP 1:
16830 // do not coarsen a cell if 'most of the neighbors' will be
16831 // refined after the step. This is to prevent the occurrence
16832 // of unrefined islands. If patch_level_1 is set, this will
16833 // be automatically fulfilled.
16834 if (smooth_grid & do_not_produce_unrefined_islands &&
16835 !(smooth_grid & patch_level_1))
16836 {
16837 for (const auto &cell : cell_iterators())
16838 {
16839 // only do something if this
16840 // cell will be coarsened
16841 if (!cell->is_active() && cell_will_be_coarsened(cell))
16842 possibly_do_not_produce_unrefined_islands<dim, spacedim>(cell);
16843 }
16844 }
16845
16846
16847 //------------------------------------
16848 // STEP 2:
16849 // eliminate refined islands in the interior and at the
16850 // boundary. since they don't do much harm besides increasing
16851 // the number of degrees of freedom, doing this has a rather
16852 // low priority. If patch_level_1 is set, this will be
16853 // automatically fulfilled.
16854 //
16855 // there is one corner case to consider: if this is a
16856 // distributed triangulation, there may be refined islands on
16857 // the boundary of which we own only part (e.g. a single cell
16858 // in the corner of a domain). the rest of the island is
16859 // ghost cells and it *looks* like the area around it
16860 // (artificial cells) are coarser but this is only because
16861 // they may actually be equally fine on other
16862 // processors. it's hard to detect this case but we can do
16863 // the following: only set coarsen flags to remove this
16864 // refined island if all cells we want to set flags on are
16865 // locally owned
16866 if (smooth_grid & (eliminate_refined_inner_islands |
16867 eliminate_refined_boundary_islands) &&
16868 !(smooth_grid & patch_level_1))
16869 {
16870 for (const auto &cell : cell_iterators())
16871 if (!cell->is_active() ||
16872 (cell->is_active() && cell->refine_flag_set() &&
16873 cell->is_locally_owned()))
16874 {
16875 // check whether all children are active, i.e. not
16876 // refined themselves. This is a precondition that the
16877 // children may be coarsened away. If the cell is only
16878 // flagged for refinement, then all future children
16879 // will be active
16880 bool all_children_active = true;
16881 if (!cell->is_active())
16882 for (unsigned int c = 0; c < cell->n_children(); ++c)
16883 if (!cell->child(c)->is_active() ||
16884 cell->child(c)->is_ghost() ||
16885 cell->child(c)->is_artificial())
16886 {
16887 all_children_active = false;
16888 break;
16889 }
16890
16891 if (all_children_active)
16892 {
16893 // count number of refined and unrefined neighbors
16894 // of cell. neighbors on lower levels are counted
16895 // as unrefined since they can only get to the
16896 // same level as this cell by the next refinement
16897 // cycle
16898 unsigned int unrefined_neighbors = 0, total_neighbors = 0;
16899
16900 // Keep track if this cell is at a periodic
16901 // boundary or not. TODO: We do not currently run
16902 // the algorithm for inner islands at a periodic
16903 // boundary (remains to be implemented), but we
16904 // also don't want to consider them
16905 // boundary_island cells as this can interfere
16906 // with 2:1 refinement across periodic faces.
16907 // Instead: just ignore those cells for this
16908 // smoothing operation below.
16909 bool at_periodic_boundary = false;
16910
16911 for (const unsigned int n :
16912 GeometryInfo<dim>::face_indices())
16913 {
16914 const cell_iterator neighbor = cell->neighbor(n);
16915 if (neighbor.state() == IteratorState::valid)
16916 {
16917 ++total_neighbors;
16918
16919 if (!face_will_be_refined_by_neighbor(cell, n))
16920 ++unrefined_neighbors;
16921 }
16922 else if (cell->has_periodic_neighbor(n))
16923 {
16924 ++total_neighbors;
16925 at_periodic_boundary = true;
16926 }
16927 }
16928
16929 // if all neighbors unrefined: mark this cell for
16930 // coarsening or don't refine if marked for that
16931 //
16932 // also do the distinction between the two
16933 // versions of the eliminate_refined_*_islands
16934 // flag
16935 //
16936 // the last check is whether there are any
16937 // neighbors at all. if not so, then we are (e.g.)
16938 // on the coarsest grid with one cell, for which,
16939 // of course, we do not remove the refine flag.
16940 if ((unrefined_neighbors == total_neighbors) &&
16941 ((!cell->at_boundary() &&
16942 (smooth_grid & eliminate_refined_inner_islands)) ||
16943 (cell->at_boundary() && !at_periodic_boundary &&
16944 (smooth_grid &
16945 eliminate_refined_boundary_islands))) &&
16946 (total_neighbors != 0))
16947 {
16948 if (!cell->is_active())
16949 for (unsigned int c = 0; c < cell->n_children(); ++c)
16950 {
16951 cell->child(c)->clear_refine_flag();
16952 cell->child(c)->set_coarsen_flag();
16953 }
16954 else
16955 cell->clear_refine_flag();
16956 }
16957 }
16958 }
16959 }
16960
16961 //------------------------------------
16962 // STEP 3:
16963 // limit the level difference of neighboring cells at each
16964 // vertex.
16965 //
16966 // in case of anisotropic refinement this does not make
16967 // sense. as soon as one cell is anisotropically refined, an
16968 // Assertion is thrown. therefore we can ignore this problem
16969 // later on
16970 if (smooth_grid & limit_level_difference_at_vertices)
16971 {
16972 Assert(!anisotropic_refinement,
16973 ExcMessage("In case of anisotropic refinement the "
16974 "limit_level_difference_at_vertices flag for "
16975 "mesh smoothing must not be set!"));
16976
16977 // store highest level one of the cells adjacent to a vertex
16978 // belongs to
16979 std::vector<int> vertex_level(vertices.size(), 0);
16980 for (const auto &cell : active_cell_iterators())
16981 {
16982 if (cell->refine_flag_set())
16983 for (const unsigned int vertex :
16985 vertex_level[cell->vertex_index(vertex)] =
16986 std::max(vertex_level[cell->vertex_index(vertex)],
16987 cell->level() + 1);
16988 else if (!cell->coarsen_flag_set())
16989 for (const unsigned int vertex :
16991 vertex_level[cell->vertex_index(vertex)] =
16992 std::max(vertex_level[cell->vertex_index(vertex)],
16993 cell->level());
16994 else
16995 {
16996 // if coarsen flag is set then tentatively assume
16997 // that the cell will be coarsened. this isn't
16998 // always true (the coarsen flag could be removed
16999 // again) and so we may make an error here
17000 Assert(cell->coarsen_flag_set(), ExcInternalError());
17001 for (const unsigned int vertex :
17003 vertex_level[cell->vertex_index(vertex)] =
17004 std::max(vertex_level[cell->vertex_index(vertex)],
17005 cell->level() - 1);
17006 }
17007 }
17008
17009
17010 // loop over all cells in reverse order. do so because we
17011 // can then update the vertex levels on the adjacent
17012 // vertices and maybe already flag additional cells in this
17013 // loop
17014 //
17015 // note that not only may we have to add additional
17016 // refinement flags, but we will also have to remove
17017 // coarsening flags on cells adjacent to vertices that will
17018 // see refinement
17019 for (active_cell_iterator cell = last_active(); cell != end(); --cell)
17020 if (cell->refine_flag_set() == false)
17021 {
17022 for (const unsigned int vertex :
17024 if (vertex_level[cell->vertex_index(vertex)] >=
17025 cell->level() + 1)
17026 {
17027 // remove coarsen flag...
17028 cell->clear_coarsen_flag();
17029
17030 // ...and if necessary also refine the current
17031 // cell, at the same time updating the level
17032 // information about vertices
17033 if (vertex_level[cell->vertex_index(vertex)] >
17034 cell->level() + 1)
17035 {
17036 cell->set_refine_flag();
17037
17038 for (const unsigned int v :
17040 vertex_level[cell->vertex_index(v)] =
17041 std::max(vertex_level[cell->vertex_index(v)],
17042 cell->level() + 1);
17043 }
17044
17045 // continue and see whether we may, for example,
17046 // go into the inner'if'
17047 // above based on a
17048 // different vertex
17049 }
17050 }
17051 }
17052
17053 //-----------------------------------
17054 // STEP 4:
17055 // eliminate unrefined islands. this has higher priority
17056 // since this diminishes the approximation properties not
17057 // only of the unrefined island, but also of the surrounding
17058 // patch.
17059 //
17060 // do the loop from finest to coarsest cells since we may
17061 // trigger a cascade by marking cells for refinement which
17062 // may trigger more cells further down below
17063 if (smooth_grid & eliminate_unrefined_islands)
17064 {
17065 for (active_cell_iterator cell = last_active(); cell != end(); --cell)
17066 // only do something if cell is not already flagged for
17067 // (isotropic) refinement
17068 if (cell->refine_flag_set() !=
17070 possibly_refine_unrefined_island<dim, spacedim>(
17071 cell, (smooth_grid & allow_anisotropic_smoothing) != 0);
17072 }
17073
17074 //-------------------------------
17075 // STEP 5:
17076 // ensure patch level 1.
17077 //
17078 // Introduce some terminology:
17079 // - a cell that is refined
17080 // once is a patch of
17081 // level 1 simply called patch.
17082 // - a cell that is globally
17083 // refined twice is called
17084 // a patch of level 2.
17085 // - patch level n says that
17086 // the triangulation consists
17087 // of patches of level n.
17088 // This makes sense only
17089 // if the grid is already at
17090 // least n times globally
17091 // refined.
17092 //
17093 // E.g. from patch level 1 follows: if at least one of the
17094 // children of a cell is or will be refined than enforce all
17095 // children to be refined.
17096
17097 // This step 4 only sets refinement flags and does not set
17098 // coarsening flags.
17099 if (smooth_grid & patch_level_1)
17100 {
17101 // An important assumption (A) is that before calling this
17102 // function the grid was already of patch level 1.
17103
17104 // loop over all cells whose children are all active. (By
17105 // assumption (A) either all or none of the children are
17106 // active). If the refine flag of at least one of the
17107 // children is set then set_refine_flag and
17108 // clear_coarsen_flag of all children.
17109 for (const auto &cell : cell_iterators())
17110 if (!cell->is_active())
17111 {
17112 // ensure the invariant. we can then check whether all
17113 // of its children are further refined or not by
17114 // simply looking at the first child
17115 Assert(cell_is_patch_level_1(cell), ExcInternalError());
17116 if (cell->child(0)->has_children() == true)
17117 continue;
17118
17119 // cell is found to be a patch. combine the refine
17120 // cases of all children
17121 RefinementCase<dim> combined_ref_case =
17123 for (unsigned int i = 0; i < cell->n_children(); ++i)
17124 combined_ref_case =
17125 combined_ref_case | cell->child(i)->refine_flag_set();
17126 if (combined_ref_case != RefinementCase<dim>::no_refinement)
17127 for (unsigned int i = 0; i < cell->n_children(); ++i)
17128 {
17129 cell_iterator child = cell->child(i);
17130
17131 child->clear_coarsen_flag();
17132 child->set_refine_flag(combined_ref_case);
17133 }
17134 }
17135
17136 // The code above dealt with the case where we may get a
17137 // non-patch_level_1 mesh from refinement. Now also deal
17138 // with the case where we could get such a mesh by
17139 // coarsening. Coarsen the children (and remove the
17140 // grandchildren) only if all cell->grandchild(i)
17141 // ->coarsen_flag_set() are set.
17142 //
17143 // for a case where this is a bit tricky, take a look at the
17144 // mesh_smoothing_0[12] testcases
17145 for (const auto &cell : cell_iterators())
17146 {
17147 // check if this cell has active grandchildren. note
17148 // that we know that it is patch_level_1, i.e. if one of
17149 // its children is active then so are all, and it isn't
17150 // going to have any grandchildren at all:
17151 if (cell->is_active() || cell->child(0)->is_active())
17152 continue;
17153
17154 // cell is not active, and so are none of its
17155 // children. check the grandchildren. note that the
17156 // children are also patch_level_1, and so we only ever
17157 // need to check their first child
17158 const unsigned int n_children = cell->n_children();
17159 bool has_active_grandchildren = false;
17160
17161 for (unsigned int i = 0; i < n_children; ++i)
17162 if (cell->child(i)->child(0)->is_active())
17163 {
17164 has_active_grandchildren = true;
17165 break;
17166 }
17167
17168 if (has_active_grandchildren == false)
17169 continue;
17170
17171
17172 // ok, there are active grandchildren. see if either all
17173 // or none of them are flagged for coarsening
17174 unsigned int n_grandchildren = 0;
17175
17176 // count all coarsen flags of the grandchildren.
17177 unsigned int n_coarsen_flags = 0;
17178
17179 // cell is not a patch (of level 1) as it has a
17180 // grandchild. Is cell a patch of level 2?? Therefore:
17181 // find out whether all cell->child(i) are patches
17182 for (unsigned int c = 0; c < n_children; ++c)
17183 {
17184 // get at the child. by assumption (A), and the
17185 // check by which we got here, the child is not
17186 // active
17187 cell_iterator child = cell->child(c);
17188
17189 const unsigned int nn_children = child->n_children();
17190 n_grandchildren += nn_children;
17191
17192 // if child is found to be a patch of active cells
17193 // itself, then add up how many of its children are
17194 // supposed to be coarsened
17195 if (child->child(0)->is_active())
17196 for (unsigned int cc = 0; cc < nn_children; ++cc)
17197 if (child->child(cc)->coarsen_flag_set())
17198 ++n_coarsen_flags;
17199 }
17200
17201 // if not all grandchildren are supposed to be coarsened
17202 // (e.g. because some simply don't have the flag set, or
17203 // because they are not active and therefore cannot
17204 // carry the flag), then remove the coarsen flag from
17205 // all of the active grandchildren. note that there may
17206 // be coarsen flags on the grandgrandchildren -- we
17207 // don't clear them here, but we'll get to them in later
17208 // iterations if necessary
17209 //
17210 // there is nothing we have to do if no coarsen flags
17211 // have been set at all
17212 if ((n_coarsen_flags != n_grandchildren) && (n_coarsen_flags > 0))
17213 for (unsigned int c = 0; c < n_children; ++c)
17214 {
17215 const cell_iterator child = cell->child(c);
17216 if (child->child(0)->is_active())
17217 for (unsigned int cc = 0; cc < child->n_children(); ++cc)
17218 child->child(cc)->clear_coarsen_flag();
17219 }
17220 }
17221 }
17222
17223 //--------------------------------
17224 //
17225 // at the boundary we could end up with cells with negative
17226 // volume or at least with a part, that is negative, if the
17227 // cell is refined anisotropically. we have to check, whether
17228 // that can happen
17229 this->policy->prevent_distorted_boundary_cells(*this);
17230
17231 //-------------------------------
17232 // STEP 6:
17233 // take care of the requirement that no
17234 // double refinement is done at each face
17235 //
17236 // in case of anisotropic refinement it is only likely, but
17237 // not sure, that the cells, which are more refined along a
17238 // certain face common to two cells are on a higher
17239 // level. therefore we cannot be sure, that the requirement
17240 // of no double refinement is fulfilled after a single pass
17241 // of the following actions. We could just wait for the next
17242 // global loop. when this function terminates, the
17243 // requirement will be fulfilled. However, it might be faster
17244 // to insert an inner loop here.
17245 bool changed = true;
17246 while (changed)
17247 {
17248 changed = false;
17249 active_cell_iterator cell = last_active(), endc = end();
17250
17251 for (; cell != endc; --cell)
17252 if (cell->refine_flag_set())
17253 {
17254 // loop over neighbors of cell
17255 for (const auto i : cell->face_indices())
17256 {
17257 // only do something if the face is not at the
17258 // boundary and if the face will be refined with
17259 // the RefineCase currently flagged for
17260 const bool has_periodic_neighbor =
17261 cell->has_periodic_neighbor(i);
17262 const bool has_neighbor_or_periodic_neighbor =
17263 !cell->at_boundary(i) || has_periodic_neighbor;
17264 if (has_neighbor_or_periodic_neighbor &&
17266 cell->refine_flag_set(), i) !=
17268 {
17269 // 1) if the neighbor has children: nothing to
17270 // worry about. 2) if the neighbor is active
17271 // and a coarser one, ensure, that its
17272 // refine_flag is set 3) if the neighbor is
17273 // active and as refined along the face as our
17274 // current cell, make sure, that no
17275 // coarsen_flag is set. if we remove the
17276 // coarsen flag of our neighbor,
17277 // fix_coarsen_flags() makes sure, that the
17278 // mother cell will not be coarsened
17279 if (cell->neighbor_or_periodic_neighbor(i)->is_active())
17280 {
17281 if ((!has_periodic_neighbor &&
17282 cell->neighbor_is_coarser(i)) ||
17283 (has_periodic_neighbor &&
17284 cell->periodic_neighbor_is_coarser(i)))
17285 {
17286 if (cell->neighbor_or_periodic_neighbor(i)
17287 ->coarsen_flag_set())
17288 cell->neighbor_or_periodic_neighbor(i)
17289 ->clear_coarsen_flag();
17290 // we'll set the refine flag for this
17291 // neighbor below. we note, that we
17292 // have changed something by setting
17293 // the changed flag to true. We do not
17294 // need to do so, if we just removed
17295 // the coarsen flag, as the changed
17296 // flag only indicates the need to
17297 // re-run the inner loop. however, we
17298 // only loop over cells flagged for
17299 // refinement here, so nothing to
17300 // worry about if we remove coarsen
17301 // flags
17302
17303 if (dim == 2)
17304 {
17305 if (smooth_grid &
17306 allow_anisotropic_smoothing)
17307 changed =
17308 has_periodic_neighbor ?
17309 cell->periodic_neighbor(i)
17310 ->flag_for_face_refinement(
17311 cell
17312 ->periodic_neighbor_of_coarser_periodic_neighbor(
17313 i)
17314 .first,
17316 cell->neighbor(i)
17317 ->flag_for_face_refinement(
17318 cell
17319 ->neighbor_of_coarser_neighbor(
17320 i)
17321 .first,
17323 else
17324 {
17325 if (!cell
17326 ->neighbor_or_periodic_neighbor(
17327 i)
17328 ->refine_flag_set())
17329 changed = true;
17330 cell->neighbor_or_periodic_neighbor(i)
17331 ->set_refine_flag();
17332 }
17333 }
17334 else // i.e. if (dim==3)
17335 {
17336 // ugly situations might arise here,
17337 // consider the following situation, which
17338 // shows neighboring cells at the common
17339 // face, where the upper right element is
17340 // coarser at the given face. Now the upper
17341 // child element of the lower left wants to
17342 // refine according to cut_z, such that
17343 // there is a 'horizontal' refinement of the
17344 // face marked with #####
17345 //
17346 // / /
17347 // / /
17348 // *---------------*
17349 // | |
17350 // | |
17351 // | |
17352 // | |
17353 // | |
17354 // | | /
17355 // | |/
17356 // *---------------*
17357 //
17358 //
17359 // *---------------*
17360 // /| /|
17361 // / | ##### / |
17362 // | |
17363 // *---------------*
17364 // /| /|
17365 // / | / |
17366 // | |
17367 // *---------------*
17368 // / /
17369 // / /
17370 //
17371 // this introduces too many hanging nodes
17372 // and the neighboring (coarser) cell (upper
17373 // right) has to be refined. If it is only
17374 // refined according to cut_z, then
17375 // everything is ok:
17376 //
17377 // / /
17378 // / /
17379 // *---------------*
17380 // | |
17381 // | | /
17382 // | |/
17383 // *---------------*
17384 // | |
17385 // | | /
17386 // | |/
17387 // *---------------*
17388 //
17389 //
17390 // *---------------*
17391 // /| /|
17392 // / *---------------*
17393 // /| /|
17394 // *---------------*
17395 // /| /|
17396 // / | / |
17397 // | |
17398 // *---------------*
17399 // / /
17400 // / /
17401 //
17402 // if however the cell wants to refine
17403 // itself in an other way, or if we disallow
17404 // anisotropic smoothing, then simply
17405 // refining the neighbor isotropically is
17406 // not going to work, since this introduces
17407 // a refinement of face ##### with both
17408 // cut_x and cut_y, which is not possible:
17409 //
17410 // / / /
17411 // / / /
17412 // *-------*-------*
17413 // | | |
17414 // | | | /
17415 // | | |/
17416 // *-------*-------*
17417 // | | |
17418 // | | | /
17419 // | | |/
17420 // *-------*-------*
17421 //
17422 //
17423 // *---------------*
17424 // /| /|
17425 // / *---------------*
17426 // /| /|
17427 // *---------------*
17428 // /| /|
17429 // / | / |
17430 // | |
17431 // *---------------*
17432 // / /
17433 // / /
17434 //
17435 // thus, in this case we also need to refine
17436 // our current cell in the new direction:
17437 //
17438 // / / /
17439 // / / /
17440 // *-------*-------*
17441 // | | |
17442 // | | | /
17443 // | | |/
17444 // *-------*-------*
17445 // | | |
17446 // | | | /
17447 // | | |/
17448 // *-------*-------*
17449 //
17450 //
17451 // *-------*-------*
17452 // /| /| /|
17453 // / *-------*-------*
17454 // /| /| /|
17455 // *-------*-------*
17456 // /| / /|
17457 // / | / |
17458 // | |
17459 // *---------------*
17460 // / /
17461 // / /
17462
17463 std::pair<unsigned int, unsigned int>
17464 nb_indices =
17465 has_periodic_neighbor ?
17466 cell
17467 ->periodic_neighbor_of_coarser_periodic_neighbor(
17468 i) :
17469 cell->neighbor_of_coarser_neighbor(i);
17470 unsigned int refined_along_x = 0,
17471 refined_along_y = 0,
17472 to_be_refined_along_x = 0,
17473 to_be_refined_along_y = 0;
17474
17475 const int this_face_index =
17476 cell->face_index(i);
17477
17478 // step 1: detect, along which axis the face
17479 // is currently refined
17480
17481 // first, we need an iterator pointing to
17482 // the parent face. This requires a slight
17483 // detour in case the neighbor is behind a
17484 // periodic face.
17485 const auto parent_face = [&]() {
17486 if (has_periodic_neighbor)
17487 {
17488 const auto neighbor =
17489 cell->periodic_neighbor(i);
17490 const auto parent_face_no =
17491 neighbor
17492 ->periodic_neighbor_of_periodic_neighbor(
17493 nb_indices.first);
17494 auto parent =
17495 neighbor->periodic_neighbor(
17496 nb_indices.first);
17497 return parent->face(parent_face_no);
17498 }
17499 else
17500 return cell->neighbor(i)->face(
17501 nb_indices.first);
17502 }();
17503
17504 if ((this_face_index ==
17505 parent_face->child_index(0)) ||
17506 (this_face_index ==
17507 parent_face->child_index(1)))
17508 {
17509 // this might be an
17510 // anisotropic child. get the
17511 // face refine case of the
17512 // neighbors face and count
17513 // refinements in x and y
17514 // direction.
17515 RefinementCase<dim - 1> frc =
17516 parent_face->refinement_case();
17518 ++refined_along_x;
17520 ++refined_along_y;
17521 }
17522 else
17523 // this has to be an isotropic
17524 // child
17525 {
17526 ++refined_along_x;
17527 ++refined_along_y;
17528 }
17529 // step 2: detect, along which axis the face
17530 // has to be refined given the current
17531 // refine flag
17532 RefinementCase<dim - 1> flagged_frc =
17534 cell->refine_flag_set(),
17535 i,
17536 cell->face_orientation(i),
17537 cell->face_flip(i),
17538 cell->face_rotation(i));
17539 if (flagged_frc &
17541 ++to_be_refined_along_x;
17542 if (flagged_frc &
17544 ++to_be_refined_along_y;
17545
17546 // step 3: set the refine flag of the
17547 // (coarser and active) neighbor.
17548 if ((smooth_grid &
17549 allow_anisotropic_smoothing) ||
17550 cell->neighbor_or_periodic_neighbor(i)
17551 ->refine_flag_set())
17552 {
17553 if (refined_along_x +
17554 to_be_refined_along_x >
17555 1)
17556 changed |=
17557 cell
17558 ->neighbor_or_periodic_neighbor(i)
17559 ->flag_for_face_refinement(
17560 nb_indices.first,
17561 RefinementCase<dim -
17562 1>::cut_axis(0));
17563 if (refined_along_y +
17564 to_be_refined_along_y >
17565 1)
17566 changed |=
17567 cell
17568 ->neighbor_or_periodic_neighbor(i)
17569 ->flag_for_face_refinement(
17570 nb_indices.first,
17571 RefinementCase<dim -
17572 1>::cut_axis(1));
17573 }
17574 else
17575 {
17576 if (cell
17577 ->neighbor_or_periodic_neighbor(i)
17578 ->refine_flag_set() !=
17581 changed = true;
17582 cell->neighbor_or_periodic_neighbor(i)
17583 ->set_refine_flag();
17584 }
17585
17586 // step 4: if necessary (see above) add to
17587 // the refine flag of the current cell
17588 cell_iterator nb =
17589 cell->neighbor_or_periodic_neighbor(i);
17590 RefinementCase<dim - 1> nb_frc =
17592 nb->refine_flag_set(),
17593 nb_indices.first,
17594 nb->face_orientation(nb_indices.first),
17595 nb->face_flip(nb_indices.first),
17596 nb->face_rotation(nb_indices.first));
17597 if ((nb_frc & RefinementCase<dim>::cut_x) &&
17598 !((refined_along_x != 0u) ||
17599 (to_be_refined_along_x != 0u)))
17600 changed |= cell->flag_for_face_refinement(
17601 i,
17603 if ((nb_frc & RefinementCase<dim>::cut_y) &&
17604 !((refined_along_y != 0u) ||
17605 (to_be_refined_along_y != 0u)))
17606 changed |= cell->flag_for_face_refinement(
17607 i,
17609 }
17610 } // if neighbor is coarser
17611 else // -> now the neighbor is not coarser
17612 {
17613 cell->neighbor_or_periodic_neighbor(i)
17614 ->clear_coarsen_flag();
17615 const unsigned int nb_nb =
17616 has_periodic_neighbor ?
17617 cell
17618 ->periodic_neighbor_of_periodic_neighbor(
17619 i) :
17620 cell->neighbor_of_neighbor(i);
17621 const cell_iterator neighbor =
17622 cell->neighbor_or_periodic_neighbor(i);
17623 RefinementCase<dim - 1> face_ref_case =
17625 neighbor->refine_flag_set(),
17626 nb_nb,
17627 neighbor->face_orientation(nb_nb),
17628 neighbor->face_flip(nb_nb),
17629 neighbor->face_rotation(nb_nb));
17630 RefinementCase<dim - 1> needed_face_ref_case =
17632 cell->refine_flag_set(),
17633 i,
17634 cell->face_orientation(i),
17635 cell->face_flip(i),
17636 cell->face_rotation(i));
17637 // if the neighbor wants to refine the
17638 // face with cut_x and we want cut_y
17639 // or vice versa, we have to refine
17640 // isotropically at the given face
17641 if ((face_ref_case ==
17643 needed_face_ref_case ==
17645 (face_ref_case ==
17647 needed_face_ref_case ==
17649 {
17650 changed = cell->flag_for_face_refinement(
17651 i, face_ref_case);
17652 neighbor->flag_for_face_refinement(
17653 nb_nb, needed_face_ref_case);
17654 }
17655 }
17656 }
17657 else //-> the neighbor is not active
17658 {
17659 RefinementCase<dim - 1>
17660 face_ref_case = cell->face(i)->refinement_case(),
17661 needed_face_ref_case =
17663 cell->refine_flag_set(),
17664 i,
17665 cell->face_orientation(i),
17666 cell->face_flip(i),
17667 cell->face_rotation(i));
17668 // if the face is refined with cut_x and
17669 // we want cut_y or vice versa, we have to
17670 // refine isotropically at the given face
17671 if ((face_ref_case == RefinementCase<dim>::cut_x &&
17672 needed_face_ref_case ==
17674 (face_ref_case == RefinementCase<dim>::cut_y &&
17675 needed_face_ref_case ==
17677 changed =
17678 cell->flag_for_face_refinement(i,
17679 face_ref_case);
17680 }
17681 }
17682 }
17683 }
17684 }
17685
17686 //------------------------------------
17687 // STEP 7:
17688 // take care that no double refinement is done at each line in 3d or
17689 // higher dimensions.
17690 this->policy->prepare_refinement_dim_dependent(*this);
17691
17692 //------------------------------------
17693 // STEP 8:
17694 // make sure that all children of each cell are either flagged for
17695 // coarsening or none of the children is
17696 fix_coarsen_flags();
17697
17698 // get the refinement and coarsening flags
17699 auto coarsen_flags_after_loop =
17700 internal::extract_raw_coarsen_flags(levels);
17701 auto refine_flags_after_loop = internal::extract_raw_refine_flags(levels);
17702
17703 // find out whether something was changed in this loop
17704 mesh_changed_in_this_loop =
17705 ((coarsen_flags_before_loop != coarsen_flags_after_loop) ||
17706 (refine_flags_before_loop != refine_flags_after_loop));
17707
17708 // set the flags for the next loop already
17709 coarsen_flags_before_loop.swap(coarsen_flags_after_loop);
17710 refine_flags_before_loop.swap(refine_flags_after_loop);
17711 }
17712 while (mesh_changed_in_this_loop);
17713
17714
17715 // find out whether something was really changed in this
17716 // function. Note that @p{..._flags_before_loop} represents the state
17717 // after the last loop, i.e., the present state
17718 return ((coarsen_flags_before != coarsen_flags_before_loop) ||
17719 (refine_flags_before != refine_flags_before_loop));
17720}
17721
17722
17723
17724template <int dim, int spacedim>
17727 const unsigned int magic_number1,
17728 const std::vector<bool> &v,
17729 const unsigned int magic_number2,
17730 std::ostream &out)
17731{
17732 const unsigned int N = v.size();
17733 unsigned char *flags = new unsigned char[N / 8 + 1];
17734 for (unsigned int i = 0; i < N / 8 + 1; ++i)
17735 flags[i] = 0;
17736
17737 for (unsigned int position = 0; position < N; ++position)
17738 flags[position / 8] |= (v[position] ? (1 << (position % 8)) : 0);
17739
17740 AssertThrow(out.fail() == false, ExcIO());
17741
17742 // format:
17743 // 0. magic number
17744 // 1. number of flags
17745 // 2. the flags
17746 // 3. magic number
17747 out << magic_number1 << ' ' << N << std::endl;
17748 for (unsigned int i = 0; i < N / 8 + 1; ++i)
17749 out << static_cast<unsigned int>(flags[i]) << ' ';
17750
17751 out << std::endl << magic_number2 << std::endl;
17752
17753 delete[] flags;
17754
17755 AssertThrow(out.fail() == false, ExcIO());
17756}
17757
17758
17759template <int dim, int spacedim>
17762 const unsigned int magic_number1,
17763 std::vector<bool> &v,
17764 const unsigned int magic_number2,
17765 std::istream &in)
17766{
17767 AssertThrow(in.fail() == false, ExcIO());
17768
17769 unsigned int magic_number;
17770 in >> magic_number;
17771 AssertThrow(magic_number == magic_number1, ExcGridReadError());
17772
17773 unsigned int N;
17774 in >> N;
17775 v.resize(N);
17776
17777 unsigned char *flags = new unsigned char[N / 8 + 1];
17778 unsigned short int tmp;
17779 for (unsigned int i = 0; i < N / 8 + 1; ++i)
17780 {
17781 in >> tmp;
17782 flags[i] = tmp;
17783 }
17784
17785 for (unsigned int position = 0; position != N; ++position)
17786 v[position] = ((flags[position / 8] & (1 << (position % 8))) != 0);
17787
17788 in >> magic_number;
17789 AssertThrow(magic_number == magic_number2, ExcGridReadError());
17790
17791 delete[] flags;
17792
17793 AssertThrow(in.fail() == false, ExcIO());
17794}
17795
17796
17797
17798template <int dim, int spacedim>
17801{
17802 std::size_t mem = 0;
17803 mem += sizeof(MeshSmoothing);
17804 mem += MemoryConsumption::memory_consumption(reference_cells);
17805 mem += MemoryConsumption::memory_consumption(periodic_face_pairs_level_0);
17807 for (const auto &level : levels)
17810 mem += MemoryConsumption::memory_consumption(vertices_used);
17811 mem += sizeof(manifolds);
17812 mem += sizeof(smooth_grid);
17813 mem += MemoryConsumption::memory_consumption(number_cache);
17814 mem += sizeof(faces);
17815 if (faces)
17817
17818 return mem;
17819}
17820
17821
17822
17823template <int dim, int spacedim>
17826 default;
17827
17828#endif
17829
17830// explicit instantiations
17831#include "tria.inst"
17832
ArrayView< std::remove_reference_t< typename std::iterator_traits< Iterator >::reference >, MemorySpaceType > make_array_view(const Iterator begin, const Iterator end)
Definition array_view.h:949
CellStatus
Definition cell_status.h:31
@ cell_will_be_refined
@ children_will_be_coarsened
types::coarse_cell_id get_coarse_cell_id() const
Definition cell_id.h:393
virtual std::unique_ptr< Manifold< dim, spacedim > > clone() const =0
Definition point.h:111
numbers::NumberTraits< Number >::real_type distance(const Point< dim, Number > &p) const
unsigned int face_to_cell_vertices(const unsigned int face, const unsigned int vertex, const unsigned char face_orientation) const
static constexpr unsigned char default_combined_face_orientation()
unsigned int standard_to_real_face_vertex(const unsigned int vertex, const unsigned int face, const unsigned char face_orientation) const
static constexpr unsigned char reversed_combined_line_orientation()
unsigned int n_lines() const
unsigned char get_combined_orientation(const ArrayView< const T > &vertices_0, const ArrayView< const T > &vertices_1) const
Subscriptor & operator=(const Subscriptor &)
constexpr void clear()
void join() const
IteratorState::IteratorStates state() const
virtual void add_periodicity(const std::vector< GridTools::PeriodicFacePair< cell_iterator > > &)
virtual types::global_cell_index n_global_active_cells() const
quad_iterator begin_quad(const unsigned int level=0) const
typename IteratorSelector::raw_line_iterator raw_line_iterator
Definition tria.h:4096
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:4472
virtual void clear()
bool anisotropic_refinement
Definition tria.h:4484
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:4542
void save_user_pointers_quad(std::vector< void * > &v) const
void save_user_flags_hex(std::ostream &out) const
void clear_user_flags_quad()
unsigned int n_faces() const
active_hex_iterator begin_active_hex(const unsigned int level=0) const
static void read_bool_vector(const unsigned int magic_number1, std::vector< bool > &v, const unsigned int magic_number2, std::istream &in)
virtual std::weak_ptr< const Utilities::MPI::Partitioner > global_active_cell_index_partitioner() const
bool all_reference_cells_are_hyper_cube() const
void load_user_flags_line(std::istream &in)
void clear_user_data()
raw_hex_iterator begin_raw_hex(const unsigned int level=0) const
const std::map< std::pair< cell_iterator, unsigned int >, std::pair< std::pair< cell_iterator, unsigned int >, unsigned char > > & get_periodic_face_map() const
void save_user_flags_line(std::ostream &out) const
active_cell_iterator last_active() const
void save(Archive &ar, const unsigned int version) const
void reset_global_cell_indices()
face_iterator end_face() const
void reset_active_cell_indices()
cell_iterator create_cell_iterator(const CellId &cell_id) const
cell_iterator begin(const unsigned int level=0) const
void fix_coarsen_flags()
void save_user_pointers_line(std::vector< void * > &v) const
void load_refine_flags(std::istream &in)
void save_user_indices_line(std::vector< unsigned int > &v) const
raw_cell_iterator begin_raw(const unsigned int level=0) const
unsigned int n_lines() const
virtual void set_mesh_smoothing(const MeshSmoothing mesh_smoothing)
unsigned int n_raw_lines() const
virtual std::size_t memory_consumption() const
std::vector< Point< spacedim > > vertices
Definition tria.h:4467
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:4491
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:4519
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:4012
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)
const std::vector< Point< spacedim > > & get_vertices() const
void load_user_pointers_quad(const std::vector< void * > &v)
std::unique_ptr<::internal::TriangulationImplementation::TriaFaces > faces
Definition tria.h:4461
unsigned int n_used_vertices() const
void reset_cell_vertex_indices_cache()
unsigned int n_active_lines() const
unsigned int n_levels() 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:4097
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:4502
void save_attached_data(const unsigned int global_first_cell, const unsigned int global_num_cells, const std::string &file_basename) const
void save_user_indices_hex(std::vector< unsigned int > &v) const
DistortedCellList execute_refinement()
void update_cell_relations()
active_line_iterator begin_active_line(const unsigned int level=0) const
void save_user_indices_quad(std::vector< unsigned int > &v) const
void load_user_pointers_hex(const std::vector< void * > &v)
cell_iterator end() const
virtual bool has_hanging_nodes() const
std::vector< GridTools::PeriodicFacePair< cell_iterator > > periodic_face_pairs_level_0
Definition tria.h:4073
unsigned int n_raw_cells(const unsigned int level) const
bool contains_cell(const CellId &cell_id) const
void load_attached_data(const unsigned int global_first_cell, const unsigned int global_num_cells, const unsigned int local_num_cells, const std::string &file_basename, const unsigned int n_attached_deserialize_fixed, const unsigned int n_attached_deserialize_variable)
void load_coarsen_flags(std::istream &out)
quad_iterator end_quad() const
line_iterator begin_line(const unsigned int level=0) const
unsigned int max_adjacent_cells() const
vertex_iterator begin_vertex() const
void clear_user_flags()
unsigned int n_hexs() const
vertex_iterator end_vertex() const
bool vertex_used(const unsigned int index) 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:4098
MeshSmoothing smooth_grid
Definition tria.h:4006
void save_refine_flags(std::ostream &out) const
std::unique_ptr< ::internal::TriangulationImplementation::Policy< dim, spacedim > > policy
Definition tria.h:4064
Triangulation< dim, spacedim > & get_triangulation()
void save_user_flags_quad(std::ostream &out) const
Signals signals
Definition tria.h:2513
internal::CellAttachedDataSerializer< dim, spacedim > data_serializer
Definition tria.h:3916
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:4453
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 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:393
void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation) override
Definition tria.cc:2564
void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation) override
Definition tria.cc:2571
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:2547
void update_neighbors(Triangulation< dim, spacedim > &tria) override
Definition tria.cc:2541
bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell) override
Definition tria.cc:2578
Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells) override
Definition tria.cc:2557
std::unique_ptr< Policy< dim, spacedim > > clone() override
Definition tria.cc:2586
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:503
#define DEAL_II_CXX20_REQUIRES(condition)
Definition config.h:177
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:504
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:1691
typename IteratorSelector::active_quad_iterator active_quad_iterator
Definition tria.h:1682
typename IteratorSelector::active_hex_iterator active_hex_iterator
Definition tria.h:1702
typename IteratorSelector::quad_iterator quad_iterator
Definition tria.h:1667
typename IteratorSelector::line_iterator line_iterator
Definition tria.h:1643
typename IteratorSelector::active_line_iterator active_line_iterator
Definition tria.h:1658
TriaIterator< CellAccessor< dim, spacedim > > cell_iterator
Definition tria.h:1556
void set_all_manifold_ids_on_boundary(const types::manifold_id number)
const Manifold< dim, spacedim > & get_manifold(const types::manifold_id number) const
virtual std::vector< types::manifold_id > get_manifold_ids() const
void reset_manifold(const types::manifold_id manifold_number)
void set_manifold(const types::manifold_id number, const Manifold< dim, spacedim > &manifold_object)
void reset_all_manifolds()
void set_all_manifold_ids(const types::manifold_id number)
Task< RT > new_task(const std::function< RT()> &function)
#define AssertIsNotUsed(obj)
#define DEAL_II_ASSERT_UNREACHABLE()
#define DEAL_II_NOT_IMPLEMENTED()
const unsigned int mn_tria_refine_flags_end
const unsigned int mn_tria_coarsen_flags_end
const unsigned int mn_tria_refine_flags_begin
const unsigned int mn_tria_hex_user_flags_end
const unsigned int mn_tria_line_user_flags_begin
const unsigned int mn_tria_line_user_flags_end
const unsigned int mn_tria_quad_user_flags_end
const unsigned int mn_tria_coarsen_flags_begin
const unsigned int mn_tria_hex_user_flags_begin
const unsigned int mn_tria_quad_user_flags_begin
const Mapping< dim, spacedim > & get_default_linear_mapping(const Triangulation< dim, spacedim > &triangulation)
Definition mapping.cc:294
void create_triangulation(Triangulation< dim, dim > &tria, const AdditionalData &additional_data=AdditionalData())
void reference_cell(Triangulation< dim, spacedim > &tria, const ReferenceCell &reference_cell)
double diameter(const Triangulation< dim, spacedim > &tria)
double cell_measure(const std::vector< Point< dim > > &all_vertices, const ArrayView< const unsigned int > &vertex_indices)
@ valid
Iterator points to a valid object.
std::enable_if_t< std::is_fundamental_v< T >, std::size_t > memory_consumption(const T &t)
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
Tensor< 2, dim, Number > l(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
constexpr const ReferenceCell Tetrahedron
constexpr const ReferenceCell Quadrilateral
constexpr const ReferenceCell Invalid
constexpr const ReferenceCell Triangle
constexpr const ReferenceCell Hexahedron
constexpr const ReferenceCell Line
VectorType::value_type * end(VectorType &V)
VectorType::value_type * begin(VectorType &V)
int File_write_at_c(MPI_File fh, MPI_Offset offset, const void *buf, MPI_Count count, MPI_Datatype datatype, MPI_Status *status)
int File_read_at_c(MPI_File fh, MPI_Offset offset, void *buf, MPI_Count count, MPI_Datatype datatype, MPI_Status *status)
unsigned int n_mpi_processes(const MPI_Comm mpi_communicator)
Definition mpi.cc:92
T max(const T &t, const MPI_Comm mpi_communicator)
unsigned int this_mpi_process(const MPI_Comm mpi_communicator)
Definition mpi.cc:107
size_t pack(const T &object, std::vector< char > &dest_buffer, const bool allow_compression=true)
Definition utilities.h:1381
constexpr T fixed_power(const T t)
Definition utilities.h:942
T unpack(const std::vector< char > &buffer, const bool allow_compression=true)
Definition utilities.h:1538
unsigned int n_active_cells(const internal::TriangulationImplementation::NumberCache< 1 > &c)
Definition tria.cc:14890
const Manifold< dim, spacedim > & get_default_flat_manifold()
Definition tria.cc:11995
unsigned int n_cells(const internal::TriangulationImplementation::NumberCache< 1 > &c)
Definition tria.cc:14883
void reserve_space(TriaFaces &tria_faces, const unsigned int new_quads_in_pairs, const unsigned int new_quads_single)
Definition tria.cc:1999
void monitor_memory(const TriaLevel &tria_level, const unsigned int true_dimension)
Definition tria.cc:2202
Connectivity< T > build_connectivity(const unsigned int dim, const std::vector< std::shared_ptr< CellTypeBase > > &cell_t, const std::vector< ReferenceCell > &cell_t_id, const CRS< T > &con_cv)
std::tuple< bool, bool, bool > split_face_orientation(const unsigned char combined_face_orientation)
const types::boundary_id internal_face_boundary_id
Definition types.h:312
const types::subdomain_id invalid_subdomain_id
Definition types.h:341
static const unsigned int invalid_unsigned_int
Definition types.h:220
const types::manifold_id flat_manifold_id
Definition types.h:325
const types::global_dof_index invalid_dof_index
Definition types.h:252
STL namespace.
::VectorizedArray< Number, width > min(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > abs(const ::VectorizedArray< Number, width > &)
unsigned int boundary_id
Definition types.h:144
unsigned int manifold_id
Definition types.h:156
const ::parallel::distributed::Triangulation< dim, spacedim > * triangulation
static unsigned int child_cell_on_face(const RefinementCase< dim > &ref_case, const unsigned int face, const unsigned int subface, const bool face_orientation=true, const bool face_flip=false, const bool face_rotation=false, const RefinementCase< dim - 1 > &face_refinement_case=RefinementCase< dim - 1 >::isotropic_refinement)
static RefinementCase< dim - 1 > face_refinement_case(const RefinementCase< dim > &cell_refinement_case, const unsigned int face_no, const bool face_orientation=true, const bool face_flip=false, const bool face_rotation=false)
static std_cxx20::ranges::iota_view< unsigned int, unsigned int > face_indices()
static RefinementCase< dim > min_cell_refinement_case_for_face_refinement(const RefinementCase< dim - 1 > &face_refinement_case, const unsigned int face_no, const bool face_orientation=true, const bool face_flip=false, const bool face_rotation=false)
static unsigned int n_children(const RefinementCase< dim > &refinement_case)
static void alternating_form_at_vertices(const Point< spacedim >(&vertices)[vertices_per_cell], Tensor< spacedim - dim, spacedim >(&forms)[vertices_per_cell])
bool check_consistency(const unsigned int dim) const
std::vector< std::vector< CellData< dim > > > cell_infos
std::vector<::CellData< dim > > coarse_cells
std::vector< Point< spacedim > > coarse_cell_vertices
virtual ~DistortedCellList() noexcept override
std::list< typename Triangulation< dim, spacedim >::cell_iterator > distorted_cells
Definition tria.h:1737
boost::signals2::signal< void(const Triangulation< dim, spacedim > &destination_tria)> copy
Definition tria.h:2359
static void update_neighbors(Triangulation< 1, spacedim > &)
Definition tria.cc:11872
static Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:11957
static bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &)
Definition tria.cc:11983
static void update_neighbors(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:11876
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:11942
static void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:11975
static void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:11966
static void reserve_space_(TriaObjects &obj, const unsigned int size)
Definition tria.cc:3631
static void reserve_space_(TriaFaces &faces, const unsigned structdim, const unsigned int size)
Definition tria.cc:3570
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:2792
static void prevent_distorted_boundary_cells(Triangulation< 1, spacedim > &)
Definition tria.cc:11479
static void update_neighbors(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:3020
static void prepare_refinement_dim_dependent(const Triangulation< dim, spacedim > &)
Definition tria.cc:11567
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:3926
static void reserve_space_(TriaLevel &level, const unsigned int spacedim, const unsigned int size, const bool orientation_needed)
Definition tria.cc:3592
static void update_neighbors(Triangulation< 1, spacedim > &)
Definition tria.cc:3014
static Triangulation< 3, spacedim >::DistortedCellList execute_refinement(Triangulation< 3, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:7118
static Triangulation< dim, spacedim >::DistortedCellList execute_refinement_isotropic(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:4921
static void compute_number_cache(const Triangulation< dim, spacedim > &triangulation, const unsigned int level_objects, internal::TriangulationImplementation::NumberCache< dim > &number_cache)
Definition tria.cc:2992
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:4554
static void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:11486
static bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell)
Definition tria.cc:11800
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:2899
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:3684
static void prepare_refinement_dim_dependent(Triangulation< 3, spacedim > &triangulation)
Definition tria.cc:11577
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:3788
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:2704
static Triangulation< 1, spacedim >::DistortedCellList execute_refinement(Triangulation< 1, spacedim > &triangulation, const bool)
Definition tria.cc:5380
static Triangulation< 3, spacedim >::DistortedCellList execute_refinement_isotropic(Triangulation< 3, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:5925
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:3199
static Triangulation< 2, spacedim >::DistortedCellList execute_refinement(Triangulation< 2, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:5615
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:3462
std::vector< std::vector< CellData< dim > > > cell_infos