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