deal.II version GIT relicensing-1853-g8a8889c127 2024-09-13 15:30:00+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
tria.cc
Go to the documentation of this file.
1// ------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: LGPL-2.1-or-later
4// Copyright (C) 1999 - 2024 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Part of the source code is dual licensed under Apache-2.0 WITH
9// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
10// governing the source code and code contributions can be found in
11// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
12//
13// ------------------------------------------------------------------------
14
15
18#include <deal.II/base/mpi.templates.h>
23
26
31#include <deal.II/grid/tria.h>
36
37#include <boost/archive/text_iarchive.hpp>
38#include <boost/archive/text_oarchive.hpp>
39
40#include <algorithm>
41#include <array>
42#include <cmath>
43#include <cstdint>
44#include <fstream>
45#include <functional>
46#include <limits>
47#include <list>
48#include <map>
49#include <memory>
50#include <numeric>
51
52
54
55
56namespace internal
57{
58 namespace TriangulationImplementation
59 {
61 : n_levels(0)
62 , n_lines(0)
63 , n_active_lines(0)
64 // all other fields are
65 // default constructed
66 {}
67
68
69
70 std::size_t
72 {
73 std::size_t mem =
78 MemoryConsumption::memory_consumption(n_active_lines_level);
79
80 if (active_cell_index_partitioner)
81 mem += active_cell_index_partitioner->memory_consumption();
82
83 for (const auto &partitioner : level_cell_index_partitioners)
84 if (partitioner)
85 mem += partitioner->memory_consumption();
86
87 return mem;
88 }
89
90
92 : n_quads(0)
93 , n_active_quads(0)
94 // all other fields are
95 // default constructed
96 {}
97
98
99
100 std::size_t
109
110
111
113 : n_hexes(0)
114 , n_active_hexes(0)
115 // all other fields are
116 // default constructed
117 {}
118
119
120
121 std::size_t
130 } // namespace TriangulationImplementation
131
132
133 template <int dim, int spacedim>
136 : variable_size_data_stored(false)
137 {}
138
139
140 template <int dim, int spacedim>
142 void CellAttachedDataSerializer<dim, spacedim>::pack_data(
143 const std::vector<cell_relation_t> &cell_relations,
144 const std::vector<
145 typename internal::CellAttachedData<dim, spacedim>::pack_callback_t>
146 &pack_callbacks_fixed,
147 const std::vector<
148 typename internal::CellAttachedData<dim, spacedim>::pack_callback_t>
149 &pack_callbacks_variable,
150 const MPI_Comm &mpi_communicator)
151 {
152 Assert(src_data_fixed.empty(),
153 ExcMessage("Previously packed data has not been released yet!"));
154 Assert(src_sizes_variable.empty(), ExcInternalError());
155
156 const unsigned int n_callbacks_fixed = pack_callbacks_fixed.size();
157 const unsigned int n_callbacks_variable = pack_callbacks_variable.size();
158
159 // Store information that we packed variable size data in
160 // a member variable for later.
161 variable_size_data_stored = (n_callbacks_variable > 0);
162
163 // If variable transfer is scheduled, we will store the data size that
164 // each variable size callback function writes in this auxiliary
165 // container. The information will be stored by each cell in this vector
166 // temporarily.
167 std::vector<unsigned int> cell_sizes_variable_cumulative(
168 n_callbacks_variable);
169
170 // Prepare the buffer structure, in which each callback function will
171 // store its data for each active cell.
172 // The outmost shell in this container construct corresponds to the
173 // data packed per cell. The next layer resembles the data that
174 // each callback function packs on the corresponding cell. These
175 // buffers are chains of chars stored in an std::vector<char>.
176 // A visualisation of the data structure:
177 /* clang-format off */
178 // | cell_1 | | cell_2 | ...
179 // || callback_1 || callback_2 |...| || callback_1 || callback_2 |...| ...
180 // |||char|char|...|||char|char|...|...| |||char|char|...|||char|char|...|...| ...
181 /* clang-format on */
182 std::vector<std::vector<std::vector<char>>> packed_fixed_size_data(
183 cell_relations.size());
184 std::vector<std::vector<std::vector<char>>> packed_variable_size_data(
185 variable_size_data_stored ? cell_relations.size() : 0);
186
187 //
188 // --------- Pack data for fixed and variable size transfer ---------
189 //
190 // Iterate over all cells, call all callback functions on each cell,
191 // and store their data in the corresponding buffer scope.
192 {
193 auto cell_rel_it = cell_relations.cbegin();
194 auto data_cell_fixed_it = packed_fixed_size_data.begin();
195 auto data_cell_variable_it = packed_variable_size_data.begin();
196 for (; cell_rel_it != cell_relations.cend(); ++cell_rel_it)
197 {
198 const auto &dealii_cell = cell_rel_it->first;
199 const auto &cell_status = cell_rel_it->second;
200
201 // Assertions about the tree structure.
202 switch (cell_status)
203 {
206 // double check the condition that we will only ever attach
207 // data to active cells when we get here
208 Assert(dealii_cell->is_active(), ExcInternalError());
209 break;
210
212 // double check the condition that we will only ever attach
213 // data to cells with children when we get here. however, we
214 // can only tolerate one level of coarsening at a time, so
215 // check that the children are all active
216 Assert(dealii_cell->is_active() == false, ExcInternalError());
217 for (unsigned int c = 0; c < dealii_cell->n_children(); ++c)
218 Assert(dealii_cell->child(c)->is_active(),
220 break;
221
223 // do nothing on invalid cells
224 break;
225
226 default:
228 break;
229 }
230
231 // Reserve memory corresponding to the number of callback
232 // functions that will be called.
233 // If variable size transfer is scheduled, we need to leave
234 // room for an array that holds information about how many
235 // bytes each of the variable size callback functions will
236 // write.
237 // On cells flagged with CellStatus::cell_invalid, only its CellStatus
238 // will be stored.
239 const unsigned int n_fixed_size_data_sets_on_cell =
240 1 + ((cell_status == CellStatus::cell_invalid) ?
241 0 :
242 ((variable_size_data_stored ? 1 : 0) + n_callbacks_fixed));
243 data_cell_fixed_it->resize(n_fixed_size_data_sets_on_cell);
244
245 // We continue with packing all data on this specific cell.
246 auto data_fixed_it = data_cell_fixed_it->begin();
247
248 // First, we pack the CellStatus information.
249 // to get consistent data sizes on each cell for the fixed size
250 // transfer, we won't allow compression
251 *data_fixed_it =
252 Utilities::pack(cell_status, /*allow_compression=*/false);
253 ++data_fixed_it;
254
255 // Proceed with all registered callback functions.
256 // Skip cells with the CellStatus::cell_invalid flag.
257 if (cell_status != CellStatus::cell_invalid)
258 {
259 // Pack fixed size data.
260 for (auto callback_it = pack_callbacks_fixed.cbegin();
261 callback_it != pack_callbacks_fixed.cend();
262 ++callback_it, ++data_fixed_it)
263 {
264 *data_fixed_it = (*callback_it)(dealii_cell, cell_status);
265 }
266
267 // Pack variable size data.
268 // If we store variable size data, we need to transfer
269 // the sizes of each corresponding callback function
270 // via fixed size transfer as well.
271 if (variable_size_data_stored)
272 {
273 const unsigned int n_variable_size_data_sets_on_cell =
274 ((cell_status == CellStatus::cell_invalid) ?
275 0 :
276 n_callbacks_variable);
277 data_cell_variable_it->resize(
278 n_variable_size_data_sets_on_cell);
279
280 auto callback_it = pack_callbacks_variable.cbegin();
281 auto data_variable_it = data_cell_variable_it->begin();
282 auto sizes_variable_it =
283 cell_sizes_variable_cumulative.begin();
284 for (; callback_it != pack_callbacks_variable.cend();
285 ++callback_it, ++data_variable_it, ++sizes_variable_it)
286 {
287 *data_variable_it =
288 (*callback_it)(dealii_cell, cell_status);
289
290 // Store data sizes for each callback function first.
291 // Make it cumulative below.
292 *sizes_variable_it = data_variable_it->size();
293 }
294
295 // Turn size vector into its cumulative representation.
296 std::partial_sum(cell_sizes_variable_cumulative.begin(),
297 cell_sizes_variable_cumulative.end(),
298 cell_sizes_variable_cumulative.begin());
299
300 // Serialize cumulative variable size vector
301 // value-by-value. This way we can circumvent the overhead
302 // of storing the container object as a whole, since we
303 // know its size by the number of registered callback
304 // functions.
305 data_fixed_it->resize(n_callbacks_variable *
306 sizeof(unsigned int));
307 for (unsigned int i = 0; i < n_callbacks_variable; ++i)
308 std::memcpy(&(data_fixed_it->at(i * sizeof(unsigned int))),
309 &(cell_sizes_variable_cumulative.at(i)),
310 sizeof(unsigned int));
311
312 ++data_fixed_it;
313 }
314
315 // Double check that we packed everything we wanted
316 // in the fixed size buffers.
317 Assert(data_fixed_it == data_cell_fixed_it->end(),
319 }
320
321 ++data_cell_fixed_it;
322
323 // Increment the variable size data iterator
324 // only if we actually pack this kind of data
325 // to avoid getting out of bounds.
326 if (variable_size_data_stored)
327 ++data_cell_variable_it;
328 } // loop over cell_relations
329 }
330
331 //
332 // ----------- Gather data sizes for fixed size transfer ------------
333 //
334 // Generate a vector which stores the sizes of each callback function,
335 // including the packed CellStatus transfer.
336 // Find the very first cell that we wrote to with all callback
337 // functions (i.e. a cell that was not flagged with
338 // CellStatus::cell_invalid) and store the sizes of each buffer.
339 //
340 // To deal with the case that at least one of the processors does not
341 // own any cell at all, we will exchange the information about the data
342 // sizes among them later. The code in between is still well-defined,
343 // since the following loops will be skipped.
344 std::vector<unsigned int> local_sizes_fixed(
345 1 + n_callbacks_fixed + (variable_size_data_stored ? 1 : 0));
346 for (const auto &data_cell : packed_fixed_size_data)
347 {
348 if (data_cell.size() == local_sizes_fixed.size())
349 {
350 auto sizes_fixed_it = local_sizes_fixed.begin();
351 auto data_fixed_it = data_cell.cbegin();
352 for (; data_fixed_it != data_cell.cend();
353 ++data_fixed_it, ++sizes_fixed_it)
354 {
355 *sizes_fixed_it = data_fixed_it->size();
356 }
357
358 break;
359 }
360 }
361
362 // Check if all cells have valid sizes.
363 for (auto data_cell_fixed_it = packed_fixed_size_data.cbegin();
364 data_cell_fixed_it != packed_fixed_size_data.cend();
365 ++data_cell_fixed_it)
366 {
367 Assert((data_cell_fixed_it->size() == 1) ||
368 (data_cell_fixed_it->size() == local_sizes_fixed.size()),
370 }
371
372 // Share information about the packed data sizes
373 // of all callback functions across all processors, in case one
374 // of them does not own any cells at all.
375 std::vector<unsigned int> global_sizes_fixed(local_sizes_fixed.size());
376 Utilities::MPI::max(local_sizes_fixed,
377 mpi_communicator,
378 global_sizes_fixed);
379
380 // Construct cumulative sizes, since this is the only information
381 // we need from now on.
382 sizes_fixed_cumulative.resize(global_sizes_fixed.size());
383 std::partial_sum(global_sizes_fixed.begin(),
384 global_sizes_fixed.end(),
385 sizes_fixed_cumulative.begin());
386
387 //
388 // ---------- Gather data sizes for variable size transfer ----------
389 //
390 if (variable_size_data_stored)
391 {
392 src_sizes_variable.reserve(packed_variable_size_data.size());
393 for (const auto &data_cell : packed_variable_size_data)
394 {
395 int variable_data_size_on_cell = 0;
396
397 for (const auto &data : data_cell)
398 variable_data_size_on_cell += data.size();
399
400 src_sizes_variable.push_back(variable_data_size_on_cell);
401 }
402 }
403
404 //
405 // ------------------------ Build buffers ---------------------------
406 //
407 const unsigned int expected_size_fixed =
408 cell_relations.size() * sizes_fixed_cumulative.back();
409 const unsigned int expected_size_variable =
410 std::accumulate(src_sizes_variable.begin(),
411 src_sizes_variable.end(),
412 std::vector<int>::size_type(0));
413
414 // Move every piece of packed fixed size data into the consecutive
415 // buffer.
416 src_data_fixed.reserve(expected_size_fixed);
417 for (const auto &data_cell_fixed : packed_fixed_size_data)
418 {
419 // Move every fraction of packed data into the buffer
420 // reserved for this particular cell.
421 for (const auto &data_fixed : data_cell_fixed)
422 std::move(data_fixed.begin(),
423 data_fixed.end(),
424 std::back_inserter(src_data_fixed));
425
426 // If we only packed the CellStatus information
427 // (i.e. encountered a cell flagged CellStatus::cell_invalid),
428 // fill the remaining space with invalid entries.
429 // We can skip this if there is nothing else to pack.
430 if ((data_cell_fixed.size() == 1) &&
431 (sizes_fixed_cumulative.size() > 1))
432 {
433 const std::size_t bytes_skipped =
434 sizes_fixed_cumulative.back() - sizes_fixed_cumulative.front();
435
436 src_data_fixed.insert(src_data_fixed.end(),
437 bytes_skipped,
438 static_cast<char>(-1)); // invalid_char
440 }
441
442 // Move every piece of packed variable size data into the consecutive
443 // buffer.
444 if (variable_size_data_stored)
445 {
446 src_data_variable.reserve(expected_size_variable);
447 for (const auto &data_cell : packed_variable_size_data)
448 {
449 // Move every fraction of packed data into the buffer
450 // reserved for this particular cell.
451 for (const auto &data : data_cell)
452 std::move(data.begin(),
453 data.end(),
454 std::back_inserter(src_data_variable));
455 }
456 }
457
458 // Double check that we packed everything correctly.
459 Assert(src_data_fixed.size() == expected_size_fixed, ExcInternalError());
460 Assert(src_data_variable.size() == expected_size_variable,
462 }
464
465
466 template <int dim, int spacedim>
468 void CellAttachedDataSerializer<dim, spacedim>::unpack_cell_status(
469 std::vector<
470 typename CellAttachedDataSerializer<dim, spacedim>::cell_relation_t>
471 &cell_relations) const
472 {
473 Assert(sizes_fixed_cumulative.size() > 0,
474 ExcMessage("No data has been packed!"));
475 if (cell_relations.size() > 0)
476 {
477 Assert(dest_data_fixed.size() > 0,
478 ExcMessage("No data has been received!"));
479 }
480
481 // Size of CellStatus object that will be unpacked on each cell.
482 const unsigned int size = sizes_fixed_cumulative.front();
483
484 // Iterate over all cells and overwrite the CellStatus
485 // information from the transferred data.
486 // Proceed buffer iterator position to next cell after
487 // each iteration.
488 auto cell_rel_it = cell_relations.begin();
489 auto dest_fixed_it = dest_data_fixed.cbegin();
490 for (; cell_rel_it != cell_relations.end();
491 ++cell_rel_it, dest_fixed_it += sizes_fixed_cumulative.back())
492 {
493 cell_rel_it->second = // cell_status
494 Utilities::unpack<CellStatus>(dest_fixed_it,
495 dest_fixed_it + size,
496 /*allow_compression=*/false);
497 }
498 }
499
500
501
502 template <int dim, int spacedim>
504 void CellAttachedDataSerializer<dim, spacedim>::unpack_data(
505 const std::vector<
506 typename CellAttachedDataSerializer<dim, spacedim>::cell_relation_t>
507 &cell_relations,
508 const unsigned int handle,
509 const std::function<
510 void(const cell_iterator &,
511 const CellStatus &,
512 const boost::iterator_range<std::vector<char>::const_iterator> &)>
513 &unpack_callback) const
514 {
515 // We decode the handle returned by register_data_attach() back into
516 // a format we can use. All even handles belong to those callback
517 // functions which write/read variable size data, all odd handles
518 // interact with fixed size buffers.
519 const bool callback_variable_transfer = (handle % 2 == 0);
520 const unsigned int callback_index = handle / 2;
521
522 // Cells will always receive fixed size data (i.e., CellStatus
523 // information), but not necessarily variable size data (e.g., with a
524 // ParticleHandler a cell might not contain any particle at all).
525 // Thus it is sufficient to check if fixed size data has been received.
526 Assert(sizes_fixed_cumulative.size() > 0,
527 ExcMessage("No data has been packed!"));
528 if (cell_relations.size() > 0)
529 {
530 Assert(dest_data_fixed.size() > 0,
531 ExcMessage("No data has been received!"));
532 }
533
534 std::vector<char>::const_iterator dest_data_it;
535 std::vector<char>::const_iterator dest_sizes_cell_it;
536
537 // Depending on whether our callback function unpacks fixed or
538 // variable size data, we have to pursue different approaches
539 // to localize the correct fraction of the buffer from which
540 // we are allowed to read.
541 unsigned int offset = numbers::invalid_unsigned_int;
542 unsigned int size = numbers::invalid_unsigned_int;
543 unsigned int data_increment = numbers::invalid_unsigned_int;
544
545 if (callback_variable_transfer)
546 {
547 // For the variable size data, we need to extract the
548 // data size from the fixed size buffer on each cell.
549 //
550 // We packed this information last, so the last packed
551 // object in the fixed size buffer corresponds to the
552 // variable data sizes.
553 //
554 // The last entry of sizes_fixed_cumulative corresponds
555 // to the size of all fixed size data packed on the cell.
556 // To get the offset for the last packed object, we need
557 // to get the next-to-last entry.
558 const unsigned int offset_variable_data_sizes =
559 sizes_fixed_cumulative[sizes_fixed_cumulative.size() - 2];
560
561 // This iterator points to the data size that the
562 // callback_function packed for each specific cell.
563 // Adjust buffer iterator to the offset of the callback
564 // function so that we only have to advance its position
565 // to the next cell after each iteration.
566 dest_sizes_cell_it = dest_data_fixed.cbegin() +
567 offset_variable_data_sizes +
568 callback_index * sizeof(unsigned int);
569
570 // Let the data iterator point to the correct buffer.
571 dest_data_it = dest_data_variable.cbegin();
572 }
573 else
574 {
575 // For the fixed size data, we can get the information about
576 // the buffer location on each cell directly from the
577 // sizes_fixed_cumulative vector.
578 offset = sizes_fixed_cumulative[callback_index];
579 size = sizes_fixed_cumulative[callback_index + 1] - offset;
580 data_increment = sizes_fixed_cumulative.back();
581
582 // Let the data iterator point to the correct buffer.
583 // Adjust buffer iterator to the offset of the callback
584 // function so that we only have to advance its position
585 // to the next cell after each iteration.
586 if (cell_relations.begin() != cell_relations.end())
587 dest_data_it = dest_data_fixed.cbegin() + offset;
588 }
589
590 // Iterate over all cells and unpack the transferred data.
591 auto cell_rel_it = cell_relations.begin();
592 auto dest_sizes_it = dest_sizes_variable.cbegin();
593 for (; cell_rel_it != cell_relations.end(); ++cell_rel_it)
594 {
595 const auto &dealii_cell = cell_rel_it->first;
596 const auto &cell_status = cell_rel_it->second;
597
598 if (callback_variable_transfer)
599 {
600 // Update the increment according to the whole data size
601 // of the current cell.
602 data_increment = *dest_sizes_it;
603
604 if (cell_status != CellStatus::cell_invalid)
605 {
606 // Extract the corresponding values for offset and size from
607 // the cumulative sizes array stored in the fixed size
608 // buffer.
609 if (callback_index == 0)
610 offset = 0;
611 else
612 std::memcpy(&offset,
613 &(*(dest_sizes_cell_it - sizeof(unsigned int))),
614 sizeof(unsigned int));
615
616 std::memcpy(&size,
617 &(*dest_sizes_cell_it),
618 sizeof(unsigned int));
619
620 size -= offset;
621
622 // Move the data iterator to the corresponding position
623 // of the callback function and adjust the increment
624 // accordingly.
625 dest_data_it += offset;
626 data_increment -= offset;
627 }
628
629 // Advance data size iterators to the next cell, avoid iterating
630 // past the end of dest_sizes_cell_it
631 if (cell_rel_it != cell_relations.end() - 1)
632 dest_sizes_cell_it += sizes_fixed_cumulative.back();
633 ++dest_sizes_it;
634 }
635
636 switch (cell_status)
637 {
640 unpack_callback(dealii_cell,
641 cell_status,
642 boost::make_iterator_range(dest_data_it,
643 dest_data_it + size));
644 break;
645
647 unpack_callback(dealii_cell->parent(),
648 cell_status,
649 boost::make_iterator_range(dest_data_it,
650 dest_data_it + size));
651 break;
652
654 // Skip this cell.
655 break;
656
657 default:
659 break;
660 }
661
662 if (cell_rel_it != cell_relations.end() - 1)
663 dest_data_it += data_increment;
664 }
665 }
666
667
668
669 template <int dim, int spacedim>
671 void CellAttachedDataSerializer<dim, spacedim>::save(
672 const unsigned int global_first_cell,
673 const unsigned int global_num_cells,
674 const std::string &file_basename,
675 const MPI_Comm &mpi_communicator) const
676 {
677 Assert(sizes_fixed_cumulative.size() > 0,
678 ExcMessage("No data has been packed!"));
679
680#ifdef DEAL_II_WITH_MPI
681 // Large fractions of this function have been copied from
682 // DataOutInterface::write_vtu_in_parallel.
683 // TODO: Write general MPIIO interface.
684
685 const unsigned int myrank =
686 Utilities::MPI::this_mpi_process(mpi_communicator);
687 const unsigned int mpisize =
688 Utilities::MPI::n_mpi_processes(mpi_communicator);
689
690 if (mpisize > 1)
691 {
692 const unsigned int bytes_per_cell = sizes_fixed_cumulative.back();
693
694 //
695 // ---------- Fixed size data ----------
696 //
697 {
698 const std::string fname_fixed =
699 std::string(file_basename) + "_fixed.data";
700
701 MPI_Info info;
702 int ierr = MPI_Info_create(&info);
703 AssertThrowMPI(ierr);
704
705 MPI_File fh;
706 ierr = MPI_File_open(mpi_communicator,
707 fname_fixed.c_str(),
708 MPI_MODE_CREATE | MPI_MODE_WRONLY,
709 info,
710 &fh);
711 AssertThrowMPI(ierr);
712
713 ierr = MPI_File_set_size(fh, 0); // delete the file contents
714 AssertThrowMPI(ierr);
715 // this barrier is necessary, because otherwise others might already
716 // write while one core is still setting the size to zero.
717 ierr = MPI_Barrier(mpi_communicator);
718 AssertThrowMPI(ierr);
719 ierr = MPI_Info_free(&info);
720 AssertThrowMPI(ierr);
721 // ------------------
722
723 // Write cumulative sizes to file.
724 // Since each processor owns the same information about the data
725 // sizes, it is sufficient to let only the first processor perform
726 // this task.
727 if (myrank == 0)
728 {
730 fh,
731 0,
732 sizes_fixed_cumulative.data(),
733 sizes_fixed_cumulative.size(),
734 MPI_UNSIGNED,
735 MPI_STATUS_IGNORE);
736 AssertThrowMPI(ierr);
737 }
738
739 // Write packed data to file simultaneously.
740 const MPI_Offset size_header =
741 sizes_fixed_cumulative.size() * sizeof(unsigned int);
742
743 // Make sure we do the following computation in 64bit integers to be
744 // able to handle 4GB+ files:
745 const MPI_Offset my_global_file_position =
746 size_header +
747 static_cast<MPI_Offset>(global_first_cell) * bytes_per_cell;
748
749 ierr =
751 my_global_file_position,
752 src_data_fixed.data(),
753 src_data_fixed.size(),
754 MPI_BYTE,
755 MPI_STATUS_IGNORE);
756 AssertThrowMPI(ierr);
757
758 ierr = MPI_File_close(&fh);
759 AssertThrowMPI(ierr);
760 }
761
762
763
764 //
765 // ---------- Variable size data ----------
766 //
767 if (variable_size_data_stored)
768 {
769 const std::string fname_variable =
770 std::string(file_basename) + "_variable.data";
771
772 MPI_Info info;
773 int ierr = MPI_Info_create(&info);
774 AssertThrowMPI(ierr);
775
776 MPI_File fh;
777 ierr = MPI_File_open(mpi_communicator,
778 fname_variable.c_str(),
779 MPI_MODE_CREATE | MPI_MODE_WRONLY,
780 info,
781 &fh);
782 AssertThrowMPI(ierr);
783
784 ierr = MPI_File_set_size(fh, 0); // delete the file contents
785 AssertThrowMPI(ierr);
786 // this barrier is necessary, because otherwise others might already
787 // write while one core is still setting the size to zero.
788 ierr = MPI_Barrier(mpi_communicator);
789 AssertThrowMPI(ierr);
790 ierr = MPI_Info_free(&info);
791 AssertThrowMPI(ierr);
792
793 // Write sizes of each cell into file simultaneously.
794 {
795 const MPI_Offset my_global_file_position =
796 static_cast<MPI_Offset>(global_first_cell) *
797 sizeof(unsigned int);
798
799 // It is very unlikely that a single process has more than
800 // 2 billion cells, but we might as well check.
801 AssertThrow(src_sizes_variable.size() <
802 static_cast<std::size_t>(
803 std::numeric_limits<int>::max()),
805
807 fh,
808 my_global_file_position,
809 src_sizes_variable.data(),
810 src_sizes_variable.size(),
811 MPI_INT,
812 MPI_STATUS_IGNORE);
813 AssertThrowMPI(ierr);
814 }
815
816 // Gather size of data in bytes we want to store from this
817 // processor and compute the prefix sum. We do this in 64 bit
818 // to avoid overflow for files larger than 4GB:
819 const std::uint64_t size_on_proc = src_data_variable.size();
820 std::uint64_t prefix_sum = 0;
821 ierr = MPI_Exscan(&size_on_proc,
822 &prefix_sum,
823 1,
824 MPI_UINT64_T,
825 MPI_SUM,
826 mpi_communicator);
827 AssertThrowMPI(ierr);
828
829 const MPI_Offset my_global_file_position =
830 static_cast<MPI_Offset>(global_num_cells) * sizeof(unsigned int) +
831 prefix_sum;
832
833 // Write data consecutively into file.
835 fh,
836 my_global_file_position,
837 src_data_variable.data(),
838 src_data_variable.size(),
839 MPI_BYTE,
840 MPI_STATUS_IGNORE);
841 AssertThrowMPI(ierr);
842
843
844 ierr = MPI_File_close(&fh);
845 AssertThrowMPI(ierr);
846 }
847 } // if (mpisize > 1)
848 else
849#endif
850 {
851 (void)global_first_cell;
852 (void)global_num_cells;
853 (void)mpi_communicator;
854
855 //
856 // ---------- Fixed size data ----------
857 //
858 {
859 const std::string fname_fixed =
860 std::string(file_basename) + "_fixed.data";
861
862 std::ofstream file(fname_fixed, std::ios::binary | std::ios::out);
863 AssertThrow(file.fail() == false, ExcIO());
864
865 // Write header data.
866 file.write(reinterpret_cast<const char *>(
867 sizes_fixed_cumulative.data()),
868 sizes_fixed_cumulative.size() * sizeof(unsigned int));
869
870 // Write packed data.
871 file.write(reinterpret_cast<const char *>(src_data_fixed.data()),
872 src_data_fixed.size() * sizeof(char));
873 }
874
875 //
876 // ---------- Variable size data ----------
877 //
878 if (variable_size_data_stored)
879 {
880 const std::string fname_variable =
881 std::string(file_basename) + "_variable.data";
882
883 std::ofstream file(fname_variable,
884 std::ios::binary | std::ios::out);
885 AssertThrow(file.fail() == false, ExcIO());
886
887 // Write header data.
888 file.write(reinterpret_cast<const char *>(
889 src_sizes_variable.data()),
890 src_sizes_variable.size() * sizeof(int));
891
892 // Write packed data.
893 file.write(reinterpret_cast<const char *>(src_data_variable.data()),
894 src_data_variable.size() * sizeof(char));
895 }
896 }
897 }
898
899
900 template <int dim, int spacedim>
902 void CellAttachedDataSerializer<dim, spacedim>::load(
903 const unsigned int global_first_cell,
904 const unsigned int global_num_cells,
905 const unsigned int local_num_cells,
906 const std::string &file_basename,
907 const unsigned int n_attached_deserialize_fixed,
908 const unsigned int n_attached_deserialize_variable,
909 const MPI_Comm &mpi_communicator)
910 {
911 Assert(dest_data_fixed.empty(),
912 ExcMessage("Previously loaded data has not been released yet!"));
913
914 variable_size_data_stored = (n_attached_deserialize_variable > 0);
915
916#ifdef DEAL_II_WITH_MPI
917 // Large fractions of this function have been copied from
918 // DataOutInterface::write_vtu_in_parallel.
919 // TODO: Write general MPIIO interface.
920
921 const unsigned int mpisize =
922 Utilities::MPI::n_mpi_processes(mpi_communicator);
923
924 if (mpisize > 1)
925 {
926 //
927 // ---------- Fixed size data ----------
928 //
929 {
930 const std::string fname_fixed =
931 std::string(file_basename) + "_fixed.data";
932
933 MPI_Info info;
934 int ierr = MPI_Info_create(&info);
935 AssertThrowMPI(ierr);
936
937 MPI_File fh;
938 ierr = MPI_File_open(
939 mpi_communicator, fname_fixed.c_str(), MPI_MODE_RDONLY, info, &fh);
940 AssertThrowMPI(ierr);
941
942 ierr = MPI_Info_free(&info);
943 AssertThrowMPI(ierr);
944
945 // Read cumulative sizes from file.
946 // Since all processors need the same information about the data
947 // sizes, let each of them retrieve it by reading from the same
948 // location in the file.
949 sizes_fixed_cumulative.resize(1 + n_attached_deserialize_fixed +
950 (variable_size_data_stored ? 1 : 0));
952 fh,
953 0,
954 sizes_fixed_cumulative.data(),
955 sizes_fixed_cumulative.size(),
956 MPI_UNSIGNED,
957 MPI_STATUS_IGNORE);
958 AssertThrowMPI(ierr);
959
960 // Allocate sufficient memory.
961 const unsigned int bytes_per_cell = sizes_fixed_cumulative.back();
962 dest_data_fixed.resize(static_cast<size_t>(local_num_cells) *
963 bytes_per_cell);
964
965 // Read packed data from file simultaneously.
966 const MPI_Offset size_header =
967 sizes_fixed_cumulative.size() * sizeof(unsigned int);
968
969 // Make sure we do the following computation in 64bit integers to be
970 // able to handle 4GB+ files:
971 const MPI_Offset my_global_file_position =
972 size_header +
973 static_cast<MPI_Offset>(global_first_cell) * bytes_per_cell;
974
975 ierr =
977 my_global_file_position,
978 dest_data_fixed.data(),
979 dest_data_fixed.size(),
980 MPI_BYTE,
981 MPI_STATUS_IGNORE);
982 AssertThrowMPI(ierr);
983
984
985 ierr = MPI_File_close(&fh);
986 AssertThrowMPI(ierr);
987 }
988
989 //
990 // ---------- Variable size data ----------
991 //
992 if (variable_size_data_stored)
993 {
994 const std::string fname_variable =
995 std::string(file_basename) + "_variable.data";
996
997 MPI_Info info;
998 int ierr = MPI_Info_create(&info);
999 AssertThrowMPI(ierr);
1000
1001 MPI_File fh;
1002 ierr = MPI_File_open(mpi_communicator,
1003 fname_variable.c_str(),
1004 MPI_MODE_RDONLY,
1005 info,
1006 &fh);
1007 AssertThrowMPI(ierr);
1008
1009 ierr = MPI_Info_free(&info);
1010 AssertThrowMPI(ierr);
1011
1012 // Read sizes of all locally owned cells.
1013 dest_sizes_variable.resize(local_num_cells);
1014
1015 const MPI_Offset my_global_file_position_sizes =
1016 static_cast<MPI_Offset>(global_first_cell) * sizeof(unsigned int);
1017
1019 fh,
1020 my_global_file_position_sizes,
1021 dest_sizes_variable.data(),
1022 dest_sizes_variable.size(),
1023 MPI_INT,
1024 MPI_STATUS_IGNORE);
1025 AssertThrowMPI(ierr);
1026
1027
1028 // Compute my data size in bytes and compute prefix sum. We do this
1029 // in 64 bit to avoid overflow for files larger than 4 GB:
1030 const std::uint64_t size_on_proc =
1031 std::accumulate(dest_sizes_variable.begin(),
1032 dest_sizes_variable.end(),
1033 0ULL);
1034
1035 std::uint64_t prefix_sum = 0;
1036 ierr = MPI_Exscan(&size_on_proc,
1037 &prefix_sum,
1038 1,
1039 MPI_UINT64_T,
1040 MPI_SUM,
1041 mpi_communicator);
1042 AssertThrowMPI(ierr);
1043
1044 const MPI_Offset my_global_file_position =
1045 static_cast<MPI_Offset>(global_num_cells) * sizeof(unsigned int) +
1046 prefix_sum;
1047
1048 dest_data_variable.resize(size_on_proc);
1049
1051 fh,
1052 my_global_file_position,
1053 dest_data_variable.data(),
1054 dest_data_variable.size(),
1055 MPI_BYTE,
1056 MPI_STATUS_IGNORE);
1057 AssertThrowMPI(ierr);
1058
1059 ierr = MPI_File_close(&fh);
1060 AssertThrowMPI(ierr);
1061 }
1062 }
1063 else // if (mpisize > 1)
1064#endif
1065 {
1066 (void)mpi_communicator;
1067 (void)global_first_cell;
1068 (void)global_num_cells;
1069
1070 //
1071 // ---------- Fixed size data ----------
1072 //
1073 {
1074 const std::string fname_fixed =
1075 std::string(file_basename) + "_fixed.data";
1076
1077 std::ifstream file(fname_fixed, std::ios::binary | std::ios::in);
1078 AssertThrow(file.fail() == false, ExcIO());
1079
1080 sizes_fixed_cumulative.resize(1 + n_attached_deserialize_fixed +
1081 (variable_size_data_stored ? 1 : 0));
1082 // Read header data.
1083 file.read(reinterpret_cast<char *>(sizes_fixed_cumulative.data()),
1084 sizes_fixed_cumulative.size() * sizeof(unsigned int));
1085
1086 const unsigned int bytes_per_cell = sizes_fixed_cumulative.back();
1087 dest_data_fixed.resize(static_cast<size_t>(local_num_cells) *
1088 bytes_per_cell);
1089
1090 // Read packed data.
1091 file.read(reinterpret_cast<char *>(dest_data_fixed.data()),
1092 dest_data_fixed.size() * sizeof(char));
1093 }
1094
1095 //
1096 // ---------- Variable size data ----------
1097 //
1098 if (variable_size_data_stored)
1099 {
1100 const std::string fname_variable =
1101 std::string(file_basename) + "_variable.data";
1102
1103 std::ifstream file(fname_variable, std::ios::binary | std::ios::in);
1104 AssertThrow(file.fail() == false, ExcIO());
1105
1106 // Read header data.
1107 dest_sizes_variable.resize(local_num_cells);
1108 file.read(reinterpret_cast<char *>(dest_sizes_variable.data()),
1109 dest_sizes_variable.size() * sizeof(int));
1110
1111 // Read packed data.
1112 const std::uint64_t size =
1113 std::accumulate(dest_sizes_variable.begin(),
1114 dest_sizes_variable.end(),
1115 0ULL);
1116 dest_data_variable.resize(size);
1117 file.read(reinterpret_cast<char *>(dest_data_variable.data()),
1118 dest_data_variable.size() * sizeof(char));
1119 }
1120 }
1121 }
1122
1123
1124 template <int dim, int spacedim>
1126 void CellAttachedDataSerializer<dim, spacedim>::clear()
1127 {
1128 variable_size_data_stored = false;
1129
1130 // free information about data sizes
1131 sizes_fixed_cumulative.clear();
1132 sizes_fixed_cumulative.shrink_to_fit();
1133
1134 // free fixed size transfer data
1135 src_data_fixed.clear();
1136 src_data_fixed.shrink_to_fit();
1137
1138 dest_data_fixed.clear();
1139 dest_data_fixed.shrink_to_fit();
1140
1141 // free variable size transfer data
1142 src_sizes_variable.clear();
1143 src_sizes_variable.shrink_to_fit();
1144
1145 src_data_variable.clear();
1146 src_data_variable.shrink_to_fit();
1147
1148 dest_sizes_variable.clear();
1149 dest_sizes_variable.shrink_to_fit();
1150
1151 dest_data_variable.clear();
1152 dest_data_variable.shrink_to_fit();
1153 }
1154
1155} // namespace internal
1156
1157// anonymous namespace for internal helper functions
1158namespace
1159{
1160 // return whether the given cell is
1161 // patch_level_1, i.e. determine
1162 // whether either all or none of
1163 // its children are further
1164 // refined. this function can only
1165 // be called for non-active cells.
1166 template <int dim, int spacedim>
1167 bool
1168 cell_is_patch_level_1(
1170 {
1171 Assert(cell->is_active() == false, ExcInternalError());
1172
1173 unsigned int n_active_children = 0;
1174 for (unsigned int i = 0; i < cell->n_children(); ++i)
1175 if (cell->child(i)->is_active())
1176 ++n_active_children;
1177
1178 return (n_active_children == 0) ||
1179 (n_active_children == cell->n_children());
1180 }
1181
1182
1183
1184 // return, whether a given @p cell will be
1185 // coarsened, which is the case if all
1186 // children are active and have their coarsen
1187 // flag set. In case only part of the coarsen
1188 // flags are set, remove them.
1189 template <int dim, int spacedim>
1190 bool
1191 cell_will_be_coarsened(
1193 {
1194 // only cells with children should be
1195 // considered for coarsening
1196
1197 if (cell->has_children())
1198 {
1199 unsigned int children_to_coarsen = 0;
1200 const unsigned int n_children = cell->n_children();
1201
1202 for (unsigned int c = 0; c < n_children; ++c)
1203 if (cell->child(c)->is_active() && cell->child(c)->coarsen_flag_set())
1204 ++children_to_coarsen;
1205 if (children_to_coarsen == n_children)
1206 return true;
1207 else
1208 for (unsigned int c = 0; c < n_children; ++c)
1209 if (cell->child(c)->is_active())
1210 cell->child(c)->clear_coarsen_flag();
1211 }
1212 // no children, so no coarsening
1213 // possible. however, no children also
1214 // means that this cell will be in the same
1215 // state as if it had children and was
1216 // coarsened. So, what should we return -
1217 // false or true?
1218 // make sure we do not have to do this at
1219 // all...
1220 Assert(cell->has_children(), ExcInternalError());
1221 // ... and then simply return false
1222 return false;
1223 }
1224
1225
1226 // return, whether the face @p face_no of the
1227 // given @p cell will be refined after the
1228 // current refinement step, considering
1229 // refine and coarsen flags and considering
1230 // only those refinemnts that will be caused
1231 // by the neighboring cell.
1232
1233 // this function is used on both active cells
1234 // and cells with children. on cells with
1235 // children it also of interest to know 'how'
1236 // the face will be refined. thus there is an
1237 // additional third argument @p
1238 // expected_face_ref_case returning just
1239 // that. be aware, that this variable will
1240 // only contain useful information if this
1241 // function is called for an active cell.
1242 //
1243 // thus, this is an internal function, users
1244 // should call one of the two alternatives
1245 // following below.
1246 template <int dim, int spacedim>
1247 bool
1248 face_will_be_refined_by_neighbor_internal(
1250 const unsigned int face_no,
1251 RefinementCase<dim - 1> &expected_face_ref_case)
1252 {
1253 // first of all: set the default value for
1254 // expected_face_ref_case, which is no
1255 // refinement at all
1256 expected_face_ref_case = RefinementCase<dim - 1>::no_refinement;
1257
1258 const typename Triangulation<dim, spacedim>::cell_iterator neighbor =
1259 cell->neighbor(face_no);
1260
1261 // If we are at the boundary, there is no
1262 // neighbor which could refine the face
1263 if (neighbor.state() != IteratorState::valid)
1264 return false;
1265
1266 if (neighbor->has_children())
1267 {
1268 // if the neighbor is refined, it may be
1269 // coarsened. if so, then it won't refine
1270 // the face, no matter what else happens
1271 if (cell_will_be_coarsened(neighbor))
1272 return false;
1273 else
1274 // if the neighbor is refined, then it
1275 // is also refined at our current
1276 // face. It will stay so without
1277 // coarsening, so return true in that
1278 // case.
1279 {
1280 expected_face_ref_case = cell->face(face_no)->refinement_case();
1281 return true;
1282 }
1283 }
1284
1285 // now, the neighbor is not refined, but
1286 // perhaps it will be
1287 const RefinementCase<dim> nb_ref_flag = neighbor->refine_flag_set();
1288 if (nb_ref_flag != RefinementCase<dim>::no_refinement)
1289 {
1290 // now we need to know, which of the
1291 // neighbors faces points towards us
1292 const unsigned int neighbor_neighbor = cell->neighbor_face_no(face_no);
1293 // check, whether the cell will be
1294 // refined in a way that refines our
1295 // face
1296 const RefinementCase<dim - 1> face_ref_case =
1298 nb_ref_flag,
1299 neighbor_neighbor,
1300 neighbor->face_orientation(neighbor_neighbor),
1301 neighbor->face_flip(neighbor_neighbor),
1302 neighbor->face_rotation(neighbor_neighbor));
1303 if (face_ref_case != RefinementCase<dim - 1>::no_refinement)
1304 {
1306 neighbor_face = neighbor->face(neighbor_neighbor);
1307 const int this_face_index = cell->face_index(face_no);
1308
1309 // there are still two basic
1310 // possibilities here: the neighbor
1311 // might be coarser or as coarse
1312 // as we are
1313 if (neighbor_face->index() == this_face_index)
1314 // the neighbor is as coarse as
1315 // we are and will be refined at
1316 // the face of consideration, so
1317 // return true
1318 {
1319 expected_face_ref_case = face_ref_case;
1320 return true;
1321 }
1322 else
1323 {
1324 // the neighbor is coarser.
1325 // this is the most complicated
1326 // case. It might be, that the
1327 // neighbor's face will be
1328 // refined, but that we will
1329 // not see this, as we are
1330 // refined in a similar way.
1331
1332 // so, the neighbor's face must
1333 // have children. check, if our
1334 // cell's face is one of these
1335 // (it could also be a
1336 // grand_child)
1337 for (unsigned int c = 0; c < neighbor_face->n_children(); ++c)
1338 if (neighbor_face->child_index(c) == this_face_index)
1339 {
1340 // if the flagged refine
1341 // case of the face is a
1342 // subset or the same as
1343 // the current refine case,
1344 // then the face, as seen
1345 // from our cell, won't be
1346 // refined by the neighbor
1347 if ((neighbor_face->refinement_case() | face_ref_case) ==
1348 neighbor_face->refinement_case())
1349 return false;
1350 else
1351 {
1352 // if we are active, we
1353 // must be an
1354 // anisotropic child
1355 // and the coming
1356 // face_ref_case is
1357 // isotropic. Thus,
1358 // from our cell we
1359 // will see exactly the
1360 // opposite refine case
1361 // that the face has
1362 // now...
1363 Assert(
1364 face_ref_case ==
1367 expected_face_ref_case =
1368 ~neighbor_face->refinement_case();
1369 return true;
1370 }
1371 }
1372
1373 // so, obviously we were not
1374 // one of the children, but a
1375 // grandchild. This is only
1376 // possible in 3d.
1377 Assert(dim == 3, ExcInternalError());
1378 // In that case, however, no
1379 // matter what the neighbor
1380 // does, it won't be finer
1381 // after the next refinement
1382 // step.
1383 return false;
1384 }
1385 } // if face will be refined
1386 } // if neighbor is flagged for refinement
1387
1388 // no cases left, so the neighbor will not
1389 // refine the face
1390 return false;
1391 }
1392
1393 // version of above function for both active
1394 // and non-active cells
1395 template <int dim, int spacedim>
1396 bool
1397 face_will_be_refined_by_neighbor(
1399 const unsigned int face_no)
1400 {
1401 RefinementCase<dim - 1> dummy = RefinementCase<dim - 1>::no_refinement;
1402 return face_will_be_refined_by_neighbor_internal(cell, face_no, dummy);
1403 }
1404
1405 // version of above function for active cells
1406 // only. Additionally returning the refine
1407 // case (to come) of the face under
1408 // consideration
1409 template <int dim, int spacedim>
1410 bool
1411 face_will_be_refined_by_neighbor(
1413 const unsigned int face_no,
1414 RefinementCase<dim - 1> &expected_face_ref_case)
1415 {
1416 return face_will_be_refined_by_neighbor_internal(cell,
1417 face_no,
1418 expected_face_ref_case);
1419 }
1420
1421
1422
1423 template <int dim, int spacedim>
1424 bool
1425 satisfies_level1_at_vertex_rule(
1427 {
1428 std::vector<unsigned int> min_adjacent_cell_level(
1429 triangulation.n_vertices(), triangulation.n_levels());
1430 std::vector<unsigned int> max_adjacent_cell_level(
1431 triangulation.n_vertices(), 0);
1432
1433 for (const auto &cell : triangulation.active_cell_iterators())
1434 for (const unsigned int v : cell->vertex_indices())
1435 {
1436 min_adjacent_cell_level[cell->vertex_index(v)] =
1437 std::min<unsigned int>(
1438 min_adjacent_cell_level[cell->vertex_index(v)], cell->level());
1439 max_adjacent_cell_level[cell->vertex_index(v)] =
1440 std::max<unsigned int>(
1441 min_adjacent_cell_level[cell->vertex_index(v)], cell->level());
1442 }
1443
1444 for (unsigned int k = 0; k < triangulation.n_vertices(); ++k)
1445 if (triangulation.vertex_used(k))
1446 if (max_adjacent_cell_level[k] - min_adjacent_cell_level[k] > 1)
1447 return false;
1448 return true;
1449 }
1450
1451
1452
1470 template <int dim, int spacedim>
1471 unsigned int
1472 middle_vertex_index(
1474 {
1475 if (line->has_children())
1476 return line->child(0)->vertex_index(1);
1478 }
1479
1480
1481 template <int dim, int spacedim>
1482 unsigned int
1483 middle_vertex_index(
1485 {
1486 switch (static_cast<unsigned char>(quad->refinement_case()))
1487 {
1489 return middle_vertex_index<dim, spacedim>(quad->child(0)->line(1));
1490 break;
1492 return middle_vertex_index<dim, spacedim>(quad->child(0)->line(3));
1493 break;
1495 return quad->child(0)->vertex_index(3);
1496 break;
1497 default:
1498 break;
1499 }
1501 }
1502
1503
1504 template <int dim, int spacedim>
1505 unsigned int
1506 middle_vertex_index(
1508 {
1509 switch (static_cast<unsigned char>(hex->refinement_case()))
1510 {
1512 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(1));
1513 break;
1515 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(3));
1516 break;
1518 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(5));
1519 break;
1521 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(11));
1522 break;
1524 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(5));
1525 break;
1527 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(7));
1528 break;
1530 return hex->child(0)->vertex_index(7);
1531 break;
1532 default:
1533 break;
1534 }
1536 }
1537
1538
1551 template <class TRIANGULATION>
1552 inline typename TRIANGULATION::DistortedCellList
1553 collect_distorted_coarse_cells(const TRIANGULATION &)
1554 {
1555 return typename TRIANGULATION::DistortedCellList();
1556 }
1557
1558
1559
1568 template <int dim>
1570 collect_distorted_coarse_cells(const Triangulation<dim, dim> &triangulation)
1571 {
1572 typename Triangulation<dim, dim>::DistortedCellList distorted_cells;
1573 for (const auto &cell : triangulation.cell_iterators_on_level(0))
1574 {
1576 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1577 vertices[i] = cell->vertex(i);
1578
1581
1582 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1583 if (determinants[i] <=
1584 1e-9 * Utilities::fixed_power<dim>(cell->diameter()))
1585 {
1586 distorted_cells.distorted_cells.push_back(cell);
1587 break;
1588 }
1589 }
1590
1591 return distorted_cells;
1592 }
1593
1594
1601 template <int dim>
1602 bool
1603 has_distorted_children(
1604 const typename Triangulation<dim, dim>::cell_iterator &cell)
1605 {
1606 Assert(cell->has_children(), ExcInternalError());
1607
1608 for (unsigned int c = 0; c < cell->n_children(); ++c)
1609 {
1611 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1612 vertices[i] = cell->child(c)->vertex(i);
1613
1616
1617 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1618 if (determinants[i] <=
1619 1e-9 * Utilities::fixed_power<dim>(cell->child(c)->diameter()))
1620 return true;
1621 }
1622
1623 return false;
1624 }
1625
1626
1634 template <int dim, int spacedim>
1635 bool
1636 has_distorted_children(
1638 {
1639 return false;
1640 }
1641
1642
1643 template <int dim, int spacedim>
1644 void
1645 update_periodic_face_map_recursively(
1646 const typename Triangulation<dim, spacedim>::cell_iterator &cell_1,
1647 const typename Triangulation<dim, spacedim>::cell_iterator &cell_2,
1648 unsigned int n_face_1,
1649 unsigned int n_face_2,
1650 const unsigned char orientation,
1651 typename std::map<
1653 unsigned int>,
1654 std::pair<std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
1655 unsigned int>,
1656 unsigned char>> &periodic_face_map)
1657 {
1658 using FaceIterator = typename Triangulation<dim, spacedim>::face_iterator;
1659 const FaceIterator face_1 = cell_1->face(n_face_1);
1660 const FaceIterator face_2 = cell_2->face(n_face_2);
1661
1662 const unsigned char inverse_orientation =
1663 face_1->reference_cell().get_inverse_combined_orientation(orientation);
1664
1665#ifdef DEBUG
1666 const auto [face_orientation, face_rotation, face_flip] =
1668
1669 Assert((dim != 1) || (face_orientation == true && face_flip == false &&
1670 face_rotation == false),
1671 ExcMessage("The supplied orientation "
1672 "(face_orientation, face_flip, face_rotation) "
1673 "is invalid for 1d"));
1674
1675 Assert((dim != 2) || (face_flip == false && face_rotation == false),
1676 ExcMessage("The supplied orientation "
1677 "(face_orientation, face_flip, face_rotation) "
1678 "is invalid for 2d"));
1679#endif
1680
1681 Assert(face_1 != face_2, ExcMessage("face_1 and face_2 are equal!"));
1682
1683 Assert(face_1->at_boundary() && face_2->at_boundary(),
1684 ExcMessage("Periodic faces must be on the boundary"));
1685
1686 // Check if the requirement that each edge can only have at most one hanging
1687 // node, and as a consequence neighboring cells can differ by at most
1688 // one refinement level is enforced. In 1d, there are no hanging nodes and
1689 // so neighboring cells can differ by more than one refinement level.
1690 Assert(dim == 1 || std::abs(cell_1->level() - cell_2->level()) < 2,
1692
1693 // insert periodic face pair for both cells
1694 using CellFace =
1695 std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
1696 unsigned int>;
1697 const CellFace cell_face_1(cell_1, n_face_1);
1698 const CellFace cell_face_2(cell_2, n_face_2);
1699 const std::pair<CellFace, unsigned char> cell_face_orientation_2(
1700 cell_face_2, orientation);
1701
1702 const std::pair<CellFace, std::pair<CellFace, unsigned char>>
1703 periodic_faces(cell_face_1, cell_face_orientation_2);
1704
1705 // Only one periodic neighbor is allowed
1706 Assert(periodic_face_map.count(cell_face_1) == 0, ExcInternalError());
1707 periodic_face_map.insert(periodic_faces);
1708
1709 if (dim == 1)
1710 {
1711 if (cell_1->has_children())
1712 {
1713 if (cell_2->has_children())
1714 {
1715 update_periodic_face_map_recursively<dim, spacedim>(
1716 cell_1->child(n_face_1),
1717 cell_2->child(n_face_2),
1718 n_face_1,
1719 n_face_2,
1720 orientation,
1721 periodic_face_map);
1722 }
1723 else // only face_1 has children
1724 {
1725 update_periodic_face_map_recursively<dim, spacedim>(
1726 cell_1->child(n_face_1),
1727 cell_2,
1728 n_face_1,
1729 n_face_2,
1730 orientation,
1731 periodic_face_map);
1732 }
1733 }
1734 }
1735 else // dim == 2 || dim == 3
1736 {
1737 if (cell_1->has_children())
1738 {
1739 if (cell_2->has_children())
1740 {
1741 // In the case that both faces have children, we loop over all
1742 // children and apply update_periodic_face_map_recursively
1743 // recursively:
1744
1745 Assert(face_1->n_children() ==
1747 face_2->n_children() ==
1750
1751 const auto reference_cell = cell_1->reference_cell();
1752
1753 for (unsigned int i = 0;
1754 i < GeometryInfo<dim>::max_children_per_face;
1755 ++i)
1756 {
1757 // Lookup the index for the second face
1758 const unsigned int j =
1759 reference_cell.standard_to_real_face_vertex(
1760 i, n_face_1, inverse_orientation);
1761
1762 // find subcell ids that belong to the subface indices
1763 unsigned int child_cell_1 =
1765 cell_1->refinement_case(),
1766 n_face_1,
1767 i,
1768 cell_1->face_orientation(n_face_1),
1769 cell_1->face_flip(n_face_1),
1770 cell_1->face_rotation(n_face_1),
1771 face_1->refinement_case());
1772 unsigned int child_cell_2 =
1774 cell_2->refinement_case(),
1775 n_face_2,
1776 j,
1777 cell_2->face_orientation(n_face_2),
1778 cell_2->face_flip(n_face_2),
1779 cell_2->face_rotation(n_face_2),
1780 face_2->refinement_case());
1781
1782 Assert(cell_1->child(child_cell_1)->face(n_face_1) ==
1783 face_1->child(i),
1785 Assert(cell_2->child(child_cell_2)->face(n_face_2) ==
1786 face_2->child(j),
1788
1789 // precondition: subcell has the same orientation as cell
1790 // (so that the face numbers coincide) recursive call
1791 update_periodic_face_map_recursively<dim, spacedim>(
1792 cell_1->child(child_cell_1),
1793 cell_2->child(child_cell_2),
1794 n_face_1,
1795 n_face_2,
1796 orientation,
1797 periodic_face_map);
1798 }
1799 }
1800 else // only face_1 has children
1801 {
1802 for (unsigned int i = 0;
1803 i < GeometryInfo<dim>::max_children_per_face;
1804 ++i)
1805 {
1806 // find subcell ids that belong to the subface indices
1807 unsigned int child_cell_1 =
1809 cell_1->refinement_case(),
1810 n_face_1,
1811 i,
1812 cell_1->face_orientation(n_face_1),
1813 cell_1->face_flip(n_face_1),
1814 cell_1->face_rotation(n_face_1),
1815 face_1->refinement_case());
1816
1817 // recursive call
1818 update_periodic_face_map_recursively<dim, spacedim>(
1819 cell_1->child(child_cell_1),
1820 cell_2,
1821 n_face_1,
1822 n_face_2,
1823 orientation,
1824 periodic_face_map);
1825 }
1826 }
1827 }
1828 }
1829 }
1830
1831
1832} // end of anonymous namespace
1833
1834
1835namespace internal
1836{
1837 namespace TriangulationImplementation
1838 {
1839 // make sure that if in the following we
1840 // write Triangulation<dim,spacedim>
1841 // we mean the *class*
1842 // ::Triangulation, not the
1843 // enclosing namespace
1844 // internal::TriangulationImplementation
1845 using ::Triangulation;
1846
1852 int,
1853 << "Something went wrong upon construction of cell "
1854 << arg1);
1865 int,
1866 << "Cell " << arg1
1867 << " has negative measure. This typically "
1868 << "indicates some distortion in the cell, or a mistakenly "
1869 << "swapped pair of vertices in the input to "
1870 << "Triangulation::create_triangulation().");
1879 int,
1880 int,
1881 int,
1882 << "Error while creating cell " << arg1
1883 << ": the vertex index " << arg2 << " must be between 0 and "
1884 << arg3 << '.');
1891 int,
1892 int,
1894 << "The input data for creating a triangulation contained "
1895 << "information about a line with indices " << arg1 << " and " << arg2
1896 << " that is described to have boundary indicator "
1897 << static_cast<int>(arg3)
1898 << ". However, this is an internal line not located on the "
1899 << "boundary. You cannot assign a boundary indicator to it." << std::endl
1900 << std::endl
1901 << "If this happened at a place where you call "
1902 << "Triangulation::create_triangulation() yourself, you need "
1903 << "to check the SubCellData object you pass to this function."
1904 << std::endl
1905 << std::endl
1906 << "If this happened in a place where you are reading a mesh "
1907 << "from a file, then you need to investigate why such a line "
1908 << "ended up in the input file. A typical case is a geometry "
1909 << "that consisted of multiple parts and for which the mesh "
1910 << "generator program assumes that the interface between "
1911 << "two parts is a boundary when that isn't supposed to be "
1912 << "the case, or where the mesh generator simply assigns "
1913 << "'geometry indicators' to lines at the perimeter of "
1914 << "a part that are not supposed to be interpreted as "
1915 << "'boundary indicators'.");
1922 int,
1923 int,
1924 int,
1925 int,
1927 << "The input data for creating a triangulation contained "
1928 << "information about a quad with indices " << arg1 << ", " << arg2
1929 << ", " << arg3 << ", and " << arg4
1930 << " that is described to have boundary indicator "
1931 << static_cast<int>(arg5)
1932 << ". However, this is an internal quad not located on the "
1933 << "boundary. You cannot assign a boundary indicator to it." << std::endl
1934 << std::endl
1935 << "If this happened at a place where you call "
1936 << "Triangulation::create_triangulation() yourself, you need "
1937 << "to check the SubCellData object you pass to this function."
1938 << std::endl
1939 << std::endl
1940 << "If this happened in a place where you are reading a mesh "
1941 << "from a file, then you need to investigate why such a quad "
1942 << "ended up in the input file. A typical case is a geometry "
1943 << "that consisted of multiple parts and for which the mesh "
1944 << "generator program assumes that the interface between "
1945 << "two parts is a boundary when that isn't supposed to be "
1946 << "the case, or where the mesh generator simply assigns "
1947 << "'geometry indicators' to quads at the surface of "
1948 << "a part that are not supposed to be interpreted as "
1949 << "'boundary indicators'.");
1956 int,
1957 int,
1958 << "In SubCellData the line info of the line with vertex indices " << arg1
1959 << " and " << arg2 << " appears more than once. "
1960 << "This is not allowed.");
1967 int,
1968 int,
1969 std::string,
1970 << "In SubCellData the line info of the line with vertex indices " << arg1
1971 << " and " << arg2 << " appears multiple times with different (valid) "
1972 << arg3 << ". This is not allowed.");
1979 int,
1980 int,
1981 int,
1982 int,
1983 std::string,
1984 << "In SubCellData the quad info of the quad with line indices " << arg1
1985 << ", " << arg2 << ", " << arg3 << " and " << arg4
1986 << " appears multiple times with different (valid) " << arg5
1987 << ". This is not allowed.");
1988
1989 /*
1990 * Reserve space for TriaFaces. Details:
1991 *
1992 * Reserve space for line_orientations.
1993 *
1994 * @note Used only for dim=3.
1995 */
1996 void
1998 const unsigned int new_quads_in_pairs,
1999 const unsigned int new_quads_single)
2000 {
2001 AssertDimension(tria_faces.dim, 3);
2002
2003 Assert(new_quads_in_pairs % 2 == 0, ExcInternalError());
2004
2005 unsigned int next_free_single = 0;
2006 unsigned int next_free_pair = 0;
2007
2008 // count the number of objects, of unused single objects and of
2009 // unused pairs of objects
2010 [[maybe_unused]] unsigned int n_quads = 0;
2011 unsigned int n_unused_pairs = 0;
2012 unsigned int n_unused_singles = 0;
2013 for (unsigned int i = 0; i < tria_faces.quads.used.size(); ++i)
2014 {
2015 if (tria_faces.quads.used[i])
2016 ++n_quads;
2017 else if (i + 1 < tria_faces.quads.used.size())
2018 {
2019 if (tria_faces.quads.used[i + 1])
2020 {
2021 ++n_unused_singles;
2022 if (next_free_single == 0)
2023 next_free_single = i;
2024 }
2025 else
2026 {
2027 ++n_unused_pairs;
2028 if (next_free_pair == 0)
2029 next_free_pair = i;
2030 ++i;
2031 }
2032 }
2033 else
2034 ++n_unused_singles;
2035 }
2036 Assert(n_quads + 2 * n_unused_pairs + n_unused_singles ==
2037 tria_faces.quads.used.size(),
2039
2040 // how many single quads are needed in addition to n_unused_quads?
2041 const int additional_single_quads = new_quads_single - n_unused_singles;
2042
2043 unsigned int new_size =
2044 tria_faces.quads.used.size() + new_quads_in_pairs - 2 * n_unused_pairs;
2045 if (additional_single_quads > 0)
2046 new_size += additional_single_quads;
2047
2048 // see above...
2049 if (new_size > tria_faces.quads.n_objects())
2050 {
2051 // reserve the field of the derived class
2052 tria_faces.quads_line_orientations.resize(
2053 new_size * GeometryInfo<3>::lines_per_face, true);
2054
2055 auto &q_is_q = tria_faces.quad_is_quadrilateral;
2056 q_is_q.reserve(new_size);
2057 q_is_q.insert(q_is_q.end(), new_size - q_is_q.size(), true);
2058 }
2059 }
2060
2061
2062
2076 void
2078 const unsigned int total_cells,
2079 const unsigned int dimension,
2080 const unsigned int space_dimension,
2081 const bool tetraheder_in_mesh = false)
2082 {
2083 // we need space for total_cells cells. Maybe we have more already
2084 // with those cells which are unused, so only allocate new space if
2085 // needed.
2086 //
2087 // note that all arrays should have equal sizes (checked by
2088 // @p{monitor_memory}
2089 if (total_cells > tria_level.refine_flags.size())
2090 {
2091 tria_level.refine_flags.reserve(total_cells);
2092 tria_level.refine_flags.insert(tria_level.refine_flags.end(),
2093 total_cells -
2094 tria_level.refine_flags.size(),
2095 /*RefinementCase::no_refinement=*/0);
2096
2097 if (tetraheder_in_mesh)
2098 {
2099 tria_level.refine_choice.reserve(total_cells);
2100 tria_level.refine_choice.insert(
2101 tria_level.refine_choice.end(),
2102 total_cells - tria_level.refine_choice.size(),
2103 static_cast<char>(
2105 }
2106
2107 tria_level.coarsen_flags.reserve(total_cells);
2108 tria_level.coarsen_flags.insert(tria_level.coarsen_flags.end(),
2109 total_cells -
2110 tria_level.coarsen_flags.size(),
2111 false);
2112
2113 tria_level.active_cell_indices.reserve(total_cells);
2114 tria_level.active_cell_indices.insert(
2115 tria_level.active_cell_indices.end(),
2116 total_cells - tria_level.active_cell_indices.size(),
2118
2119 tria_level.subdomain_ids.reserve(total_cells);
2120 tria_level.subdomain_ids.insert(tria_level.subdomain_ids.end(),
2121 total_cells -
2122 tria_level.subdomain_ids.size(),
2123 0);
2124
2125 tria_level.level_subdomain_ids.reserve(total_cells);
2126 tria_level.level_subdomain_ids.insert(
2127 tria_level.level_subdomain_ids.end(),
2128 total_cells - tria_level.level_subdomain_ids.size(),
2129 0);
2130
2131 tria_level.global_active_cell_indices.reserve(total_cells);
2132 tria_level.global_active_cell_indices.insert(
2133 tria_level.global_active_cell_indices.end(),
2134 total_cells - tria_level.global_active_cell_indices.size(),
2136
2137 tria_level.global_level_cell_indices.reserve(total_cells);
2138 tria_level.global_level_cell_indices.insert(
2139 tria_level.global_level_cell_indices.end(),
2140 total_cells - tria_level.global_level_cell_indices.size(),
2142
2143 if (dimension == space_dimension - 1)
2144 {
2145 tria_level.direction_flags.reserve(total_cells);
2146 tria_level.direction_flags.insert(
2147 tria_level.direction_flags.end(),
2148 total_cells - tria_level.direction_flags.size(),
2149 true);
2150 }
2151 else
2152 tria_level.direction_flags.clear();
2153
2154 tria_level.parents.reserve((total_cells + 1) / 2);
2155 tria_level.parents.insert(tria_level.parents.end(),
2156 (total_cells + 1) / 2 -
2157 tria_level.parents.size(),
2158 -1);
2159
2160 tria_level.neighbors.reserve(total_cells * (2 * dimension));
2161 tria_level.neighbors.insert(tria_level.neighbors.end(),
2162 total_cells * (2 * dimension) -
2163 tria_level.neighbors.size(),
2164 std::make_pair(-1, -1));
2165
2166 if (tria_level.dim == 2 || tria_level.dim == 3)
2167 {
2168 const unsigned int max_faces_per_cell = 2 * dimension;
2169 tria_level.face_orientations.resize(total_cells *
2170 max_faces_per_cell);
2171
2172 tria_level.reference_cell.reserve(total_cells);
2173 tria_level.reference_cell.insert(
2174 tria_level.reference_cell.end(),
2175 total_cells - tria_level.reference_cell.size(),
2176 tria_level.dim == 2 ? ReferenceCells::Quadrilateral :
2178 }
2179 }
2180 }
2181
2182
2183
2188 int,
2189 int,
2190 << "The containers have sizes " << arg1 << " and " << arg2
2191 << ", which is not as expected.");
2192
2198 void
2199 monitor_memory(const TriaLevel &tria_level,
2200 const unsigned int true_dimension)
2201 {
2202 Assert(2 * true_dimension * tria_level.refine_flags.size() ==
2203 tria_level.neighbors.size(),
2204 ExcMemoryInexact(tria_level.refine_flags.size(),
2205 tria_level.neighbors.size()));
2206 Assert(2 * true_dimension * tria_level.coarsen_flags.size() ==
2207 tria_level.neighbors.size(),
2208 ExcMemoryInexact(tria_level.coarsen_flags.size(),
2209 tria_level.neighbors.size()));
2210 }
2211
2212
2213
2226 void
2228 const unsigned int new_objects_in_pairs,
2229 const unsigned int new_objects_single = 0)
2230 {
2231 if (tria_objects.structdim <= 2)
2232 {
2233 Assert(new_objects_in_pairs % 2 == 0, ExcInternalError());
2234
2235 tria_objects.next_free_single = 0;
2236 tria_objects.next_free_pair = 0;
2237 tria_objects.reverse_order_next_free_single = false;
2238
2239 // count the number of objects, of unused single objects and of
2240 // unused pairs of objects
2241 [[maybe_unused]] unsigned int n_objects = 0;
2242 unsigned int n_unused_pairs = 0;
2243 unsigned int n_unused_singles = 0;
2244 for (unsigned int i = 0; i < tria_objects.used.size(); ++i)
2245 {
2246 if (tria_objects.used[i])
2247 ++n_objects;
2248 else if (i + 1 < tria_objects.used.size())
2249 {
2250 if (tria_objects.used[i + 1])
2251 {
2252 ++n_unused_singles;
2253 if (tria_objects.next_free_single == 0)
2254 tria_objects.next_free_single = i;
2255 }
2256 else
2257 {
2258 ++n_unused_pairs;
2259 if (tria_objects.next_free_pair == 0)
2260 tria_objects.next_free_pair = i;
2261 ++i;
2262 }
2263 }
2264 else
2265 ++n_unused_singles;
2266 }
2267 Assert(n_objects + 2 * n_unused_pairs + n_unused_singles ==
2268 tria_objects.used.size(),
2270
2271 // how many single objects are needed in addition to
2272 // n_unused_objects?
2273 const int additional_single_objects =
2274 new_objects_single - n_unused_singles;
2275
2276 unsigned int new_size = tria_objects.used.size() +
2277 new_objects_in_pairs - 2 * n_unused_pairs;
2278 if (additional_single_objects > 0)
2279 new_size += additional_single_objects;
2280
2281 // only allocate space if necessary
2282 if (new_size > tria_objects.n_objects())
2283 {
2284 const unsigned int max_faces_per_cell =
2285 2 * tria_objects.structdim;
2286 const unsigned int max_children_per_cell =
2287 1 << tria_objects.structdim;
2288
2289 tria_objects.cells.reserve(new_size * max_faces_per_cell);
2290 tria_objects.cells.insert(tria_objects.cells.end(),
2291 (new_size - tria_objects.n_objects()) *
2292 max_faces_per_cell,
2293 -1);
2294
2295 tria_objects.used.reserve(new_size);
2296 tria_objects.used.insert(tria_objects.used.end(),
2297 new_size - tria_objects.used.size(),
2298 false);
2299
2300 tria_objects.user_flags.reserve(new_size);
2301 tria_objects.user_flags.insert(tria_objects.user_flags.end(),
2302 new_size -
2303 tria_objects.user_flags.size(),
2304 false);
2305
2306 const unsigned int factor = max_children_per_cell / 2;
2307 tria_objects.children.reserve(factor * new_size);
2308 tria_objects.children.insert(tria_objects.children.end(),
2309 factor * new_size -
2310 tria_objects.children.size(),
2311 -1);
2312
2313 if (tria_objects.structdim > 1)
2314 {
2315 tria_objects.refinement_cases.reserve(new_size);
2316 tria_objects.refinement_cases.insert(
2317 tria_objects.refinement_cases.end(),
2318 new_size - tria_objects.refinement_cases.size(),
2319 /*RefinementCase::no_refinement=*/0);
2320 }
2321
2322 // first reserve, then resize. Otherwise the std library can
2323 // decide to allocate more entries.
2324 tria_objects.boundary_or_material_id.reserve(new_size);
2325 tria_objects.boundary_or_material_id.resize(new_size);
2326
2327 tria_objects.user_data.reserve(new_size);
2328 tria_objects.user_data.resize(new_size);
2329
2330 tria_objects.manifold_id.reserve(new_size);
2331 tria_objects.manifold_id.insert(tria_objects.manifold_id.end(),
2332 new_size -
2333 tria_objects.manifold_id.size(),
2335 }
2336
2337 if (n_unused_singles == 0)
2338 {
2339 tria_objects.next_free_single = new_size - 1;
2340 tria_objects.reverse_order_next_free_single = true;
2341 }
2342 }
2343 else
2344 {
2345 const unsigned int new_hexes = new_objects_in_pairs;
2346
2347 const unsigned int new_size =
2348 new_hexes + std::count(tria_objects.used.begin(),
2349 tria_objects.used.end(),
2350 true);
2351
2352 // see above...
2353 if (new_size > tria_objects.n_objects())
2354 {
2355 const unsigned int max_faces_per_cell =
2356 2 * tria_objects.structdim;
2357
2358 tria_objects.cells.reserve(new_size * max_faces_per_cell);
2359 tria_objects.cells.insert(tria_objects.cells.end(),
2360 (new_size - tria_objects.n_objects()) *
2361 max_faces_per_cell,
2362 -1);
2363
2364 tria_objects.used.reserve(new_size);
2365 tria_objects.used.insert(tria_objects.used.end(),
2366 new_size - tria_objects.used.size(),
2367 false);
2368
2369 tria_objects.user_flags.reserve(new_size);
2370 tria_objects.user_flags.insert(tria_objects.user_flags.end(),
2371 new_size -
2372 tria_objects.user_flags.size(),
2373 false);
2374
2375 tria_objects.children.reserve(4 * new_size);
2376 tria_objects.children.insert(tria_objects.children.end(),
2377 4 * new_size -
2378 tria_objects.children.size(),
2379 -1);
2380
2381 // for the following fields, we know exactly how many elements
2382 // we need, so first reserve then resize (resize itself, at least
2383 // with some compiler libraries, appears to round up the size it
2384 // actually reserves)
2385 tria_objects.boundary_or_material_id.reserve(new_size);
2386 tria_objects.boundary_or_material_id.resize(new_size);
2387
2388 tria_objects.manifold_id.reserve(new_size);
2389 tria_objects.manifold_id.insert(tria_objects.manifold_id.end(),
2390 new_size -
2391 tria_objects.manifold_id.size(),
2393
2394 tria_objects.user_data.reserve(new_size);
2395 tria_objects.user_data.resize(new_size);
2396
2397 tria_objects.refinement_cases.reserve(new_size);
2398 tria_objects.refinement_cases.insert(
2399 tria_objects.refinement_cases.end(),
2400 new_size - tria_objects.refinement_cases.size(),
2401 /*RefinementCase::no_refinement=*/0);
2402 }
2403 tria_objects.next_free_single = tria_objects.next_free_pair = 0;
2404 }
2405 }
2406
2407
2408
2414 void
2415 monitor_memory(const TriaObjects &tria_object, const unsigned int)
2416 {
2417 Assert(tria_object.n_objects() == tria_object.used.size(),
2418 ExcMemoryInexact(tria_object.n_objects(),
2419 tria_object.used.size()));
2420 Assert(tria_object.n_objects() == tria_object.user_flags.size(),
2421 ExcMemoryInexact(tria_object.n_objects(),
2422 tria_object.user_flags.size()));
2423 Assert(tria_object.n_objects() ==
2424 tria_object.boundary_or_material_id.size(),
2425 ExcMemoryInexact(tria_object.n_objects(),
2426 tria_object.boundary_or_material_id.size()));
2427 Assert(tria_object.n_objects() == tria_object.manifold_id.size(),
2428 ExcMemoryInexact(tria_object.n_objects(),
2429 tria_object.manifold_id.size()));
2430 Assert(tria_object.n_objects() == tria_object.user_data.size(),
2431 ExcMemoryInexact(tria_object.n_objects(),
2432 tria_object.user_data.size()));
2433
2434 if (tria_object.structdim == 1)
2435 {
2436 Assert(1 * tria_object.n_objects() == tria_object.children.size(),
2437 ExcMemoryInexact(tria_object.n_objects(),
2438 tria_object.children.size()));
2439 }
2440 else if (tria_object.structdim == 2)
2441 {
2442 Assert(2 * tria_object.n_objects() == tria_object.children.size(),
2443 ExcMemoryInexact(tria_object.n_objects(),
2444 tria_object.children.size()));
2445 }
2446 else if (tria_object.structdim == 3)
2447 {
2448 Assert(4 * tria_object.n_objects() == tria_object.children.size(),
2449 ExcMemoryInexact(tria_object.n_objects(),
2450 tria_object.children.size()));
2451 }
2452 }
2453
2454
2455
2460 template <int dim, int spacedim>
2462 {
2463 public:
2467 virtual ~Policy() = default;
2468
2472 virtual void
2474
2478 virtual void
2482 std::vector<unsigned int> &line_cell_count,
2483 std::vector<unsigned int> &quad_cell_count) = 0;
2484
2490 const bool check_for_distorted_cells) = 0;
2491
2495 virtual void
2498
2502 virtual void
2505
2509 virtual bool
2511 const typename Triangulation<dim, spacedim>::cell_iterator &cell) = 0;
2512
2519 virtual std::unique_ptr<Policy<dim, spacedim>>
2520 clone() = 0;
2521 };
2522
2523
2524
2530 template <int dim, int spacedim, typename T>
2531 class PolicyWrapper : public Policy<dim, spacedim>
2532 {
2533 public:
2534 void
2536 {
2537 T::update_neighbors(tria);
2538 }
2539
2540 void
2544 std::vector<unsigned int> &line_cell_count,
2545 std::vector<unsigned int> &quad_cell_count) override
2546 {
2547 T::delete_children(tria, cell, line_cell_count, quad_cell_count);
2548 }
2549
2552 const bool check_for_distorted_cells) override
2553 {
2554 return T::execute_refinement(triangulation, check_for_distorted_cells);
2555 }
2556
2557 void
2560 {
2561 T::prevent_distorted_boundary_cells(triangulation);
2562 }
2563
2564 void
2567 {
2568 T::prepare_refinement_dim_dependent(triangulation);
2569 }
2570
2571 bool
2574 override
2575 {
2576 return T::template coarsening_allowed<dim, spacedim>(cell);
2577 }
2578
2579 std::unique_ptr<Policy<dim, spacedim>>
2580 clone() override
2581 {
2582 return std::make_unique<PolicyWrapper<dim, spacedim, T>>();
2583 }
2584 };
2585
2586
2587
2684 {
2696 template <int dim, int spacedim>
2697 static void
2700 const unsigned int level_objects,
2702 {
2703 using line_iterator =
2705
2706 number_cache.n_levels = 0;
2707 if (level_objects > 0)
2708 // find the last level on which there are used cells
2709 for (unsigned int level = 0; level < level_objects; ++level)
2710 if (triangulation.begin(level) != triangulation.end(level))
2711 number_cache.n_levels = level + 1;
2712
2713 // no cells at all?
2714 Assert(number_cache.n_levels > 0, ExcInternalError());
2715
2716 //---------------------------------
2717 // update the number of lines on the different levels in the
2718 // cache
2719 number_cache.n_lines = 0;
2720 number_cache.n_active_lines = 0;
2721
2722 // for 1d, lines have levels so take count the objects per
2723 // level and globally
2724 if (dim == 1)
2725 {
2726 number_cache.n_lines_level.resize(number_cache.n_levels);
2727 number_cache.n_active_lines_level.resize(number_cache.n_levels);
2728
2729 for (unsigned int level = 0; level < number_cache.n_levels; ++level)
2730 {
2731 // count lines on this level
2732 number_cache.n_lines_level[level] = 0;
2733 number_cache.n_active_lines_level[level] = 0;
2734
2735 line_iterator line = triangulation.begin_line(level),
2736 endc =
2737 (level == number_cache.n_levels - 1 ?
2738 line_iterator(triangulation.end_line()) :
2739 triangulation.begin_line(level + 1));
2740 for (; line != endc; ++line)
2741 {
2742 ++number_cache.n_lines_level[level];
2743 if (line->has_children() == false)
2744 ++number_cache.n_active_lines_level[level];
2745 }
2746
2747 // update total number of lines
2748 number_cache.n_lines += number_cache.n_lines_level[level];
2749 number_cache.n_active_lines +=
2750 number_cache.n_active_lines_level[level];
2751 }
2752 }
2753 else
2754 {
2755 // for dim>1, there are no levels for lines
2756 number_cache.n_lines_level.clear();
2757 number_cache.n_active_lines_level.clear();
2758
2759 line_iterator line = triangulation.begin_line(),
2760 endc = triangulation.end_line();
2761 for (; line != endc; ++line)
2762 {
2763 ++number_cache.n_lines;
2764 if (line->has_children() == false)
2765 ++number_cache.n_active_lines;
2766 }
2767 }
2768 }
2769
2784 template <int dim, int spacedim>
2785 static void
2788 const unsigned int level_objects,
2790 {
2791 // update lines and n_levels in number_cache. since we don't
2792 // access any of these numbers, we can do this in the
2793 // background
2795 static_cast<
2796 void (*)(const Triangulation<dim, spacedim> &,
2797 const unsigned int,
2799 &compute_number_cache_dim<dim, spacedim>),
2801 level_objects,
2803 number_cache));
2804
2805 using quad_iterator =
2807
2808 //---------------------------------
2809 // update the number of quads on the different levels in the
2810 // cache
2811 number_cache.n_quads = 0;
2812 number_cache.n_active_quads = 0;
2813
2814 // for 2d, quads have levels so take count the objects per
2815 // level and globally
2816 if (dim == 2)
2817 {
2818 // count the number of levels; the function we called above
2819 // on a separate Task for lines also does this and puts it into
2820 // number_cache.n_levels, but this datum may not yet be
2821 // available as we call the function on a separate task
2822 unsigned int n_levels = 0;
2823 if (level_objects > 0)
2824 // find the last level on which there are used cells
2825 for (unsigned int level = 0; level < level_objects; ++level)
2826 if (triangulation.begin(level) != triangulation.end(level))
2827 n_levels = level + 1;
2828
2829 number_cache.n_quads_level.resize(n_levels);
2830 number_cache.n_active_quads_level.resize(n_levels);
2831
2832 for (unsigned int level = 0; level < n_levels; ++level)
2833 {
2834 // count quads on this level
2835 number_cache.n_quads_level[level] = 0;
2836 number_cache.n_active_quads_level[level] = 0;
2837
2838 quad_iterator quad = triangulation.begin_quad(level),
2839 endc =
2840 (level == n_levels - 1 ?
2841 quad_iterator(triangulation.end_quad()) :
2842 triangulation.begin_quad(level + 1));
2843 for (; quad != endc; ++quad)
2844 {
2845 ++number_cache.n_quads_level[level];
2846 if (quad->has_children() == false)
2847 ++number_cache.n_active_quads_level[level];
2848 }
2849
2850 // update total number of quads
2851 number_cache.n_quads += number_cache.n_quads_level[level];
2852 number_cache.n_active_quads +=
2853 number_cache.n_active_quads_level[level];
2854 }
2855 }
2856 else
2857 {
2858 // for dim>2, there are no levels for quads
2859 number_cache.n_quads_level.clear();
2860 number_cache.n_active_quads_level.clear();
2861
2862 quad_iterator quad = triangulation.begin_quad(),
2863 endc = triangulation.end_quad();
2864 for (; quad != endc; ++quad)
2865 {
2866 ++number_cache.n_quads;
2867 if (quad->has_children() == false)
2868 ++number_cache.n_active_quads;
2869 }
2870 }
2871
2872 // wait for the background computation for lines
2873 update_lines.join();
2874 }
2875
2891 template <int dim, int spacedim>
2892 static void
2895 const unsigned int level_objects,
2897 {
2898 // update quads, lines and n_levels in number_cache. since we
2899 // don't access any of these numbers, we can do this in the
2900 // background
2901 Threads::Task<void> update_quads_and_lines = Threads::new_task(
2902 static_cast<
2903 void (*)(const Triangulation<dim, spacedim> &,
2904 const unsigned int,
2906 &compute_number_cache_dim<dim, spacedim>),
2908 level_objects,
2910 number_cache));
2911
2912 using hex_iterator =
2914
2915 //---------------------------------
2916 // update the number of hexes on the different levels in the
2917 // cache
2918 number_cache.n_hexes = 0;
2919 number_cache.n_active_hexes = 0;
2920
2921 // for 3d, hexes have levels so take count the objects per
2922 // level and globally
2923 if (dim == 3)
2924 {
2925 // count the number of levels; the function we called
2926 // above on a separate Task for quads (recursively, via
2927 // the lines function) also does this and puts it into
2928 // number_cache.n_levels, but this datum may not yet be
2929 // available as we call the function on a separate task
2930 unsigned int n_levels = 0;
2931 if (level_objects > 0)
2932 // find the last level on which there are used cells
2933 for (unsigned int level = 0; level < level_objects; ++level)
2934 if (triangulation.begin(level) != triangulation.end(level))
2935 n_levels = level + 1;
2936
2937 number_cache.n_hexes_level.resize(n_levels);
2938 number_cache.n_active_hexes_level.resize(n_levels);
2939
2940 for (unsigned int level = 0; level < n_levels; ++level)
2941 {
2942 // count hexes on this level
2943 number_cache.n_hexes_level[level] = 0;
2944 number_cache.n_active_hexes_level[level] = 0;
2945
2946 hex_iterator hex = triangulation.begin_hex(level),
2947 endc = (level == n_levels - 1 ?
2948 hex_iterator(triangulation.end_hex()) :
2949 triangulation.begin_hex(level + 1));
2950 for (; hex != endc; ++hex)
2951 {
2952 ++number_cache.n_hexes_level[level];
2953 if (hex->has_children() == false)
2954 ++number_cache.n_active_hexes_level[level];
2955 }
2956
2957 // update total number of hexes
2958 number_cache.n_hexes += number_cache.n_hexes_level[level];
2959 number_cache.n_active_hexes +=
2960 number_cache.n_active_hexes_level[level];
2961 }
2962 }
2963 else
2964 {
2965 // for dim>3, there are no levels for hexes
2966 number_cache.n_hexes_level.clear();
2967 number_cache.n_active_hexes_level.clear();
2968
2969 hex_iterator hex = triangulation.begin_hex(),
2970 endc = triangulation.end_hex();
2971 for (; hex != endc; ++hex)
2972 {
2973 ++number_cache.n_hexes;
2974 if (hex->has_children() == false)
2975 ++number_cache.n_active_hexes;
2976 }
2977 }
2978
2979 // wait for the background computation for quads
2980 update_quads_and_lines.join();
2981 }
2982
2983
2984 template <int dim, int spacedim>
2985 static void
2988 const unsigned int level_objects,
2990 {
2991 compute_number_cache_dim(triangulation, level_objects, number_cache);
2992
2993 number_cache.active_cell_index_partitioner =
2994 std::make_shared<const Utilities::MPI::Partitioner>(
2995 triangulation.n_active_cells());
2996
2997 number_cache.level_cell_index_partitioners.resize(
2998 triangulation.n_levels());
2999 for (unsigned int level = 0; level < triangulation.n_levels(); ++level)
3000 number_cache.level_cell_index_partitioners[level] =
3001 std::make_shared<const Utilities::MPI::Partitioner>(
3002 triangulation.n_cells(level));
3003 }
3004
3005
3006 template <int spacedim>
3007 static void
3010
3011
3012 template <int dim, int spacedim>
3013 static void
3015 {
3016 // each face can be neighbored on two sides
3017 // by cells. according to the face's
3018 // intrinsic normal we define the left
3019 // neighbor as the one for which the face
3020 // normal points outward, and store that
3021 // one first; the second one is then
3022 // the right neighbor for which the
3023 // face normal points inward. This
3024 // information depends on the type of cell
3025 // and local number of face for the
3026 // 'standard ordering and orientation' of
3027 // faces and then on the face_orientation
3028 // information for the real mesh. Set up a
3029 // table to have fast access to those
3030 // offsets (0 for left and 1 for
3031 // right). Some of the values are invalid
3032 // as they reference too large face
3033 // numbers, but we just leave them at a
3034 // zero value.
3035 //
3036 // Note, that in 2d for lines as faces the
3037 // normal direction given in the
3038 // GeometryInfo class is not consistent. We
3039 // thus define here that the normal for a
3040 // line points to the right if the line
3041 // points upwards.
3042 //
3043 // There is one more point to
3044 // consider, however: if we have
3045 // dim<spacedim, then we may have
3046 // cases where cells are
3047 // inverted. In effect, both
3048 // cells think they are the left
3049 // neighbor of an edge, for
3050 // example, which leads us to
3051 // forget neighborship
3052 // information (a case that shows
3053 // this is
3054 // codim_one/hanging_nodes_02). We
3055 // store whether a cell is
3056 // inverted using the
3057 // direction_flag, so if a cell
3058 // has a false direction_flag,
3059 // then we need to invert our
3060 // selection whether we are a
3061 // left or right neighbor in all
3062 // following computations.
3063 //
3064 // first index: dimension (minus 2)
3065 // second index: local face index
3066 // third index: face_orientation (false and true)
3067 static const unsigned int left_right_offset[2][6][2] = {
3068 // quadrilateral
3069 {{0, 1}, // face 0, face_orientation = false and true
3070 {1, 0}, // face 1, face_orientation = false and true
3071 {1, 0}, // face 2, face_orientation = false and true
3072 {0, 1}, // face 3, face_orientation = false and true
3073 {0, 0}, // face 4, invalid face
3074 {0, 0}}, // face 5, invalid face
3075 // hexahedron
3076 {{0, 1}, {1, 0}, {0, 1}, {1, 0}, {0, 1}, {1, 0}}};
3077
3078 // now create a vector of the two active
3079 // neighbors (left and right) for each face
3080 // and fill it by looping over all cells. For
3081 // cases with anisotropic refinement and more
3082 // then one cell neighboring at a given side
3083 // of the face we will automatically get the
3084 // active one on the highest level as we loop
3085 // over cells from lower levels first.
3087 std::vector<typename Triangulation<dim, spacedim>::cell_iterator>
3088 adjacent_cells(2 * triangulation.n_raw_faces(), dummy);
3089
3090 for (const auto &cell : triangulation.cell_iterators())
3091 for (auto f : cell->face_indices())
3092 {
3094 cell->face(f);
3095
3096 const unsigned int offset =
3097 (cell->direction_flag() ?
3098 left_right_offset[dim - 2][f][cell->face_orientation(f)] :
3099 1 -
3100 left_right_offset[dim - 2][f][cell->face_orientation(f)]);
3101
3102 adjacent_cells[2 * face->index() + offset] = cell;
3103
3104 // if this cell is not refined, but the
3105 // face is, then we'll have to set our
3106 // cell as neighbor for the child faces
3107 // as well. Fortunately the normal
3108 // orientation of children will be just
3109 // the same.
3110 if (dim == 2)
3111 {
3112 if (cell->is_active() && face->has_children())
3113 {
3114 adjacent_cells[2 * face->child(0)->index() + offset] =
3115 cell;
3116 adjacent_cells[2 * face->child(1)->index() + offset] =
3117 cell;
3118 }
3119 }
3120 else // -> dim == 3
3121 {
3122 // We need the same as in 2d
3123 // here. Furthermore, if the face is
3124 // refined with cut_x or cut_y then
3125 // those children again in the other
3126 // direction, and if this cell is
3127 // refined isotropically (along the
3128 // face) then the neighbor will
3129 // (probably) be refined as cut_x or
3130 // cut_y along the face. For those
3131 // neighboring children cells, their
3132 // neighbor will be the current,
3133 // inactive cell, as our children are
3134 // too fine to be neighbors. Catch that
3135 // case by also acting on inactive
3136 // cells with isotropic refinement
3137 // along the face. If the situation
3138 // described is not present, the data
3139 // will be overwritten later on when we
3140 // visit cells on finer levels, so no
3141 // harm will be done.
3142 if (face->has_children() &&
3143 (cell->is_active() ||
3145 cell->refinement_case(), f) ==
3147 {
3148 for (unsigned int c = 0; c < face->n_children(); ++c)
3149 adjacent_cells[2 * face->child(c)->index() + offset] =
3150 cell;
3151 if (face->child(0)->has_children())
3152 {
3153 adjacent_cells[2 * face->child(0)->child(0)->index() +
3154 offset] = cell;
3155 adjacent_cells[2 * face->child(0)->child(1)->index() +
3156 offset] = cell;
3157 }
3158 if (face->child(1)->has_children())
3159 {
3160 adjacent_cells[2 * face->child(1)->child(0)->index() +
3161 offset] = cell;
3162 adjacent_cells[2 * face->child(1)->child(1)->index() +
3163 offset] = cell;
3164 }
3165 } // if cell active and face refined
3166 } // else -> dim==3
3167 } // for all faces of all cells
3168
3169 // now loop again over all cells and set the
3170 // corresponding neighbor cell. Note, that we
3171 // have to use the opposite of the
3172 // left_right_offset in this case as we want
3173 // the offset of the neighbor, not our own.
3174 for (const auto &cell : triangulation.cell_iterators())
3175 for (auto f : cell->face_indices())
3176 {
3177 const unsigned int offset =
3178 (cell->direction_flag() ?
3179 left_right_offset[dim - 2][f][cell->face_orientation(f)] :
3180 1 -
3181 left_right_offset[dim - 2][f][cell->face_orientation(f)]);
3182 cell->set_neighbor(
3183 f, adjacent_cells[2 * cell->face(f)->index() + 1 - offset]);
3184 }
3185 }
3186
3187
3191 template <int dim, int spacedim>
3192 static void
3194 const std::vector<CellData<dim>> &cells,
3195 const SubCellData &subcelldata,
3197 {
3198 AssertThrow(vertices.size() > 0, ExcMessage("No vertices given"));
3199 AssertThrow(cells.size() > 0, ExcMessage("No cells given"));
3200
3201 // Check that all cells have positive volume.
3202#ifndef _MSC_VER
3203 // TODO: The following code does not compile with MSVC. Find a way
3204 // around it
3205 if (dim == spacedim)
3206 for (unsigned int cell_no = 0; cell_no < cells.size(); ++cell_no)
3207 {
3208 // If we should check for distorted cells, then we permit them
3209 // to exist. If a cell has negative measure, then it must be
3210 // distorted (the converse is not necessarily true); hence
3211 // throw an exception if no such cells should exist.
3213 {
3214 const double cell_measure = GridTools::cell_measure<spacedim>(
3215 vertices,
3216 ArrayView<const unsigned int>(cells[cell_no].vertices));
3217 AssertThrow(cell_measure > 0, ExcGridHasInvalidCell(cell_no));
3218 }
3219 }
3220#endif
3221
3222 // clear old content
3223 tria.levels.clear();
3224 tria.levels.push_back(
3225 std::make_unique<
3227
3228 if (dim > 1)
3229 tria.faces = std::make_unique<
3231
3232 // copy vertices
3233 tria.vertices = vertices;
3234 tria.vertices_used.assign(vertices.size(), true);
3235
3236 // compute connectivity
3237 const auto connectivity = build_connectivity<unsigned int>(cells);
3238 const unsigned int n_cell = cells.size();
3239
3240 // TriaObjects: lines
3241 if (dim >= 2)
3242 {
3243 auto &lines_0 = tria.faces->lines; // data structure to be filled
3244
3245 // get connectivity between quads and lines
3246 const auto &crs = connectivity.entity_to_entities(1, 0);
3247 const unsigned int n_lines = crs.ptr.size() - 1;
3248
3249 // allocate memory
3250 reserve_space_(lines_0, n_lines);
3251
3252 // loop over lines
3253 for (unsigned int line = 0; line < n_lines; ++line)
3254 for (unsigned int i = crs.ptr[line], j = 0; i < crs.ptr[line + 1];
3255 ++i, ++j)
3256 lines_0.cells[line * GeometryInfo<1>::faces_per_cell + j] =
3257 crs.col[i]; // set vertex indices
3258 }
3259
3260 // TriaObjects: quads
3261 if (dim == 3)
3262 {
3263 auto &quads_0 = tria.faces->quads; // data structures to be filled
3264 auto &faces = *tria.faces;
3265
3266 // get connectivity between quads and lines
3267 const auto &crs = connectivity.entity_to_entities(2, 1);
3268 const unsigned int n_quads = crs.ptr.size() - 1;
3269
3270 // allocate memory
3271 reserve_space_(quads_0, n_quads);
3272 reserve_space_(faces, 2 /*structdim*/, n_quads);
3273
3274 // loop over all quads -> entity type, line indices/orientations
3275 for (unsigned int q = 0, k = 0; q < n_quads; ++q)
3276 {
3277 // set entity type of quads
3278 faces.set_quad_type(q, connectivity.entity_types(2)[q]);
3279
3280 // loop over all its lines
3281 for (unsigned int i = crs.ptr[q], j = 0; i < crs.ptr[q + 1];
3282 ++i, ++j, ++k)
3283 {
3284 // set line index
3285 quads_0.cells[q * GeometryInfo<3>::lines_per_face + j] =
3286 crs.col[i];
3287
3288 // set line orientations
3289 const unsigned char combined_orientation =
3290 connectivity.entity_orientations(1)
3291 .get_combined_orientation(k);
3292 // it doesn't make sense to set any flags except
3293 // orientation for a line
3294 Assert(
3295 combined_orientation ==
3297 combined_orientation ==
3300 faces.quads_line_orientations
3302 combined_orientation ==
3304 }
3305 }
3306 }
3307
3308 // TriaObjects/TriaLevel: cell
3309 {
3310 auto &cells_0 = tria.levels[0]->cells; // data structure to be filled
3311 auto &level = *tria.levels[0];
3312
3313 // get connectivity between cells/faces and cells/cells
3314 const auto &crs = connectivity.entity_to_entities(dim, dim - 1);
3315 const auto &nei = connectivity.entity_to_entities(dim, dim);
3316
3317 // in 2d optional: since in in pure QUAD meshes same line
3318 // orientations can be guaranteed
3319 bool orientation_needed = false;
3320 if (dim == 3)
3321 orientation_needed = true;
3322 else if (dim == 2)
3323 {
3324 const auto &orientations = connectivity.entity_orientations(1);
3325 for (unsigned int i = 0; i < orientations.n_objects(); ++i)
3326 if (orientations.get_combined_orientation(i) !=
3328 {
3329 orientation_needed = true;
3330 break;
3331 }
3332 }
3333
3334 // allocate memory
3335 reserve_space_(cells_0, n_cell);
3336 reserve_space_(level, spacedim, n_cell, orientation_needed);
3337
3338 // loop over all cells
3339 for (unsigned int cell = 0; cell < n_cell; ++cell)
3340 {
3341 // set material ids
3342 cells_0.boundary_or_material_id[cell].material_id =
3343 cells[cell].material_id;
3344
3345 // set manifold ids
3346 cells_0.manifold_id[cell] = cells[cell].manifold_id;
3347
3348 // set entity types
3349 level.reference_cell[cell] = connectivity.entity_types(dim)[cell];
3350
3351 // loop over faces
3352 for (unsigned int i = crs.ptr[cell], j = 0; i < crs.ptr[cell + 1];
3353 ++i, ++j)
3354 {
3355 // set neighbor if not at boundary
3356 if (nei.col[i] != static_cast<unsigned int>(-1))
3357 level.neighbors[cell * GeometryInfo<dim>::faces_per_cell +
3358 j] = {0, nei.col[i]};
3359
3360 // set face indices
3361 cells_0.cells[cell * GeometryInfo<dim>::faces_per_cell + j] =
3362 crs.col[i];
3363
3364 // set face orientation if needed
3365 if (orientation_needed)
3366 {
3367 level.face_orientations.set_combined_orientation(
3369 connectivity.entity_orientations(dim - 1)
3370 .get_combined_orientation(i));
3371 }
3372 }
3373 }
3374 }
3375
3376 // TriaFaces: boundary id of boundary faces
3377 if (dim > 1)
3378 {
3379 auto &bids_face = dim == 3 ?
3380 tria.faces->quads.boundary_or_material_id :
3381 tria.faces->lines.boundary_or_material_id;
3382
3383 // count number of cells a face is belonging to
3384 std::vector<unsigned int> count(bids_face.size(), 0);
3385
3386 // get connectivity between cells/faces
3387 const auto &crs = connectivity.entity_to_entities(dim, dim - 1);
3388
3389 // count how many cells are adjacent to the same face
3390 for (unsigned int cell = 0; cell < cells.size(); ++cell)
3391 for (unsigned int i = crs.ptr[cell]; i < crs.ptr[cell + 1]; ++i)
3392 count[crs.col[i]]++;
3393
3394 // loop over all faces
3395 for (unsigned int face = 0; face < count.size(); ++face)
3396 {
3397 if (count[face] != 1) // inner face
3398 continue;
3399
3400 // boundary faces ...
3401 bids_face[face].boundary_id = 0;
3402
3403 if (dim != 3)
3404 continue;
3405
3406 // ... and the lines of quads in 3d
3407 const auto &crs = connectivity.entity_to_entities(2, 1);
3408 for (unsigned int i = crs.ptr[face]; i < crs.ptr[face + 1]; ++i)
3409 tria.faces->lines.boundary_or_material_id[crs.col[i]]
3410 .boundary_id = 0;
3411 }
3412 }
3413 else // 1d
3414 {
3415 static const unsigned int t_tba = static_cast<unsigned int>(-1);
3416 static const unsigned int t_inner = static_cast<unsigned int>(-2);
3417
3418 std::vector<unsigned int> type(vertices.size(), t_tba);
3419
3420 const auto &crs = connectivity.entity_to_entities(1, 0);
3421
3422 for (unsigned int cell = 0; cell < cells.size(); ++cell)
3423 for (unsigned int i = crs.ptr[cell], j = 0; i < crs.ptr[cell + 1];
3424 ++i, ++j)
3425 if (type[crs.col[i]] != t_inner)
3426 type[crs.col[i]] = type[crs.col[i]] == t_tba ? j : t_inner;
3427
3428 for (unsigned int face = 0; face < type.size(); ++face)
3429 {
3430 // note: we also treat manifolds here!?
3431 (*tria.vertex_to_manifold_id_map_1d)[face] =
3433 if (type[face] != t_inner && type[face] != t_tba)
3434 (*tria.vertex_to_boundary_id_map_1d)[face] = type[face];
3435 }
3436 }
3437
3438 // SubCellData: line
3439 if (dim >= 2)
3440 process_subcelldata(connectivity.entity_to_entities(1, 0),
3441 tria.faces->lines,
3442 subcelldata.boundary_lines,
3443 vertices);
3444
3445 // SubCellData: quad
3446 if (dim == 3)
3447 process_subcelldata(connectivity.entity_to_entities(2, 0),
3448 tria.faces->quads,
3449 subcelldata.boundary_quads,
3450 vertices);
3451 }
3452
3453
3454 template <int structdim, int spacedim, typename T>
3455 static void
3457 const CRS<T> &crs,
3458 TriaObjects &obj,
3459 const std::vector<CellData<structdim>> &boundary_objects_in,
3460 const std::vector<Point<spacedim>> &vertex_locations)
3461 {
3462 AssertDimension(obj.structdim, structdim);
3463
3464 if (boundary_objects_in.empty())
3465 return; // empty subcelldata -> nothing to do
3466
3467 // pre-sort subcelldata
3468 auto boundary_objects = boundary_objects_in;
3469
3470 // ... sort vertices
3471 for (auto &boundary_object : boundary_objects)
3472 std::sort(boundary_object.vertices.begin(),
3473 boundary_object.vertices.end());
3474
3475 // ... sort cells
3476 std::sort(boundary_objects.begin(),
3477 boundary_objects.end(),
3478 [](const auto &a, const auto &b) {
3479 return a.vertices < b.vertices;
3480 });
3481
3482 [[maybe_unused]] unsigned int counter = 0;
3483
3484 std::vector<unsigned int> key;
3486
3487 for (unsigned int o = 0; o < obj.n_objects(); ++o)
3488 {
3489 auto &boundary_id = obj.boundary_or_material_id[o].boundary_id;
3490 auto &manifold_id = obj.manifold_id[o];
3491
3492 // assert that object has not been visited yet and its value
3493 // has not been modified yet
3494 AssertThrow(boundary_id == 0 ||
3499
3500 // create key
3501 key.assign(crs.col.data() + crs.ptr[o],
3502 crs.col.data() + crs.ptr[o + 1]);
3503 std::sort(key.begin(), key.end());
3504
3505 // is subcelldata provided? -> binary search
3506 const auto subcell_object =
3507 std::lower_bound(boundary_objects.begin(),
3508 boundary_objects.end(),
3509 key,
3510 [&](const auto &cell, const auto &key) {
3511 return cell.vertices < key;
3512 });
3513
3514 // no subcelldata provided for this object
3515 if (subcell_object == boundary_objects.end() ||
3516 subcell_object->vertices != key)
3517 continue;
3518
3519 ++counter;
3520
3521 // set manifold id
3522 manifold_id = subcell_object->manifold_id;
3523
3524 // set boundary id
3525 if (subcell_object->boundary_id !=
3527 {
3530 ExcMessage(
3531 "The input arguments for creating a triangulation "
3532 "specified a boundary id for an internal face. This "
3533 "is not allowed."
3534 "\n\n"
3535 "The object in question has vertex indices " +
3536 [subcell_object]() {
3537 std::string s;
3538 for (const auto v : subcell_object->vertices)
3539 s += std::to_string(v) + ',';
3540 return s;
3541 }() +
3542 " which are located at positions " +
3543 [vertex_locations, subcell_object]() {
3544 std::ostringstream s;
3545 for (const auto v : subcell_object->vertices)
3546 s << '(' << vertex_locations[v] << ')';
3547 return s.str();
3548 }() +
3549 "."));
3550 boundary_id = subcell_object->boundary_id;
3551 }
3552 }
3553
3554 // make sure that all subcelldata entries have been processed
3555 // TODO: this is not guaranteed, why?
3556 // AssertDimension(counter, boundary_objects_in.size());
3557 }
3558
3559
3560
3561 static void
3563 const unsigned structdim,
3564 const unsigned int size)
3565 {
3566 const unsigned int dim = faces.dim;
3567
3568 const unsigned int max_lines_per_face = 2 * structdim;
3569
3570 if (dim == 3 && structdim == 2)
3571 {
3572 // quad entity types
3573 faces.quad_is_quadrilateral.assign(size, true);
3574
3575 // quad line orientations
3576 faces.quads_line_orientations.assign(size * max_lines_per_face,
3577 true);
3578 }
3579 }
3580
3581
3582
3583 static void
3585 const unsigned int spacedim,
3586 const unsigned int size,
3587 const bool orientation_needed)
3588 {
3589 const unsigned int dim = level.dim;
3590
3591 const unsigned int max_faces_per_cell = 2 * dim;
3592
3593 level.active_cell_indices.assign(size, numbers::invalid_unsigned_int);
3594 level.subdomain_ids.assign(size, 0);
3595 level.level_subdomain_ids.assign(size, 0);
3596
3597 level.refine_flags.assign(size, 0u);
3598 level.refine_choice.assign(size, 0u);
3599 level.coarsen_flags.assign(size, false);
3600
3601 level.parents.assign((size + 1) / 2, -1);
3602
3603 if (dim == spacedim - 1)
3604 level.direction_flags.assign(size, true);
3605
3606 level.neighbors.assign(size * max_faces_per_cell, {-1, -1});
3607
3608 level.reference_cell.assign(size, ReferenceCells::Invalid);
3609
3610 if (orientation_needed)
3611 level.face_orientations.reinit(size * max_faces_per_cell);
3612
3613
3614 level.global_active_cell_indices.assign(size,
3616 level.global_level_cell_indices.assign(size,
3618 }
3619
3620
3621
3622 static void
3623 reserve_space_(TriaObjects &obj, const unsigned int size)
3624 {
3625 const unsigned int structdim = obj.structdim;
3626
3627 const unsigned int max_children_per_cell = 1 << structdim;
3628 const unsigned int max_faces_per_cell = 2 * structdim;
3629
3630 obj.used.assign(size, true);
3631 obj.boundary_or_material_id.assign(
3632 size,
3634 BoundaryOrMaterialId());
3635 obj.manifold_id.assign(size, -1);
3636 obj.user_flags.assign(size, false);
3637 obj.user_data.resize(size);
3638
3639 if (structdim > 1) // TODO: why?
3640 obj.refinement_cases.assign(size, 0);
3641
3642 obj.children.assign(max_children_per_cell / 2 * size, -1);
3643
3644 obj.cells.assign(max_faces_per_cell * size, -1);
3645
3646 if (structdim <= 2)
3647 {
3648 obj.next_free_single = size - 1;
3649 obj.next_free_pair = 0;
3651 }
3652 else
3653 {
3654 obj.next_free_single = obj.next_free_pair = 0;
3655 }
3656 }
3657
3658
3674 template <int spacedim>
3675 static void
3678 std::vector<unsigned int> &,
3679 std::vector<unsigned int> &)
3680 {
3681 const unsigned int dim = 1;
3682
3683 // first we need to reset the
3684 // neighbor pointers of the
3685 // neighbors of this cell's
3686 // children to this cell. This is
3687 // different for one dimension,
3688 // since there neighbors can have a
3689 // refinement level differing from
3690 // that of this cell's children by
3691 // more than one level.
3692
3693 Assert(!cell->child(0)->has_children() &&
3694 !cell->child(1)->has_children(),
3696
3697 // first do it for the cells to the
3698 // left
3699 if (cell->neighbor(0).state() == IteratorState::valid)
3700 if (cell->neighbor(0)->has_children())
3701 {
3703 cell->neighbor(0);
3704 Assert(neighbor->level() == cell->level(), ExcInternalError());
3705
3706 // right child
3707 neighbor = neighbor->child(1);
3708 while (true)
3709 {
3710 Assert(neighbor->neighbor(1) == cell->child(0),
3712 neighbor->set_neighbor(1, cell);
3713
3714 // move on to further
3715 // children on the
3716 // boundary between this
3717 // cell and its neighbor
3718 if (neighbor->has_children())
3719 neighbor = neighbor->child(1);
3720 else
3721 break;
3722 }
3723 }
3724
3725 // now do it for the cells to the
3726 // left
3727 if (cell->neighbor(1).state() == IteratorState::valid)
3728 if (cell->neighbor(1)->has_children())
3729 {
3731 cell->neighbor(1);
3732 Assert(neighbor->level() == cell->level(), ExcInternalError());
3733
3734 // left child
3735 neighbor = neighbor->child(0);
3736 while (true)
3737 {
3738 Assert(neighbor->neighbor(0) == cell->child(1),
3740 neighbor->set_neighbor(0, cell);
3741
3742 // move on to further
3743 // children on the
3744 // boundary between this
3745 // cell and its neighbor
3746 if (neighbor->has_children())
3747 neighbor = neighbor->child(0);
3748 else
3749 break;
3750 }
3751 }
3752
3753
3754 // delete the vertex which will not
3755 // be needed anymore. This vertex
3756 // is the second of the first child
3757 triangulation.vertices_used[cell->child(0)->vertex_index(1)] = false;
3758
3759 // invalidate children. clear user
3760 // pointers, to avoid that they may
3761 // appear at unwanted places later
3762 // on...
3763 for (unsigned int child = 0; child < cell->n_children(); ++child)
3764 {
3765 cell->child(child)->clear_user_data();
3766 cell->child(child)->clear_user_flag();
3767 cell->child(child)->clear_used_flag();
3768 }
3769
3770
3771 // delete pointer to children
3772 cell->clear_children();
3773 cell->clear_user_flag();
3774 }
3775
3776
3777
3778 template <int spacedim>
3779 static void
3782 std::vector<unsigned int> &line_cell_count,
3783 std::vector<unsigned int> &)
3784 {
3785 const unsigned int dim = 2;
3786 const RefinementCase<dim> ref_case = cell->refinement_case();
3787
3788 Assert(line_cell_count.size() == triangulation.n_raw_lines(),
3790
3791 // vectors to hold all lines which
3792 // may be deleted
3793 std::vector<typename Triangulation<dim, spacedim>::line_iterator>
3794 lines_to_delete(0);
3795
3796 lines_to_delete.reserve(4 * 2 + 4);
3797
3798 // now we decrease the counters for
3799 // lines contained in the child
3800 // cells
3801 for (unsigned int c = 0; c < cell->n_children(); ++c)
3802 {
3804 cell->child(c);
3805 for (unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++l)
3806 --line_cell_count[child->line_index(l)];
3807 }
3808
3809
3810 // delete the vertex which will not
3811 // be needed anymore. This vertex
3812 // is the second of the second line
3813 // of the first child, if the cell
3814 // is refined with cut_xy, else there
3815 // is no inner vertex.
3816 // additionally delete unneeded inner
3817 // lines
3818 if (ref_case == RefinementCase<dim>::cut_xy)
3819 {
3821 .vertices_used[cell->child(0)->line(1)->vertex_index(1)] = false;
3822
3823 lines_to_delete.push_back(cell->child(0)->line(1));
3824 lines_to_delete.push_back(cell->child(0)->line(3));
3825 lines_to_delete.push_back(cell->child(3)->line(0));
3826 lines_to_delete.push_back(cell->child(3)->line(2));
3827 }
3828 else
3829 {
3830 unsigned int inner_face_no =
3831 ref_case == RefinementCase<dim>::cut_x ? 1 : 3;
3832
3833 // the inner line will not be
3834 // used any more
3835 lines_to_delete.push_back(cell->child(0)->line(inner_face_no));
3836 }
3837
3838 // invalidate children
3839 for (unsigned int child = 0; child < cell->n_children(); ++child)
3840 {
3841 cell->child(child)->clear_user_data();
3842 cell->child(child)->clear_user_flag();
3843 cell->child(child)->clear_used_flag();
3844 }
3845
3846
3847 // delete pointer to children
3848 cell->clear_children();
3849 cell->clear_refinement_case();
3850 cell->clear_user_flag();
3851
3852 // look at the refinement of outer
3853 // lines. if nobody needs those
3854 // anymore we can add them to the
3855 // list of lines to be deleted.
3856 for (unsigned int line_no = 0;
3857 line_no < GeometryInfo<dim>::lines_per_cell;
3858 ++line_no)
3859 {
3861 cell->line(line_no);
3862
3863 if (line->has_children())
3864 {
3865 // if one of the cell counters is
3866 // zero, the other has to be as well
3867
3868 Assert((line_cell_count[line->child_index(0)] == 0 &&
3869 line_cell_count[line->child_index(1)] == 0) ||
3870 (line_cell_count[line->child_index(0)] > 0 &&
3871 line_cell_count[line->child_index(1)] > 0),
3873
3874 if (line_cell_count[line->child_index(0)] == 0)
3875 {
3876 for (unsigned int c = 0; c < 2; ++c)
3877 Assert(!line->child(c)->has_children(),
3879
3880 // we may delete the line's
3881 // children and the middle vertex
3882 // as no cell references them
3883 // anymore
3885 .vertices_used[line->child(0)->vertex_index(1)] = false;
3886
3887 lines_to_delete.push_back(line->child(0));
3888 lines_to_delete.push_back(line->child(1));
3889
3890 line->clear_children();
3891 }
3892 }
3893 }
3894
3895 // finally, delete unneeded lines
3896
3897 // clear user pointers, to avoid that
3898 // they may appear at unwanted places
3899 // later on...
3900 // same for user flags, then finally
3901 // delete the lines
3902 typename std::vector<
3904 line = lines_to_delete.begin(),
3905 endline = lines_to_delete.end();
3906 for (; line != endline; ++line)
3907 {
3908 (*line)->clear_user_data();
3909 (*line)->clear_user_flag();
3910 (*line)->clear_used_flag();
3911 }
3912 }
3913
3914
3915
3916 template <int spacedim>
3917 static void
3920 std::vector<unsigned int> &line_cell_count,
3921 std::vector<unsigned int> &quad_cell_count)
3922 {
3923 const unsigned int dim = 3;
3924
3925 Assert(line_cell_count.size() == triangulation.n_raw_lines(),
3927 Assert(quad_cell_count.size() == triangulation.n_raw_quads(),
3929
3930 // first of all, we store the RefineCase of
3931 // this cell
3932 const RefinementCase<dim> ref_case = cell->refinement_case();
3933 // vectors to hold all lines and quads which
3934 // may be deleted
3935 std::vector<typename Triangulation<dim, spacedim>::line_iterator>
3936 lines_to_delete(0);
3937 std::vector<typename Triangulation<dim, spacedim>::quad_iterator>
3938 quads_to_delete(0);
3939
3940 lines_to_delete.reserve(12 * 2 + 6 * 4 + 6);
3941 quads_to_delete.reserve(6 * 4 + 12);
3942
3943 // now we decrease the counters for lines and
3944 // quads contained in the child cells
3945 for (unsigned int c = 0; c < cell->n_children(); ++c)
3946 {
3948 cell->child(c);
3949 const auto line_indices = TriaAccessorImplementation::
3950 Implementation::get_line_indices_of_cell(*child);
3951 for (const unsigned int l : cell->line_indices())
3952 --line_cell_count[line_indices[l]];
3953 for (auto f : GeometryInfo<dim>::face_indices())
3954 --quad_cell_count[child->quad_index(f)];
3955 }
3956
3957 //-------------------------------------
3958 // delete interior quads and lines and the
3959 // interior vertex, depending on the
3960 // refinement case of the cell
3961 //
3962 // for append quads and lines: only append
3963 // them to the list of objects to be deleted
3964
3965 switch (ref_case)
3966 {
3968 quads_to_delete.push_back(cell->child(0)->face(1));
3969 break;
3971 quads_to_delete.push_back(cell->child(0)->face(3));
3972 break;
3974 quads_to_delete.push_back(cell->child(0)->face(5));
3975 break;
3977 quads_to_delete.push_back(cell->child(0)->face(1));
3978 quads_to_delete.push_back(cell->child(0)->face(3));
3979 quads_to_delete.push_back(cell->child(3)->face(0));
3980 quads_to_delete.push_back(cell->child(3)->face(2));
3981
3982 lines_to_delete.push_back(cell->child(0)->line(11));
3983 break;
3985 quads_to_delete.push_back(cell->child(0)->face(1));
3986 quads_to_delete.push_back(cell->child(0)->face(5));
3987 quads_to_delete.push_back(cell->child(3)->face(0));
3988 quads_to_delete.push_back(cell->child(3)->face(4));
3989
3990 lines_to_delete.push_back(cell->child(0)->line(5));
3991 break;
3993 quads_to_delete.push_back(cell->child(0)->face(3));
3994 quads_to_delete.push_back(cell->child(0)->face(5));
3995 quads_to_delete.push_back(cell->child(3)->face(2));
3996 quads_to_delete.push_back(cell->child(3)->face(4));
3997
3998 lines_to_delete.push_back(cell->child(0)->line(7));
3999 break;
4001 quads_to_delete.push_back(cell->child(0)->face(1));
4002 quads_to_delete.push_back(cell->child(2)->face(1));
4003 quads_to_delete.push_back(cell->child(4)->face(1));
4004 quads_to_delete.push_back(cell->child(6)->face(1));
4005
4006 quads_to_delete.push_back(cell->child(0)->face(3));
4007 quads_to_delete.push_back(cell->child(1)->face(3));
4008 quads_to_delete.push_back(cell->child(4)->face(3));
4009 quads_to_delete.push_back(cell->child(5)->face(3));
4010
4011 quads_to_delete.push_back(cell->child(0)->face(5));
4012 quads_to_delete.push_back(cell->child(1)->face(5));
4013 quads_to_delete.push_back(cell->child(2)->face(5));
4014 quads_to_delete.push_back(cell->child(3)->face(5));
4015
4016 lines_to_delete.push_back(cell->child(0)->line(5));
4017 lines_to_delete.push_back(cell->child(0)->line(7));
4018 lines_to_delete.push_back(cell->child(0)->line(11));
4019 lines_to_delete.push_back(cell->child(7)->line(0));
4020 lines_to_delete.push_back(cell->child(7)->line(2));
4021 lines_to_delete.push_back(cell->child(7)->line(8));
4022 // delete the vertex which will not
4023 // be needed anymore. This vertex
4024 // is the vertex at the heart of
4025 // this cell, which is the sixth of
4026 // the first child
4027 triangulation.vertices_used[cell->child(0)->vertex_index(7)] =
4028 false;
4029 break;
4030 default:
4031 // only remaining case is
4032 // no_refinement, thus an error
4034 break;
4035 }
4036
4037
4038 // invalidate children
4039 for (unsigned int child = 0; child < cell->n_children(); ++child)
4040 {
4041 cell->child(child)->clear_user_data();
4042 cell->child(child)->clear_user_flag();
4043
4044 for (auto f : GeometryInfo<dim>::face_indices())
4045 // set flags denoting deviations from standard orientation of
4046 // faces back to initialization values
4047 cell->child(child)->set_combined_face_orientation(
4049
4050 cell->child(child)->clear_used_flag();
4051 }
4052
4053
4054 // delete pointer to children
4055 cell->clear_children();
4056 cell->clear_refinement_case();
4057 cell->clear_user_flag();
4058
4059 // so far we only looked at inner quads,
4060 // lines and vertices. Now we have to
4061 // consider outer ones as well. here, we have
4062 // to check, whether there are other cells
4063 // still needing these objects. otherwise we
4064 // can delete them. first for quads (and
4065 // their inner lines).
4066
4067 for (const unsigned int quad_no : GeometryInfo<dim>::face_indices())
4068 {
4070 cell->face(quad_no);
4071
4072 Assert(
4073 (GeometryInfo<dim>::face_refinement_case(ref_case, quad_no) &&
4074 quad->has_children()) ||
4075 GeometryInfo<dim>::face_refinement_case(ref_case, quad_no) ==
4078
4079 switch (quad->refinement_case())
4080 {
4081 case RefinementCase<dim - 1>::no_refinement:
4082 // nothing to do as the quad
4083 // is not refined
4084 break;
4085 case RefinementCase<dim - 1>::cut_x:
4086 case RefinementCase<dim - 1>::cut_y:
4087 {
4088 // if one of the cell counters is
4089 // zero, the other has to be as
4090 // well
4091 Assert((quad_cell_count[quad->child_index(0)] == 0 &&
4092 quad_cell_count[quad->child_index(1)] == 0) ||
4093 (quad_cell_count[quad->child_index(0)] > 0 &&
4094 quad_cell_count[quad->child_index(1)] > 0),
4096 // it might be, that the quad is
4097 // refined twice anisotropically,
4098 // first check, whether we may
4099 // delete possible grand_children
4100 unsigned int deleted_grandchildren = 0;
4101 unsigned int number_of_child_refinements = 0;
4102
4103 for (unsigned int c = 0; c < 2; ++c)
4104 if (quad->child(c)->has_children())
4105 {
4106 ++number_of_child_refinements;
4107 // if one of the cell counters is
4108 // zero, the other has to be as
4109 // well
4110 Assert(
4111 (quad_cell_count[quad->child(c)->child_index(0)] ==
4112 0 &&
4113 quad_cell_count[quad->child(c)->child_index(1)] ==
4114 0) ||
4115 (quad_cell_count[quad->child(c)->child_index(0)] >
4116 0 &&
4117 quad_cell_count[quad->child(c)->child_index(1)] >
4118 0),
4120 if (quad_cell_count[quad->child(c)->child_index(0)] ==
4121 0)
4122 {
4123 // Assert, that the two
4124 // anisotropic
4125 // refinements add up to
4126 // isotropic refinement
4127 Assert(quad->refinement_case() +
4128 quad->child(c)->refinement_case() ==
4131 // we may delete the
4132 // quad's children and
4133 // the inner line as no
4134 // cell references them
4135 // anymore
4136 quads_to_delete.push_back(
4137 quad->child(c)->child(0));
4138 quads_to_delete.push_back(
4139 quad->child(c)->child(1));
4140 if (quad->child(c)->refinement_case() ==
4142 lines_to_delete.push_back(
4143 quad->child(c)->child(0)->line(1));
4144 else
4145 lines_to_delete.push_back(
4146 quad->child(c)->child(0)->line(3));
4147 quad->child(c)->clear_children();
4148 quad->child(c)->clear_refinement_case();
4149 ++deleted_grandchildren;
4150 }
4151 }
4152 // if no grandchildren are left, we
4153 // may as well delete the
4154 // refinement of the inner line
4155 // between our children and the
4156 // corresponding vertex
4157 if (number_of_child_refinements > 0 &&
4158 deleted_grandchildren == number_of_child_refinements)
4159 {
4161 middle_line;
4162 if (quad->refinement_case() == RefinementCase<2>::cut_x)
4163 middle_line = quad->child(0)->line(1);
4164 else
4165 middle_line = quad->child(0)->line(3);
4166
4167 lines_to_delete.push_back(middle_line->child(0));
4168 lines_to_delete.push_back(middle_line->child(1));
4170 .vertices_used[middle_vertex_index<dim, spacedim>(
4171 middle_line)] = false;
4172 middle_line->clear_children();
4173 }
4174
4175 // now consider the direct children
4176 // of the given quad
4177 if (quad_cell_count[quad->child_index(0)] == 0)
4178 {
4179 // we may delete the quad's
4180 // children and the inner line
4181 // as no cell references them
4182 // anymore
4183 quads_to_delete.push_back(quad->child(0));
4184 quads_to_delete.push_back(quad->child(1));
4185 if (quad->refinement_case() == RefinementCase<2>::cut_x)
4186 lines_to_delete.push_back(quad->child(0)->line(1));
4187 else
4188 lines_to_delete.push_back(quad->child(0)->line(3));
4189
4190 // if the counters just dropped
4191 // to zero, otherwise the
4192 // children would have been
4193 // deleted earlier, then this
4194 // cell's children must have
4195 // contained the anisotropic
4196 // quad children. thus, if
4197 // those have again anisotropic
4198 // children, which are in
4199 // effect isotropic children of
4200 // the original quad, those are
4201 // still needed by a
4202 // neighboring cell and we
4203 // cannot delete them. instead,
4204 // we have to reset this quad's
4205 // refine case to isotropic and
4206 // set the children
4207 // accordingly.
4208 if (quad->child(0)->has_children())
4209 if (quad->refinement_case() ==
4211 {
4212 // now evereything is
4213 // quite complicated. we
4214 // have the children
4215 // numbered according to
4216 //
4217 // *---*---*
4218 // |n+1|m+1|
4219 // *---*---*
4220 // | n | m |
4221 // *---*---*
4222 //
4223 // from the original
4224 // anisotropic
4225 // refinement. we have to
4226 // reorder them as
4227 //
4228 // *---*---*
4229 // | m |m+1|
4230 // *---*---*
4231 // | n |n+1|
4232 // *---*---*
4233 //
4234 // for isotropic refinement.
4235 //
4236 // this is a bit ugly, of
4237 // course: loop over all
4238 // cells on all levels
4239 // and look for faces n+1
4240 // (switch_1) and m
4241 // (switch_2).
4242 const typename Triangulation<dim, spacedim>::
4243 quad_iterator switch_1 =
4244 quad->child(0)->child(1),
4245 switch_2 =
4246 quad->child(1)->child(0);
4247
4248 Assert(!switch_1->has_children(),
4250 Assert(!switch_2->has_children(),
4252
4253 const int switch_1_index = switch_1->index();
4254 const int switch_2_index = switch_2->index();
4255 for (unsigned int l = 0;
4256 l < triangulation.levels.size();
4257 ++l)
4258 for (unsigned int h = 0;
4259 h <
4260 triangulation.levels[l]->cells.n_objects();
4261 ++h)
4262 for (const unsigned int q :
4264 {
4265 const int index =
4267 ->cells.get_bounding_object_indices(
4268 h)[q];
4269 if (index == switch_1_index)
4270 triangulation.levels[l]
4271 ->cells.get_bounding_object_indices(
4272 h)[q] = switch_2_index;
4273 else if (index == switch_2_index)
4274 triangulation.levels[l]
4275 ->cells.get_bounding_object_indices(
4276 h)[q] = switch_1_index;
4277 }
4278 // now we have to copy
4279 // all information of the
4280 // two quads
4281 const int switch_1_lines[4] = {
4282 static_cast<signed int>(
4283 switch_1->line_index(0)),
4284 static_cast<signed int>(
4285 switch_1->line_index(1)),
4286 static_cast<signed int>(
4287 switch_1->line_index(2)),
4288 static_cast<signed int>(
4289 switch_1->line_index(3))};
4290 const bool switch_1_line_orientations[4] = {
4291 switch_1->line_orientation(0),
4292 switch_1->line_orientation(1),
4293 switch_1->line_orientation(2),
4294 switch_1->line_orientation(3)};
4295 const types::boundary_id switch_1_boundary_id =
4296 switch_1->boundary_id();
4297 const unsigned int switch_1_user_index =
4298 switch_1->user_index();
4299 const bool switch_1_user_flag =
4300 switch_1->user_flag_set();
4301
4302 switch_1->set_bounding_object_indices(
4303 {switch_2->line_index(0),
4304 switch_2->line_index(1),
4305 switch_2->line_index(2),
4306 switch_2->line_index(3)});
4307 switch_1->set_line_orientation(
4308 0, switch_2->line_orientation(0));
4309 switch_1->set_line_orientation(
4310 1, switch_2->line_orientation(1));
4311 switch_1->set_line_orientation(
4312 2, switch_2->line_orientation(2));
4313 switch_1->set_line_orientation(
4314 3, switch_2->line_orientation(3));
4315 switch_1->set_boundary_id_internal(
4316 switch_2->boundary_id());
4317 switch_1->set_manifold_id(
4318 switch_2->manifold_id());
4319 switch_1->set_user_index(switch_2->user_index());
4320 if (switch_2->user_flag_set())
4321 switch_1->set_user_flag();
4322 else
4323 switch_1->clear_user_flag();
4324
4325 switch_2->set_bounding_object_indices(
4326 {switch_1_lines[0],
4327 switch_1_lines[1],
4328 switch_1_lines[2],
4329 switch_1_lines[3]});
4330 switch_2->set_line_orientation(
4331 0, switch_1_line_orientations[0]);
4332 switch_2->set_line_orientation(
4333 1, switch_1_line_orientations[1]);
4334 switch_2->set_line_orientation(
4335 2, switch_1_line_orientations[2]);
4336 switch_2->set_line_orientation(
4337 3, switch_1_line_orientations[3]);
4338 switch_2->set_boundary_id_internal(
4339 switch_1_boundary_id);
4340 switch_2->set_manifold_id(
4341 switch_1->manifold_id());
4342 switch_2->set_user_index(switch_1_user_index);
4343 if (switch_1_user_flag)
4344 switch_2->set_user_flag();
4345 else
4346 switch_2->clear_user_flag();
4347
4348 const unsigned int child_0 =
4349 quad->child(0)->child_index(0);
4350 const unsigned int child_2 =
4351 quad->child(1)->child_index(0);
4352 quad->clear_children();
4353 quad->clear_refinement_case();
4354 quad->set_refinement_case(
4356 quad->set_children(0, child_0);
4357 quad->set_children(2, child_2);
4358 std::swap(quad_cell_count[child_0 + 1],
4359 quad_cell_count[child_2]);
4360 }
4361 else
4362 {
4363 // the face was refined
4364 // with cut_y, thus the
4365 // children are already
4366 // in correct order. we
4367 // only have to set them
4368 // correctly, deleting
4369 // the indirection of two
4370 // anisotropic refinement
4371 // and going directly
4372 // from the quad to
4373 // isotropic children
4374 const unsigned int child_0 =
4375 quad->child(0)->child_index(0);
4376 const unsigned int child_2 =
4377 quad->child(1)->child_index(0);
4378 quad->clear_children();
4379 quad->clear_refinement_case();
4380 quad->set_refinement_case(
4382 quad->set_children(0, child_0);
4383 quad->set_children(2, child_2);
4384 }
4385 else
4386 {
4387 quad->clear_children();
4388 quad->clear_refinement_case();
4389 }
4390 }
4391 break;
4392 }
4393 case RefinementCase<dim - 1>::cut_xy:
4394 {
4395 // if one of the cell counters is
4396 // zero, the others have to be as
4397 // well
4398
4399 Assert((quad_cell_count[quad->child_index(0)] == 0 &&
4400 quad_cell_count[quad->child_index(1)] == 0 &&
4401 quad_cell_count[quad->child_index(2)] == 0 &&
4402 quad_cell_count[quad->child_index(3)] == 0) ||
4403 (quad_cell_count[quad->child_index(0)] > 0 &&
4404 quad_cell_count[quad->child_index(1)] > 0 &&
4405 quad_cell_count[quad->child_index(2)] > 0 &&
4406 quad_cell_count[quad->child_index(3)] > 0),
4408
4409 if (quad_cell_count[quad->child_index(0)] == 0)
4410 {
4411 // we may delete the quad's
4412 // children, the inner lines
4413 // and the middle vertex as no
4414 // cell references them anymore
4415 lines_to_delete.push_back(quad->child(0)->line(1));
4416 lines_to_delete.push_back(quad->child(3)->line(0));
4417 lines_to_delete.push_back(quad->child(0)->line(3));
4418 lines_to_delete.push_back(quad->child(3)->line(2));
4419
4420 for (unsigned int child = 0; child < quad->n_children();
4421 ++child)
4422 quads_to_delete.push_back(quad->child(child));
4423
4425 .vertices_used[quad->child(0)->vertex_index(3)] =
4426 false;
4427
4428 quad->clear_children();
4429 quad->clear_refinement_case();
4430 }
4431 }
4432 break;
4433
4434 default:
4436 break;
4437 }
4438 }
4439
4440 // now we repeat a similar procedure
4441 // for the outer lines of this cell.
4442
4443 // if in debug mode: check that each
4444 // of the lines for which we consider
4445 // deleting the children in fact has
4446 // children (the bits/coarsening_3d
4447 // test tripped over this initially)
4448 for (unsigned int line_no = 0;
4449 line_no < GeometryInfo<dim>::lines_per_cell;
4450 ++line_no)
4451 {
4453 cell->line(line_no);
4454
4455 Assert(
4456 (GeometryInfo<dim>::line_refinement_case(ref_case, line_no) &&
4457 line->has_children()) ||
4458 GeometryInfo<dim>::line_refinement_case(ref_case, line_no) ==
4461
4462 if (line->has_children())
4463 {
4464 // if one of the cell counters is
4465 // zero, the other has to be as well
4466
4467 Assert((line_cell_count[line->child_index(0)] == 0 &&
4468 line_cell_count[line->child_index(1)] == 0) ||
4469 (line_cell_count[line->child_index(0)] > 0 &&
4470 line_cell_count[line->child_index(1)] > 0),
4472
4473 if (line_cell_count[line->child_index(0)] == 0)
4474 {
4475 for (unsigned int c = 0; c < 2; ++c)
4476 Assert(!line->child(c)->has_children(),
4478
4479 // we may delete the line's
4480 // children and the middle vertex
4481 // as no cell references them
4482 // anymore
4484 .vertices_used[line->child(0)->vertex_index(1)] = false;
4485
4486 lines_to_delete.push_back(line->child(0));
4487 lines_to_delete.push_back(line->child(1));
4488
4489 line->clear_children();
4490 }
4491 }
4492 }
4493
4494 // finally, delete unneeded quads and lines
4495
4496 // clear user pointers, to avoid that
4497 // they may appear at unwanted places
4498 // later on...
4499 // same for user flags, then finally
4500 // delete the quads and lines
4501 typename std::vector<
4503 line = lines_to_delete.begin(),
4504 endline = lines_to_delete.end();
4505 for (; line != endline; ++line)
4506 {
4507 (*line)->clear_user_data();
4508 (*line)->clear_user_flag();
4509 (*line)->clear_used_flag();
4510 }
4511
4512 typename std::vector<
4514 quad = quads_to_delete.begin(),
4515 endquad = quads_to_delete.end();
4516 for (; quad != endquad; ++quad)
4517 {
4518 (*quad)->clear_user_data();
4519 (*quad)->clear_children();
4520 (*quad)->clear_refinement_case();
4521 (*quad)->clear_user_flag();
4522 (*quad)->clear_used_flag();
4523 }
4524 }
4525
4526
4544 template <int spacedim>
4545 static void
4548 unsigned int &next_unused_vertex,
4550 &next_unused_line,
4552 &next_unused_cell,
4553 const typename Triangulation<2, spacedim>::cell_iterator &cell)
4554 {
4555 const unsigned int dim = 2;
4556 // clear refinement flag
4557 const RefinementCase<dim> ref_case = cell->refine_flag_set();
4558 cell->clear_refine_flag();
4559
4560 /* For the refinement process: since we go the levels up from the
4561 lowest, there are (unlike above) only two possibilities: a neighbor
4562 cell is on the same level or one level up (in both cases, it may or
4563 may not be refined later on, but we don't care here).
4564
4565 First:
4566 Set up an array of the 3x3 vertices, which are distributed on the
4567 cell (the array consists of indices into the @p{vertices} std::vector
4568
4569 2--7--3
4570 | | |
4571 4--8--5
4572 | | |
4573 0--6--1
4574
4575 note: in case of cut_x or cut_y not all these vertices are needed for
4576 the new cells
4577
4578 Second:
4579 Set up an array of the new lines (the array consists of iterator
4580 pointers into the lines arrays)
4581
4582 .-6-.-7-. The directions are: .->-.->-.
4583 1 9 3 ^ ^ ^
4584 .-10.11-. .->-.->-.
4585 0 8 2 ^ ^ ^
4586 .-4-.-5-. .->-.->-.
4587
4588 cut_x:
4589 .-4-.-5-.
4590 | | |
4591 0 6 1
4592 | | |
4593 .-2-.-3-.
4594
4595 cut_y:
4596 .---5---.
4597 1 3
4598 .---6---.
4599 0 2
4600 .---4---.
4601
4602
4603 Third:
4604 Set up an array of neighbors:
4605
4606 6 7
4607 .--.--.
4608 1| | |3
4609 .--.--.
4610 0| | |2
4611 .--.--.
4612 4 5
4613
4614 We need this array for two reasons: first to get the lines which will
4615 bound the four subcells (if the neighboring cell is refined, these
4616 lines already exist), and second to update neighborship information.
4617 Since if a neighbor is not refined, its neighborship record only
4618 points to the present, unrefined, cell rather than the children we
4619 are presently creating, we only need the neighborship information
4620 if the neighbor cells are refined. In all other cases, we store
4621 the unrefined neighbor address
4622
4623 We also need for every neighbor (if refined) which number among its
4624 neighbors the present (unrefined) cell has, since that number is to
4625 be replaced and because that also is the number of the subline which
4626 will be the interface between that neighbor and the to be created
4627 cell. We will store this number (between 0 and 3) in the field
4628 @p{neighbors_neighbor}.
4629
4630 It would be sufficient to use the children of the common line to the
4631 neighbor, if we only wanted to get the new sublines and the new
4632 vertex, but because we need to update the neighborship information of
4633 the two refined subcells of the neighbor, we need to search these
4634 anyway.
4635
4636 Convention:
4637 The created children are numbered like this:
4638
4639 .--.--.
4640 |2 . 3|
4641 .--.--.
4642 |0 | 1|
4643 .--.--.
4644 */
4645 // collect the indices of the eight surrounding vertices
4646 // 2--7--3
4647 // | | |
4648 // 4--8--5
4649 // | | |
4650 // 0--6--1
4651 int new_vertices[9];
4652 for (unsigned int vertex_no = 0; vertex_no < 4; ++vertex_no)
4653 new_vertices[vertex_no] = cell->vertex_index(vertex_no);
4654 for (unsigned int line_no = 0; line_no < 4; ++line_no)
4655 if (cell->line(line_no)->has_children())
4656 new_vertices[4 + line_no] =
4657 cell->line(line_no)->child(0)->vertex_index(1);
4658
4659 if (ref_case == RefinementCase<dim>::cut_xy)
4660 {
4661 // find the next
4662 // unused vertex and
4663 // allocate it for
4664 // the new vertex we
4665 // need here
4666 while (triangulation.vertices_used[next_unused_vertex] == true)
4667 ++next_unused_vertex;
4668 Assert(next_unused_vertex < triangulation.vertices.size(),
4669 ExcMessage(
4670 "Internal error: During refinement, the triangulation "
4671 "wants to access an element of the 'vertices' array "
4672 "but it turns out that the array is not large enough."));
4673 triangulation.vertices_used[next_unused_vertex] = true;
4674
4675 new_vertices[8] = next_unused_vertex;
4676
4677 // determine middle vertex by transfinite interpolation to be
4678 // consistent with what happens to quads in a
4679 // Triangulation<3,3> when they are refined
4680 triangulation.vertices[next_unused_vertex] =
4681 cell->center(true, true);
4682 }
4683
4684
4685 // Now the lines:
4687 unsigned int lmin = 8;
4688 unsigned int lmax = 12;
4689 if (ref_case != RefinementCase<dim>::cut_xy)
4690 {
4691 lmin = 6;
4692 lmax = 7;
4693 }
4694
4695 for (unsigned int l = lmin; l < lmax; ++l)
4696 {
4697 while (next_unused_line->used() == true)
4698 ++next_unused_line;
4699 new_lines[l] = next_unused_line;
4700 ++next_unused_line;
4701
4702 AssertIsNotUsed(new_lines[l]);
4703 }
4704
4705 if (ref_case == RefinementCase<dim>::cut_xy)
4706 {
4707 // .-6-.-7-.
4708 // 1 9 3
4709 // .-10.11-.
4710 // 0 8 2
4711 // .-4-.-5-.
4712
4713 // lines 0-7 already exist, create only the four interior
4714 // lines 8-11
4715 unsigned int l = 0;
4716 for (const unsigned int face_no : GeometryInfo<dim>::face_indices())
4717 for (unsigned int c = 0; c < 2; ++c, ++l)
4718 new_lines[l] = cell->line(face_no)->child(c);
4719 Assert(l == 8, ExcInternalError());
4720
4721 new_lines[8]->set_bounding_object_indices(
4722 {new_vertices[6], new_vertices[8]});
4723 new_lines[9]->set_bounding_object_indices(
4724 {new_vertices[8], new_vertices[7]});
4725 new_lines[10]->set_bounding_object_indices(
4726 {new_vertices[4], new_vertices[8]});
4727 new_lines[11]->set_bounding_object_indices(
4728 {new_vertices[8], new_vertices[5]});
4729 }
4730 else if (ref_case == RefinementCase<dim>::cut_x)
4731 {
4732 // .-4-.-5-.
4733 // | | |
4734 // 0 6 1
4735 // | | |
4736 // .-2-.-3-.
4737 new_lines[0] = cell->line(0);
4738 new_lines[1] = cell->line(1);
4739 new_lines[2] = cell->line(2)->child(0);
4740 new_lines[3] = cell->line(2)->child(1);
4741 new_lines[4] = cell->line(3)->child(0);
4742 new_lines[5] = cell->line(3)->child(1);
4743 new_lines[6]->set_bounding_object_indices(
4744 {new_vertices[6], new_vertices[7]});
4745 }
4746 else
4747 {
4749 // .---5---.
4750 // 1 3
4751 // .---6---.
4752 // 0 2
4753 // .---4---.
4754 new_lines[0] = cell->line(0)->child(0);
4755 new_lines[1] = cell->line(0)->child(1);
4756 new_lines[2] = cell->line(1)->child(0);
4757 new_lines[3] = cell->line(1)->child(1);
4758 new_lines[4] = cell->line(2);
4759 new_lines[5] = cell->line(3);
4760 new_lines[6]->set_bounding_object_indices(
4761 {new_vertices[4], new_vertices[5]});
4762 }
4763
4764 for (unsigned int l = lmin; l < lmax; ++l)
4765 {
4766 new_lines[l]->set_used_flag();
4767 new_lines[l]->clear_user_flag();
4768 new_lines[l]->clear_user_data();
4769 new_lines[l]->clear_children();
4770 // interior line
4771 new_lines[l]->set_boundary_id_internal(
4773 new_lines[l]->set_manifold_id(cell->manifold_id());
4774 }
4775
4776 // Now add the four (two)
4777 // new cells!
4780 while (next_unused_cell->used() == true)
4781 ++next_unused_cell;
4782
4783 const unsigned int n_children = GeometryInfo<dim>::n_children(ref_case);
4784 for (unsigned int i = 0; i < n_children; ++i)
4785 {
4786 AssertIsNotUsed(next_unused_cell);
4787 subcells[i] = next_unused_cell;
4788 ++next_unused_cell;
4789 if (i % 2 == 1 && i < n_children - 1)
4790 while (next_unused_cell->used() == true)
4791 ++next_unused_cell;
4792 }
4793
4794 if (ref_case == RefinementCase<dim>::cut_xy)
4795 {
4796 // children:
4797 // .--.--.
4798 // |2 . 3|
4799 // .--.--.
4800 // |0 | 1|
4801 // .--.--.
4802 // lines:
4803 // .-6-.-7-.
4804 // 1 9 3
4805 // .-10.11-.
4806 // 0 8 2
4807 // .-4-.-5-.
4808 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
4809 new_lines[8]->index(),
4810 new_lines[4]->index(),
4811 new_lines[10]->index()});
4812 subcells[1]->set_bounding_object_indices({new_lines[8]->index(),
4813 new_lines[2]->index(),
4814 new_lines[5]->index(),
4815 new_lines[11]->index()});
4816 subcells[2]->set_bounding_object_indices({new_lines[1]->index(),
4817 new_lines[9]->index(),
4818 new_lines[10]->index(),
4819 new_lines[6]->index()});
4820 subcells[3]->set_bounding_object_indices({new_lines[9]->index(),
4821 new_lines[3]->index(),
4822 new_lines[11]->index(),
4823 new_lines[7]->index()});
4824 }
4825 else if (ref_case == RefinementCase<dim>::cut_x)
4826 {
4827 // children:
4828 // .--.--.
4829 // | . |
4830 // .0 . 1.
4831 // | | |
4832 // .--.--.
4833 // lines:
4834 // .-4-.-5-.
4835 // | | |
4836 // 0 6 1
4837 // | | |
4838 // .-2-.-3-.
4839 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
4840 new_lines[6]->index(),
4841 new_lines[2]->index(),
4842 new_lines[4]->index()});
4843 subcells[1]->set_bounding_object_indices({new_lines[6]->index(),
4844 new_lines[1]->index(),
4845 new_lines[3]->index(),
4846 new_lines[5]->index()});
4847 }
4848 else
4849 {
4851 // children:
4852 // .-----.
4853 // | 1 |
4854 // .-----.
4855 // | 0 |
4856 // .-----.
4857 // lines:
4858 // .---5---.
4859 // 1 3
4860 // .---6---.
4861 // 0 2
4862 // .---4---.
4863 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
4864 new_lines[2]->index(),
4865 new_lines[4]->index(),
4866 new_lines[6]->index()});
4867 subcells[1]->set_bounding_object_indices({new_lines[1]->index(),
4868 new_lines[3]->index(),
4869 new_lines[6]->index(),
4870 new_lines[5]->index()});
4871 }
4872
4873 types::subdomain_id subdomainid = cell->subdomain_id();
4874
4875 for (unsigned int i = 0; i < n_children; ++i)
4876 {
4877 subcells[i]->set_used_flag();
4878 subcells[i]->clear_refine_flag();
4879 subcells[i]->clear_user_flag();
4880 subcells[i]->clear_user_data();
4881 subcells[i]->clear_children();
4882 // inherit material properties
4883 subcells[i]->set_material_id(cell->material_id());
4884 subcells[i]->set_manifold_id(cell->manifold_id());
4885 subcells[i]->set_subdomain_id(subdomainid);
4886
4887 if (i % 2 == 0)
4888 subcells[i]->set_parent(cell->index());
4889 }
4890
4891
4892
4893 // set child index for even children i=0,2 (0)
4894 for (unsigned int i = 0; i < n_children / 2; ++i)
4895 cell->set_children(2 * i, subcells[2 * i]->index());
4896 // set the refine case
4897 cell->set_refinement_case(ref_case);
4898
4899 // note that the
4900 // refinement flag was
4901 // already cleared at the
4902 // beginning of this function
4903
4904 if (dim == spacedim - 1)
4905 for (unsigned int c = 0; c < n_children; ++c)
4906 cell->child(c)->set_direction_flag(cell->direction_flag());
4907 }
4908
4909
4910
4911 template <int dim, int spacedim>
4914 const bool check_for_distorted_cells)
4915 {
4916 AssertDimension(dim, 2);
4917
4918 // Check whether a new level is needed. We have to check for
4919 // this on the highest level only
4920 for (const auto &cell : triangulation.active_cell_iterators_on_level(
4921 triangulation.levels.size() - 1))
4922 if (cell->refine_flag_set())
4923 {
4924 triangulation.levels.push_back(
4925 std::make_unique<
4927 break;
4928 }
4929
4932 line != triangulation.end_line();
4933 ++line)
4934 {
4935 line->clear_user_flag();
4936 line->clear_user_data();
4937 }
4938
4939 unsigned int n_single_lines = 0;
4940 unsigned int n_lines_in_pairs = 0;
4941 unsigned int needed_vertices = 0;
4942
4943 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
4944 {
4945 // count number of flagged cells on this level and compute
4946 // how many new vertices and new lines will be needed
4947 unsigned int needed_cells = 0;
4948
4949 for (const auto &cell :
4950 triangulation.active_cell_iterators_on_level(level))
4951 if (cell->refine_flag_set())
4952 {
4953 if (cell->reference_cell() == ReferenceCells::Triangle)
4954 {
4955 needed_cells += 4;
4956 needed_vertices += 0;
4957 n_single_lines += 3;
4958 }
4959 else if (cell->reference_cell() ==
4961 {
4962 needed_cells += 4;
4963 needed_vertices += 1;
4964 n_single_lines += 4;
4965 }
4966 else
4967 {
4969 }
4970
4971 for (const auto line_no : cell->face_indices())
4972 {
4973 auto line = cell->line(line_no);
4974 if (line->has_children() == false)
4975 line->set_user_flag();
4976 }
4977 }
4978
4979
4980 const unsigned int used_cells =
4981 std::count(triangulation.levels[level + 1]->cells.used.begin(),
4982 triangulation.levels[level + 1]->cells.used.end(),
4983 true);
4984
4985
4986 reserve_space(*triangulation.levels[level + 1],
4987 used_cells + needed_cells,
4988 2,
4989 spacedim);
4990
4991 reserve_space(triangulation.levels[level + 1]->cells,
4992 needed_cells,
4993 0);
4994 }
4995
4996 for (auto line = triangulation.begin_line();
4997 line != triangulation.end_line();
4998 ++line)
4999 if (line->user_flag_set())
5000 {
5001 Assert(line->has_children() == false, ExcInternalError());
5002 n_lines_in_pairs += 2;
5003 needed_vertices += 1;
5004 }
5005
5006 reserve_space(triangulation.faces->lines, n_lines_in_pairs, 0);
5007
5008 needed_vertices += std::count(triangulation.vertices_used.begin(),
5009 triangulation.vertices_used.end(),
5010 true);
5011
5012 if (needed_vertices > triangulation.vertices.size())
5013 {
5014 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
5015 triangulation.vertices_used.resize(needed_vertices, false);
5016 }
5017
5018 unsigned int next_unused_vertex = 0;
5019
5020 {
5023 endl = triangulation.end_line();
5025 next_unused_line = triangulation.begin_raw_line();
5026
5027 for (; line != endl; ++line)
5028 if (line->user_flag_set())
5029 {
5030 // This line needs to be refined. Find the next unused vertex
5031 // and set it appropriately
5032 while (triangulation.vertices_used[next_unused_vertex] == true)
5033 ++next_unused_vertex;
5034 Assert(next_unused_vertex < triangulation.vertices.size(),
5035 ExcMessage(
5036 "Internal error: During refinement, the triangulation "
5037 "wants to access an element of the 'vertices' array "
5038 "but it turns out that the array is not large "
5039 "enough."));
5040 triangulation.vertices_used[next_unused_vertex] = true;
5041
5042 triangulation.vertices[next_unused_vertex] = line->center(true);
5043
5044 [[maybe_unused]] bool pair_found = false;
5045 for (; next_unused_line != endl; ++next_unused_line)
5046 if (!next_unused_line->used() &&
5047 !(++next_unused_line)->used())
5048 {
5049 --next_unused_line;
5050 pair_found = true;
5051 break;
5052 }
5053 Assert(pair_found, ExcInternalError());
5054
5055 line->set_children(0, next_unused_line->index());
5056
5058 children[2] = {next_unused_line, ++next_unused_line};
5059
5060 AssertIsNotUsed(children[0]);
5061 AssertIsNotUsed(children[1]);
5062
5063 children[0]->set_bounding_object_indices(
5064 {line->vertex_index(0), next_unused_vertex});
5065 children[1]->set_bounding_object_indices(
5066 {next_unused_vertex, line->vertex_index(1)});
5067
5068 for (auto &child : children)
5069 {
5070 child->set_used_flag();
5071 child->clear_children();
5072 child->clear_user_data();
5073 child->clear_user_flag();
5074 child->set_boundary_id_internal(line->boundary_id());
5075 child->set_manifold_id(line->manifold_id());
5076 // Line orientation is relative to the cell it is on so
5077 // those cannot be set at this point.
5078 }
5079
5080 line->clear_user_flag();
5081 }
5082 }
5083
5084 reserve_space(triangulation.faces->lines, 0, n_single_lines);
5085
5087 cells_with_distorted_children;
5088
5090 next_unused_line = triangulation.begin_raw_line();
5091
5092 const auto create_children = [](auto &triangulation,
5093 unsigned int &next_unused_vertex,
5094 auto &next_unused_line,
5095 auto &next_unused_cell,
5096 const auto &cell) {
5097 const auto ref_case = cell->refine_flag_set();
5098 cell->clear_refine_flag();
5099
5100 unsigned int n_new_vertices = 0;
5101
5102 if (cell->reference_cell() == ReferenceCells::Triangle)
5103 n_new_vertices = 6;
5104 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5105 n_new_vertices = 9;
5106 else
5108
5109 std::vector<unsigned int> new_vertices(n_new_vertices,
5111 for (unsigned int vertex_no = 0; vertex_no < cell->n_vertices();
5112 ++vertex_no)
5113 new_vertices[vertex_no] = cell->vertex_index(vertex_no);
5114 for (unsigned int line_no = 0; line_no < cell->n_lines(); ++line_no)
5115 if (cell->line(line_no)->has_children())
5116 new_vertices[cell->n_vertices() + line_no] =
5117 cell->line(line_no)->child(0)->vertex_index(1);
5118
5119 if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5120 {
5121 while (triangulation.vertices_used[next_unused_vertex] == true)
5122 ++next_unused_vertex;
5123 Assert(
5124 next_unused_vertex < triangulation.vertices.size(),
5125 ExcMessage(
5126 "Internal error: During refinement, the triangulation wants "
5127 "to access an element of the 'vertices' array but it turns "
5128 "out that the array is not large enough."));
5129 triangulation.vertices_used[next_unused_vertex] = true;
5130
5131 new_vertices[8] = next_unused_vertex;
5132
5133 triangulation.vertices[next_unused_vertex] =
5134 cell->center(true, true);
5135 }
5136
5137 std::array<typename Triangulation<dim, spacedim>::raw_line_iterator,
5138 12>
5139 new_lines;
5140 std::array<unsigned char, 12> inherited_orientations;
5141 inherited_orientations.fill(
5143 unsigned int lmin = 0;
5144 unsigned int lmax = 0;
5145
5146 if (cell->reference_cell() == ReferenceCells::Triangle)
5147 {
5148 lmin = 6;
5149 lmax = 9;
5150 // For triangles, the innermost faces are always reversed for the
5151 // first three children and are in the standard orientation for
5152 // the last one.
5153 std::fill(inherited_orientations.begin() + lmin,
5154 inherited_orientations.begin() + lmax,
5156 }
5157 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5158 {
5159 lmin = 8;
5160 lmax = 12;
5161 }
5162 else
5163 {
5165 }
5166
5167 for (unsigned int l = lmin; l < lmax; ++l)
5168 {
5169 while (next_unused_line->used() == true)
5170 ++next_unused_line;
5171 new_lines[l] = next_unused_line;
5172 ++next_unused_line;
5173
5174 AssertIsNotUsed(new_lines[l]);
5175 }
5176
5177 // set up lines which have parents:
5178 for (const unsigned int face_no : cell->face_indices())
5179 {
5180 // Check the face (line) orientation to ensure that the (six or
5181 // eight) outer lines in new_lines are indexed in the default
5182 // orientation. This way we can index into this array in the
5183 // without special casing orientations (e.g., quadrilateral child
5184 // 3 will always have lines 9, 3, 11, 7) when setting child lines.
5185 const unsigned char combined_orientation =
5186 cell->combined_face_orientation(face_no);
5187 Assert(combined_orientation ==
5189 combined_orientation ==
5192 for (unsigned int c = 0; c < 2; ++c)
5193 {
5194 new_lines[2 * face_no + c] = cell->line(face_no)->child(c);
5195 inherited_orientations[2 * face_no + c] =
5196 cell->combined_face_orientation(face_no);
5197 }
5198 if (combined_orientation ==
5200 std::swap(new_lines[2 * face_no], new_lines[2 * face_no + 1]);
5201 }
5202
5203 // set up lines which do not have parents:
5204 if (cell->reference_cell() == ReferenceCells::Triangle)
5205 {
5206 new_lines[6]->set_bounding_object_indices(
5207 {new_vertices[3], new_vertices[4]});
5208 new_lines[7]->set_bounding_object_indices(
5209 {new_vertices[4], new_vertices[5]});
5210 new_lines[8]->set_bounding_object_indices(
5211 {new_vertices[5], new_vertices[3]});
5212 }
5213 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5214 {
5215 new_lines[8]->set_bounding_object_indices(
5216 {new_vertices[6], new_vertices[8]});
5217 new_lines[9]->set_bounding_object_indices(
5218 {new_vertices[8], new_vertices[7]});
5219 new_lines[10]->set_bounding_object_indices(
5220 {new_vertices[4], new_vertices[8]});
5221 new_lines[11]->set_bounding_object_indices(
5222 {new_vertices[8], new_vertices[5]});
5223 }
5224 else
5225 {
5227 }
5228
5229 for (unsigned int l = lmin; l < lmax; ++l)
5230 {
5231 new_lines[l]->set_used_flag();
5232 new_lines[l]->clear_user_flag();
5233 new_lines[l]->clear_user_data();
5234 new_lines[l]->clear_children();
5235 // new lines are always internal.
5236 new_lines[l]->set_boundary_id_internal(
5238 new_lines[l]->set_manifold_id(cell->manifold_id());
5239 }
5240
5243 while (next_unused_cell->used() == true)
5244 ++next_unused_cell;
5245
5246 unsigned int n_children = 0;
5247 if (cell->reference_cell() == ReferenceCells::Triangle)
5248 n_children = 4;
5249 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5250 n_children = 4;
5251 else
5253
5254 for (unsigned int i = 0; i < n_children; ++i)
5255 {
5256 AssertIsNotUsed(next_unused_cell);
5257 subcells[i] = next_unused_cell;
5258 ++next_unused_cell;
5259 if (i % 2 == 1 && i < n_children - 1)
5260 while (next_unused_cell->used() == true)
5261 ++next_unused_cell;
5262 }
5263
5264 // Assign lines to child cells:
5265 constexpr unsigned int X = numbers::invalid_unsigned_int;
5266 static constexpr ::ndarray<unsigned int, 4, 4> tri_child_lines =
5267 {{{{0, 8, 5, X}}, {{1, 2, 6, X}}, {{7, 3, 4, X}}, {{6, 7, 8, X}}}};
5268 static constexpr ::ndarray<unsigned int, 4, 4>
5269 quad_child_lines = {{{{0, 8, 4, 10}},
5270 {{8, 2, 5, 11}},
5271 {{1, 9, 10, 6}},
5272 {{9, 3, 11, 7}}}};
5273 // Here and below we assume that child cells have the same reference
5274 // cell type as the parent.
5275 const auto &child_lines =
5276 cell->reference_cell() == ReferenceCells::Triangle ?
5277 tri_child_lines :
5278 quad_child_lines;
5279 for (unsigned int i = 0; i < n_children; ++i)
5280 {
5281 if (cell->reference_cell() == ReferenceCells::Triangle)
5282 subcells[i]->set_bounding_object_indices(
5283 {new_lines[child_lines[i][0]]->index(),
5284 new_lines[child_lines[i][1]]->index(),
5285 new_lines[child_lines[i][2]]->index()});
5286 else
5287 subcells[i]->set_bounding_object_indices(
5288 {new_lines[child_lines[i][0]]->index(),
5289 new_lines[child_lines[i][1]]->index(),
5290 new_lines[child_lines[i][2]]->index(),
5291 new_lines[child_lines[i][3]]->index()});
5292
5293 subcells[i]->set_used_flag();
5294 subcells[i]->clear_refine_flag();
5295 subcells[i]->clear_user_flag();
5296 subcells[i]->clear_user_data();
5297 subcells[i]->clear_children();
5298 // inherit material properties
5299 subcells[i]->set_material_id(cell->material_id());
5300 subcells[i]->set_manifold_id(cell->manifold_id());
5301 subcells[i]->set_subdomain_id(cell->subdomain_id());
5302
5303 triangulation.levels[subcells[i]->level()]
5304 ->reference_cell[subcells[i]->index()] = cell->reference_cell();
5305
5306 // Finally, now that children are marked as used, we can set
5307 // orientation flags:
5308 for (unsigned int face_no : cell->face_indices())
5309 subcells[i]->set_combined_face_orientation(
5310 face_no, inherited_orientations[child_lines[i][face_no]]);
5311
5312 if (i % 2 == 0)
5313 subcells[i]->set_parent(cell->index());
5314 }
5315
5316 // Unlike the same lines on other children, the innermost triangle's
5317 // faces are all in the default orientation:
5318 if (cell->reference_cell() == ReferenceCells::Triangle)
5319 for (unsigned int face_no : cell->face_indices())
5320 subcells[3]->set_combined_face_orientation(
5322
5323 for (unsigned int i = 0; i < n_children / 2; ++i)
5324 cell->set_children(2 * i, subcells[2 * i]->index());
5325
5326 cell->set_refinement_case(ref_case);
5327
5328 if (dim == spacedim - 1)
5329 for (unsigned int c = 0; c < n_children; ++c)
5330 cell->child(c)->set_direction_flag(cell->direction_flag());
5331 };
5332
5333 for (int level = 0;
5334 level < static_cast<int>(triangulation.levels.size()) - 1;
5335 ++level)
5336 {
5338 next_unused_cell = triangulation.begin_raw(level + 1);
5339
5340 for (const auto &cell :
5341 triangulation.active_cell_iterators_on_level(level))
5342 if (cell->refine_flag_set())
5343 {
5344 create_children(triangulation,
5345 next_unused_vertex,
5346 next_unused_line,
5347 next_unused_cell,
5348 cell);
5349
5350 if (cell->reference_cell() == ReferenceCells::Quadrilateral &&
5351 check_for_distorted_cells &&
5352 has_distorted_children<dim, spacedim>(cell))
5353 cells_with_distorted_children.distorted_cells.push_back(
5354 cell);
5355
5356 triangulation.signals.post_refinement_on_cell(cell);
5357 }
5358 }
5359
5360 return cells_with_distorted_children;
5361 }
5362
5363
5364
5369 template <int spacedim>
5372 const bool /*check_for_distorted_cells*/)
5373 {
5374 const unsigned int dim = 1;
5375
5376 // Check whether a new level is needed. We have to check for
5377 // this on the highest level only
5378 for (const auto &cell : triangulation.active_cell_iterators_on_level(
5379 triangulation.levels.size() - 1))
5380 if (cell->refine_flag_set())
5381 {
5382 triangulation.levels.push_back(
5383 std::make_unique<
5385 break;
5386 }
5387
5388
5389 // check how much space is needed on every level. We need not
5390 // check the highest level since either - on the highest level
5391 // no cells are flagged for refinement - there are, but
5392 // prepare_refinement added another empty level
5393 unsigned int needed_vertices = 0;
5394 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5395 {
5396 // count number of flagged
5397 // cells on this level
5398 unsigned int flagged_cells = 0;
5399
5400 for (const auto &acell :
5401 triangulation.active_cell_iterators_on_level(level))
5402 if (acell->refine_flag_set())
5403 ++flagged_cells;
5404
5405 // count number of used cells
5406 // on the next higher level
5407 const unsigned int used_cells =
5408 std::count(triangulation.levels[level + 1]->cells.used.begin(),
5409 triangulation.levels[level + 1]->cells.used.end(),
5410 true);
5411
5412 // reserve space for the used_cells cells already existing
5413 // on the next higher level as well as for the
5414 // 2*flagged_cells that will be created on that level
5415 reserve_space(*triangulation.levels[level + 1],
5417 flagged_cells,
5418 1,
5419 spacedim);
5420 // reserve space for 2*flagged_cells new lines on the next
5421 // higher level
5422 reserve_space(triangulation.levels[level + 1]->cells,
5424 flagged_cells,
5425 0);
5426
5427 needed_vertices += flagged_cells;
5428 }
5429
5430 // add to needed vertices how many
5431 // vertices are already in use
5432 needed_vertices += std::count(triangulation.vertices_used.begin(),
5433 triangulation.vertices_used.end(),
5434 true);
5435 // if we need more vertices: create them, if not: leave the
5436 // array as is, since shrinking is not really possible because
5437 // some of the vertices at the end may be in use
5438 if (needed_vertices > triangulation.vertices.size())
5439 {
5440 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
5441 triangulation.vertices_used.resize(needed_vertices, false);
5442 }
5443
5444
5445 // Do REFINEMENT on every level; exclude highest level as
5446 // above
5447
5448 // index of next unused vertex
5449 unsigned int next_unused_vertex = 0;
5450
5451 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5452 {
5454 next_unused_cell = triangulation.begin_raw(level + 1);
5455
5456 for (const auto &cell :
5457 triangulation.active_cell_iterators_on_level(level))
5458 if (cell->refine_flag_set())
5459 {
5460 // clear refinement flag
5461 cell->clear_refine_flag();
5462
5463 // search for next unused
5464 // vertex
5465 while (triangulation.vertices_used[next_unused_vertex] ==
5466 true)
5467 ++next_unused_vertex;
5468 Assert(
5469 next_unused_vertex < triangulation.vertices.size(),
5470 ExcMessage(
5471 "Internal error: During refinement, the triangulation "
5472 "wants to access an element of the 'vertices' array "
5473 "but it turns out that the array is not large enough."));
5474
5475 // Now we always ask the cell itself where to put
5476 // the new point. The cell in turn will query the
5477 // manifold object internally.
5478 triangulation.vertices[next_unused_vertex] =
5479 cell->center(true);
5480
5481 triangulation.vertices_used[next_unused_vertex] = true;
5482
5483 // search for next two unused cell (++ takes care of
5484 // the end of the vector)
5486 first_child,
5487 second_child;
5488 while (next_unused_cell->used() == true)
5489 ++next_unused_cell;
5490 first_child = next_unused_cell;
5491 first_child->set_used_flag();
5492 first_child->clear_user_data();
5493 ++next_unused_cell;
5494 AssertIsNotUsed(next_unused_cell);
5495 second_child = next_unused_cell;
5496 second_child->set_used_flag();
5497 second_child->clear_user_data();
5498
5499 types::subdomain_id subdomainid = cell->subdomain_id();
5500
5501 // insert first child
5502 cell->set_children(0, first_child->index());
5503 first_child->clear_children();
5504 first_child->set_bounding_object_indices(
5505 {cell->vertex_index(0), next_unused_vertex});
5506 first_child->set_material_id(cell->material_id());
5507 first_child->set_manifold_id(cell->manifold_id());
5508 first_child->set_subdomain_id(subdomainid);
5509 if (dim == spacedim - 1)
5510 first_child->set_direction_flag(cell->direction_flag());
5511
5512 first_child->set_parent(cell->index());
5513
5514 // Set manifold id of the right face. Only do this
5515 // on the first child.
5516 first_child->face(1)->set_manifold_id(cell->manifold_id());
5517
5518 // reset neighborship info (refer to
5519 // internal::TriangulationImplementation::TriaLevel<0> for
5520 // details)
5521 first_child->set_neighbor(1, second_child);
5522 if (cell->neighbor(0).state() != IteratorState::valid)
5523 first_child->set_neighbor(0, cell->neighbor(0));
5524 else if (cell->neighbor(0)->is_active())
5525 {
5526 // since the neighbors level is always <=level,
5527 // if the cell is active, then there are no
5528 // cells to the left which may want to know
5529 // about this new child cell.
5530 Assert(cell->neighbor(0)->level() <= cell->level(),
5532 first_child->set_neighbor(0, cell->neighbor(0));
5533 }
5534 else
5535 // left neighbor is refined
5536 {
5537 // set neighbor to cell on same level
5538 const unsigned int nbnb = cell->neighbor_of_neighbor(0);
5539 first_child->set_neighbor(0,
5540 cell->neighbor(0)->child(nbnb));
5541
5542 // reset neighbor info of all right descendant
5543 // of the left neighbor of cell
5545 left_neighbor = cell->neighbor(0);
5546 while (left_neighbor->has_children())
5547 {
5548 left_neighbor = left_neighbor->child(nbnb);
5549 left_neighbor->set_neighbor(nbnb, first_child);
5550 }
5551 }
5552
5553 // insert second child
5554 second_child->clear_children();
5555 second_child->set_bounding_object_indices(
5556 {next_unused_vertex, cell->vertex_index(1)});
5557 second_child->set_neighbor(0, first_child);
5558 second_child->set_material_id(cell->material_id());
5559 second_child->set_manifold_id(cell->manifold_id());
5560 second_child->set_subdomain_id(subdomainid);
5561 if (dim == spacedim - 1)
5562 second_child->set_direction_flag(cell->direction_flag());
5563
5564 if (cell->neighbor(1).state() != IteratorState::valid)
5565 second_child->set_neighbor(1, cell->neighbor(1));
5566 else if (cell->neighbor(1)->is_active())
5567 {
5568 Assert(cell->neighbor(1)->level() <= cell->level(),
5570 second_child->set_neighbor(1, cell->neighbor(1));
5571 }
5572 else
5573 // right neighbor is refined same as above
5574 {
5575 const unsigned int nbnb = cell->neighbor_of_neighbor(1);
5576 second_child->set_neighbor(
5577 1, cell->neighbor(1)->child(nbnb));
5578
5580 right_neighbor = cell->neighbor(1);
5581 while (right_neighbor->has_children())
5582 {
5583 right_neighbor = right_neighbor->child(nbnb);
5584 right_neighbor->set_neighbor(nbnb, second_child);
5585 }
5586 }
5587 // inform all listeners that cell refinement is done
5588 triangulation.signals.post_refinement_on_cell(cell);
5589 }
5590 }
5591
5592 // in 1d, we can not have distorted children unless the parent
5593 // was already distorted (that is because we don't use
5594 // boundary information for 1d triangulations). so return an
5595 // empty list
5597 }
5598
5599
5604 template <int spacedim>
5607 const bool check_for_distorted_cells)
5608 {
5609 const unsigned int dim = 2;
5610
5611 // First check whether we can get away with isotropic refinement, or
5612 // whether we need to run through the full anisotropic algorithm
5613 {
5614 bool do_isotropic_refinement = true;
5615 for (const auto &cell : triangulation.active_cell_iterators())
5616 if (cell->refine_flag_set() == RefinementCase<dim>::cut_x ||
5617 cell->refine_flag_set() == RefinementCase<dim>::cut_y)
5618 {
5619 do_isotropic_refinement = false;
5620 break;
5621 }
5622
5623 if (do_isotropic_refinement)
5624 return execute_refinement_isotropic(triangulation,
5625 check_for_distorted_cells);
5626 }
5627
5628 // If we get here, we are doing anisotropic refinement.
5629
5630 // Check whether a new level is needed. We have to check for
5631 // this on the highest level only
5632 for (const auto &cell : triangulation.active_cell_iterators_on_level(
5633 triangulation.levels.size() - 1))
5634 if (cell->refine_flag_set())
5635 {
5636 triangulation.levels.push_back(
5637 std::make_unique<
5639 break;
5640 }
5641
5642 // TODO[WB]: we clear user flags and pointers of lines; we're going
5643 // to use them to flag which lines need refinement
5646 line != triangulation.end_line();
5647 ++line)
5648 {
5649 line->clear_user_flag();
5650 line->clear_user_data();
5651 }
5652 // running over all cells and lines count the number
5653 // n_single_lines of lines which can be stored as single
5654 // lines, e.g. inner lines
5655 unsigned int n_single_lines = 0;
5656
5657 // New lines to be created: number lines which are stored in
5658 // pairs (the children of lines must be stored in pairs)
5659 unsigned int n_lines_in_pairs = 0;
5660
5661 // check how much space is needed on every level. We need not
5662 // check the highest level since either - on the highest level
5663 // no cells are flagged for refinement - there are, but
5664 // prepare_refinement added another empty level
5665 unsigned int needed_vertices = 0;
5666 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5667 {
5668 // count number of flagged cells on this level and compute
5669 // how many new vertices and new lines will be needed
5670 unsigned int needed_cells = 0;
5671
5672 for (const auto &cell :
5673 triangulation.active_cell_iterators_on_level(level))
5674 if (cell->refine_flag_set())
5675 {
5676 if (cell->refine_flag_set() == RefinementCase<dim>::cut_xy)
5677 {
5678 needed_cells += 4;
5679
5680 // new vertex at center of cell is needed in any
5681 // case
5682 ++needed_vertices;
5683
5684 // the four inner lines can be stored as singles
5685 n_single_lines += 4;
5686 }
5687 else // cut_x || cut_y
5688 {
5689 // set the flag showing that anisotropic
5690 // refinement is used for at least one cell
5691 triangulation.anisotropic_refinement = true;
5692
5693 needed_cells += 2;
5694 // no vertex at center
5695
5696 // the inner line can be stored as single
5697 n_single_lines += 1;
5698 }
5699
5700 // mark all faces (lines) for refinement; checking
5701 // locally whether the neighbor would also like to
5702 // refine them is rather difficult for lines so we
5703 // only flag them and after visiting all cells, we
5704 // decide which lines need refinement;
5705 for (const unsigned int line_no :
5707 {
5709 cell->refine_flag_set(), line_no) ==
5711 {
5713 line = cell->line(line_no);
5714 if (line->has_children() == false)
5715 line->set_user_flag();
5716 }
5717 }
5718 }
5719
5720
5721 // count number of used cells on the next higher level
5722 const unsigned int used_cells =
5723 std::count(triangulation.levels[level + 1]->cells.used.begin(),
5724 triangulation.levels[level + 1]->cells.used.end(),
5725 true);
5726
5727
5728 // reserve space for the used_cells cells already existing
5729 // on the next higher level as well as for the
5730 // needed_cells that will be created on that level
5731 reserve_space(*triangulation.levels[level + 1],
5732 used_cells + needed_cells,
5733 2,
5734 spacedim);
5735
5736 // reserve space for needed_cells new quads on the next
5737 // higher level
5738 reserve_space(triangulation.levels[level + 1]->cells,
5739 needed_cells,
5740 0);
5741 }
5742
5743 // now count the lines which were flagged for refinement
5746 line != triangulation.end_line();
5747 ++line)
5748 if (line->user_flag_set())
5749 {
5750 Assert(line->has_children() == false, ExcInternalError());
5751 n_lines_in_pairs += 2;
5752 needed_vertices += 1;
5753 }
5754 // reserve space for n_lines_in_pairs new lines. note, that
5755 // we can't reserve space for the single lines here as well,
5756 // as all the space reserved for lines in pairs would be
5757 // counted as unused and we would end up with too little space
5758 // to store all lines. memory reservation for n_single_lines
5759 // can only be done AFTER we refined the lines of the current
5760 // cells
5761 reserve_space(triangulation.faces->lines, n_lines_in_pairs, 0);
5762
5763 // add to needed vertices how many vertices are already in use
5764 needed_vertices += std::count(triangulation.vertices_used.begin(),
5765 triangulation.vertices_used.end(),
5766 true);
5767 // if we need more vertices: create them, if not: leave the
5768 // array as is, since shrinking is not really possible because
5769 // some of the vertices at the end may be in use
5770 if (needed_vertices > triangulation.vertices.size())
5771 {
5772 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
5773 triangulation.vertices_used.resize(needed_vertices, false);
5774 }
5775
5776
5777 // Do REFINEMENT on every level; exclude highest level as
5778 // above
5779
5780 // index of next unused vertex
5781 unsigned int next_unused_vertex = 0;
5782
5783 // first the refinement of lines. children are stored
5784 // pairwise
5785 {
5786 // only active objects can be refined further
5789 endl = triangulation.end_line();
5791 next_unused_line = triangulation.begin_raw_line();
5792
5793 for (; line != endl; ++line)
5794 if (line->user_flag_set())
5795 {
5796 // this line needs to be refined
5797
5798 // find the next unused vertex and set it
5799 // appropriately
5800 while (triangulation.vertices_used[next_unused_vertex] == true)
5801 ++next_unused_vertex;
5802 Assert(
5803 next_unused_vertex < triangulation.vertices.size(),
5804 ExcMessage(
5805 "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."));
5806 triangulation.vertices_used[next_unused_vertex] = true;
5807
5808 triangulation.vertices[next_unused_vertex] = line->center(true);
5809
5810 // now that we created the right point, make up the
5811 // two child lines. To this end, find a pair of
5812 // unused lines
5813 [[maybe_unused]] bool pair_found = false;
5814 for (; next_unused_line != endl; ++next_unused_line)
5815 if (!next_unused_line->used() &&
5816 !(++next_unused_line)->used())
5817 {
5818 // go back to the first of the two unused
5819 // lines
5820 --next_unused_line;
5821 pair_found = true;
5822 break;
5823 }
5824 Assert(pair_found, ExcInternalError());
5825
5826 // there are now two consecutive unused lines, such
5827 // that the children of a line will be consecutive.
5828 // then set the child pointer of the present line
5829 line->set_children(0, next_unused_line->index());
5830
5831 // set the two new lines
5833 children[2] = {next_unused_line, ++next_unused_line};
5834 // some tests; if any of the iterators should be
5835 // invalid, then already dereferencing will fail
5836 AssertIsNotUsed(children[0]);
5837 AssertIsNotUsed(children[1]);
5838
5839 children[0]->set_bounding_object_indices(
5840 {line->vertex_index(0), next_unused_vertex});
5841 children[1]->set_bounding_object_indices(
5842 {next_unused_vertex, line->vertex_index(1)});
5843
5844 children[0]->set_used_flag();
5845 children[1]->set_used_flag();
5846 children[0]->clear_children();
5847 children[1]->clear_children();
5848 children[0]->clear_user_data();
5849 children[1]->clear_user_data();
5850 children[0]->clear_user_flag();
5851 children[1]->clear_user_flag();
5852
5853
5854 children[0]->set_boundary_id_internal(line->boundary_id());
5855 children[1]->set_boundary_id_internal(line->boundary_id());
5856
5857 children[0]->set_manifold_id(line->manifold_id());
5858 children[1]->set_manifold_id(line->manifold_id());
5859
5860 // finally clear flag indicating the need for
5861 // refinement
5862 line->clear_user_flag();
5863 }
5864 }
5865
5866
5867 // Now set up the new cells
5868
5869 // reserve space for inner lines (can be stored as single
5870 // lines)
5871 reserve_space(triangulation.faces->lines, 0, n_single_lines);
5872
5874 cells_with_distorted_children;
5875
5876 // reset next_unused_line, as now also single empty places in
5877 // the vector can be used
5879 next_unused_line = triangulation.begin_raw_line();
5880
5881 for (int level = 0;
5882 level < static_cast<int>(triangulation.levels.size()) - 1;
5883 ++level)
5884 {
5886 next_unused_cell = triangulation.begin_raw(level + 1);
5887
5888 for (const auto &cell :
5889 triangulation.active_cell_iterators_on_level(level))
5890 if (cell->refine_flag_set())
5891 {
5892 // actually set up the children and update neighbor
5893 // information
5894 create_children(triangulation,
5895 next_unused_vertex,
5896 next_unused_line,
5897 next_unused_cell,
5898 cell);
5899
5900 if (check_for_distorted_cells &&
5901 has_distorted_children<dim, spacedim>(cell))
5902 cells_with_distorted_children.distorted_cells.push_back(
5903 cell);
5904 // inform all listeners that cell refinement is done
5905 triangulation.signals.post_refinement_on_cell(cell);
5906 }
5907 }
5908
5909 return cells_with_distorted_children;
5910 }
5911
5912
5913 template <int spacedim>
5916 const bool check_for_distorted_cells)
5917 {
5918 static const int dim = 3;
5919 static const unsigned int X = numbers::invalid_unsigned_int;
5920 using raw_line_iterator =
5922 using raw_quad_iterator =
5924
5925 Assert(spacedim == 3, ExcNotImplemented());
5926
5927 Assert(triangulation.vertices.size() ==
5928 triangulation.vertices_used.size(),
5930
5931 // Check whether a new level is needed. We have to check for
5932 // this on the highest level only
5933 for (const auto &cell : triangulation.active_cell_iterators_on_level(
5934 triangulation.levels.size() - 1))
5935 if (cell->refine_flag_set())
5936 {
5937 triangulation.levels.push_back(
5938 std::make_unique<
5940 break;
5941 }
5942
5943 // first clear user flags for quads and lines; we're going to
5944 // use them to flag which lines and quads need refinement
5945 triangulation.faces->quads.clear_user_data();
5946 triangulation.faces->lines.clear_user_flags();
5947 triangulation.faces->quads.clear_user_flags();
5948
5949 // check how much space is needed on every level. We need not
5950 // check the highest level since either
5951 // - on the highest level no cells are flagged for refinement
5952 // - there are, but prepare_refinement added another empty
5953 // level which then is the highest level
5954
5955 // variables to hold the number of newly to be created
5956 // vertices, lines and quads. as these are stored globally,
5957 // declare them outside the loop over al levels. we need lines
5958 // and quads in pairs for refinement of old ones and lines and
5959 // quads, that can be stored as single ones, as they are newly
5960 // created in the inside of an existing cell
5961 unsigned int needed_vertices = 0;
5962 unsigned int needed_lines_single = 0;
5963 unsigned int needed_quads_single = 0;
5964 unsigned int needed_lines_pair = 0;
5965 unsigned int needed_quads_pair = 0;
5966 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5967 {
5968 unsigned int new_cells = 0;
5969
5970 for (const auto &cell :
5971 triangulation.active_cell_iterators_on_level(level))
5972 if (cell->refine_flag_set())
5973 {
5974 // Only support isotropic refinement
5975 Assert(cell->refine_flag_set() ==
5978
5979 // Now count up how many new cells, faces, edges, and vertices
5980 // we will need to allocate to do this refinement.
5981 new_cells += cell->reference_cell().n_isotropic_children();
5982
5983 if (cell->reference_cell() == ReferenceCells::Hexahedron)
5984 {
5985 ++needed_vertices;
5986 needed_lines_single += 6;
5987 needed_quads_single += 12;
5988 }
5989 else if (cell->reference_cell() ==
5991 {
5992 needed_lines_single += 1;
5993 needed_quads_single += 8;
5994 }
5995 else
5996 {
5998 }
5999
6000 // Also check whether we have to refine any of the faces and
6001 // edges that bound this cell. They may of course already be
6002 // refined, so we only *mark* them for refinement by setting
6003 // the user flags
6004 for (const auto face : cell->face_indices())
6005 if (cell->face(face)->n_children() == 0)
6006 cell->face(face)->set_user_flag();
6007 else
6008 Assert(cell->face(face)->n_children() ==
6009 cell->reference_cell()
6010 .face_reference_cell(face)
6011 .n_isotropic_children(),
6013
6014 for (const auto line : cell->line_indices())
6015 if (cell->line(line)->has_children() == false)
6016 cell->line(line)->set_user_flag();
6017 else
6018 Assert(cell->line(line)->n_children() == 2,
6020 }
6021
6022 const unsigned int used_cells =
6023 std::count(triangulation.levels[level + 1]->cells.used.begin(),
6024 triangulation.levels[level + 1]->cells.used.end(),
6025 true);
6026
6027 if (triangulation.all_reference_cells_are_hyper_cube())
6028 reserve_space(*triangulation.levels[level + 1],
6029 used_cells + new_cells,
6030 3,
6031 spacedim,
6032 false);
6033 else
6034 reserve_space(*triangulation.levels[level + 1],
6035 used_cells + new_cells,
6036 3,
6037 spacedim,
6038 true);
6039
6040 reserve_space(triangulation.levels[level + 1]->cells, new_cells);
6041 }
6042
6043 // now count the quads and lines which were flagged for
6044 // refinement
6047 quad != triangulation.end_quad();
6048 ++quad)
6049 {
6050 if (quad->user_flag_set() == false)
6051 continue;
6052
6053 if (quad->reference_cell() == ReferenceCells::Quadrilateral)
6054 {
6055 needed_quads_pair += 4;
6056 needed_lines_pair += 4;
6057 needed_vertices += 1;
6058 }
6059 else if (quad->reference_cell() == ReferenceCells::Triangle)
6060 {
6061 needed_quads_pair += 4;
6062 needed_lines_single += 3;
6063 }
6064 else
6065 {
6067 }
6068 }
6069
6072 line != triangulation.end_line();
6073 ++line)
6074 {
6075 if (line->user_flag_set() == false)
6076 continue;
6077
6078 needed_lines_pair += 2;
6079 needed_vertices += 1;
6080 }
6081
6082 reserve_space(triangulation.faces->lines,
6083 needed_lines_pair,
6084 needed_lines_single);
6086 needed_quads_pair,
6087 needed_quads_single);
6088 reserve_space(triangulation.faces->quads,
6089 needed_quads_pair,
6090 needed_quads_single);
6091
6092
6093 // add to needed vertices how many vertices are already in use
6094 needed_vertices += std::count(triangulation.vertices_used.begin(),
6095 triangulation.vertices_used.end(),
6096 true);
6097
6098 if (needed_vertices > triangulation.vertices.size())
6099 {
6100 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
6101 triangulation.vertices_used.resize(needed_vertices, false);
6102 }
6103
6104 //-----------------------------------------
6105 // Before we start with the actual refinement, we do some
6106 // sanity checks if in debug mode. especially, we try to catch
6107 // the notorious problem with lines being twice refined,
6108 // i.e. there are cells adjacent at one line ("around the
6109 // edge", but not at a face), with two cells differing by more
6110 // than one refinement level
6111 //
6112 // this check is very simple to implement here, since we have
6113 // all lines flagged if they shall be refined
6114#ifdef DEBUG
6115 for (const auto &cell : triangulation.active_cell_iterators())
6116 if (!cell->refine_flag_set())
6117 for (unsigned int line_n = 0; line_n < cell->n_lines(); ++line_n)
6118 if (cell->line(line_n)->has_children())
6119 for (unsigned int c = 0; c < 2; ++c)
6120 Assert(cell->line(line_n)->child(c)->user_flag_set() == false,
6122#endif
6123
6124 unsigned int current_vertex = 0;
6125
6126 // helper function - find the next available vertex number and mark it
6127 // as used.
6128 auto get_next_unused_vertex = [](const unsigned int current_vertex,
6129 std::vector<bool> &vertices_used) {
6130 unsigned int next_vertex = current_vertex;
6131 while (next_vertex < vertices_used.size() &&
6132 vertices_used[next_vertex] == true)
6133 ++next_vertex;
6134 Assert(next_vertex < vertices_used.size(), ExcInternalError());
6135 vertices_used[next_vertex] = true;
6136
6137 return next_vertex;
6138 };
6139
6140 // LINES
6141 {
6144 endl = triangulation.end_line();
6145 raw_line_iterator next_unused_line = triangulation.begin_raw_line();
6146
6147 for (; line != endl; ++line)
6148 {
6149 if (line->user_flag_set() == false)
6150 continue;
6151
6152 next_unused_line =
6153 triangulation.faces->lines.template next_free_pair_object<1>(
6155 Assert(next_unused_line.state() == IteratorState::valid,
6157
6158 // now we found two consecutive unused lines, such
6159 // that the children of a line will be consecutive.
6160 // then set the child pointer of the present line
6161 line->set_children(0, next_unused_line->index());
6162
6163 const std::array<raw_line_iterator, 2> children{
6164 {next_unused_line, ++next_unused_line}};
6165
6166 AssertIsNotUsed(children[0]);
6167 AssertIsNotUsed(children[1]);
6168
6169 current_vertex =
6170 get_next_unused_vertex(current_vertex,
6171 triangulation.vertices_used);
6172 triangulation.vertices[current_vertex] = line->center(true);
6173
6174 children[0]->set_bounding_object_indices(
6175 {line->vertex_index(0), current_vertex});
6176 children[1]->set_bounding_object_indices(
6177 {current_vertex, line->vertex_index(1)});
6178
6179 const auto manifold_id = line->manifold_id();
6180 const auto boundary_id = line->boundary_id();
6181 for (const auto &child : children)
6182 {
6183 child->set_used_flag();
6184 child->clear_children();
6185 child->clear_user_data();
6186 child->clear_user_flag();
6187 child->set_boundary_id_internal(boundary_id);
6188 child->set_manifold_id(manifold_id);
6189 }
6190
6191 line->clear_user_flag();
6192 }
6193 }
6194
6195 // QUADS
6196 {
6198 quad = triangulation.begin_quad(),
6199 endq = triangulation.end_quad();
6200
6201 for (; quad != endq; ++quad)
6202 {
6203 if (quad->user_flag_set() == false)
6204 continue;
6205
6206 const auto reference_face_type = quad->reference_cell();
6207
6208 // 1) create new lines (property is set later)
6209 // maximum of 4 new lines (4 quadrilateral, 3 triangle)
6210 std::array<raw_line_iterator, 4> new_lines;