deal.II version GIT relicensing-6842-g793a97d2aa 2026-10-02 14:00:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
time_dependent.cc
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 1999 - 2025 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
16
18#include <deal.II/grid/tria.h>
21
22#include <deal.II/lac/vector.h>
23
25
26#include <algorithm>
27#include <functional>
28#include <numeric>
29
31
33 const unsigned int look_back)
34 : look_ahead(look_ahead)
35 , look_back(look_back)
36{}
37
38
40 const TimeSteppingData &data_dual,
41 const TimeSteppingData &data_postprocess)
42 : sweep_no(numbers::invalid_unsigned_int)
43 , timestepping_data_primal(data_primal)
44 , timestepping_data_dual(data_dual)
45 , timestepping_data_postprocess(data_postprocess)
46{}
47
48
50{
51 try
52 {
53 while (timesteps.size() != 0)
55 }
56 catch (...)
57 {}
58}
59
60
61void
63 TimeStepBase *new_timestep)
64{
65 Assert((std::find(timesteps.begin(), timesteps.end(), position) !=
66 timesteps.end()) ||
67 (position == nullptr),
69 // first insert the new time step
70 // into the doubly linked list
71 // of timesteps
72 if (position == nullptr)
73 {
74 // at the end
75 new_timestep->set_next_timestep(nullptr);
76 if (timesteps.size() > 0)
77 {
78 timesteps.back()->set_next_timestep(new_timestep);
79 new_timestep->set_previous_timestep(timesteps.back());
80 }
81 else
82 new_timestep->set_previous_timestep(nullptr);
83 }
84 else if (position == timesteps[0])
85 {
86 // at the beginning
87 new_timestep->set_previous_timestep(nullptr);
88 if (timesteps.size() > 0)
89 {
90 timesteps[0]->set_previous_timestep(new_timestep);
91 new_timestep->set_next_timestep(timesteps[0]);
92 }
93 else
94 new_timestep->set_next_timestep(nullptr);
95 }
96 else
97 {
98 // inner time step
99 const std::vector<ObserverPointer<TimeStepBase, TimeDependent>>::iterator
100 insert_position =
101 std::find(timesteps.begin(), timesteps.end(), position);
102 // check iterators again to satisfy coverity: both insert_position and
103 // insert_position - 1 must be valid iterators
104 Assert(insert_position != timesteps.begin() &&
105 insert_position != timesteps.end(),
107
108 (*(insert_position - 1))->set_next_timestep(new_timestep);
109 new_timestep->set_previous_timestep(*(insert_position - 1));
110 new_timestep->set_next_timestep(*insert_position);
111 (*insert_position)->set_previous_timestep(new_timestep);
112 }
113
114 // finally enter it into the
115 // array
116 timesteps.insert((position == nullptr ?
117 timesteps.end() :
118 std::find(timesteps.begin(), timesteps.end(), position)),
119 new_timestep);
120}
121
122
123void
125{
126 insert_timestep(nullptr, new_timestep);
127}
128
129
130void
131TimeDependent::delete_timestep(const unsigned int position)
132{
133 Assert(position < timesteps.size(), ExcInvalidPosition());
134
135 // Remember time step object for
136 // later deletion and unlock
137 // ObserverPointer
138 TimeStepBase *t = timesteps[position];
139 timesteps[position] = nullptr;
140 // Now delete unsubscribed object
141 delete t;
142
143 timesteps.erase(timesteps.begin() + position);
144
145 // reset "next" pointer of previous
146 // time step if possible
147 //
148 // note that if now position==size,
149 // then we deleted the last time step
150 if (position != 0)
151 timesteps[position - 1]->set_next_timestep(
152 (position < timesteps.size()) ?
153 timesteps[position] :
155
156 // same for "previous" pointer of next
157 // time step
158 if (position < timesteps.size())
159 timesteps[position]->set_previous_timestep(
160 (position != 0) ?
161 timesteps[position - 1] :
163}
164
165
166void
168{
169 do_loop(
170 [](TimeStepBase *const time_step) { time_step->init_for_primal_problem(); },
171 [](TimeStepBase *const time_step) { time_step->solve_primal_problem(); },
173 forward);
174}
175
176
177void
179{
180 do_loop(
181 [](TimeStepBase *const time_step) { time_step->init_for_dual_problem(); },
182 [](TimeStepBase *const time_step) { time_step->init_for_dual_problem(); },
184 backward);
185}
186
187
188void
190{
191 do_loop(
192 [](TimeStepBase *const time_step) { time_step->init_for_postprocessing(); },
193 [](TimeStepBase *const time_step) { time_step->postprocess_timestep(); },
195 forward);
196}
197
198
199
200void
201TimeDependent::start_sweep(const unsigned int s)
202{
203 sweep_no = s;
204
205 // reset the number each
206 // time step has, since some time
207 // steps might have been added since
208 // the last time we visited them
209 //
210 // also set the sweep we will
211 // process in the sequel
212 for (unsigned int step = 0; step < timesteps.size(); ++step)
213 {
214 timesteps[step]->set_timestep_no(step);
215 timesteps[step]->set_sweep_no(sweep_no);
216 }
217
218 for (const auto &timestep : timesteps)
219 timestep->start_sweep();
220}
221
222
223
224void
226{
228 0U,
229 timesteps.size(),
230 [this](const unsigned int begin, const unsigned int end) {
231 this->end_sweep(begin, end);
232 },
233 1);
234}
235
236
237
238void
239TimeDependent::end_sweep(const unsigned int begin, const unsigned int end)
240{
241 for (unsigned int step = begin; step < end; ++step)
242 timesteps[step]->end_sweep();
243}
244
245
246
247std::size_t
249{
250 std::size_t mem =
255 for (const auto &timestep : timesteps)
257
258 return mem;
259}
260
261
262
263/* --------------------------------------------------------------------- */
264
265
267 : previous_timestep(nullptr)
268 , next_timestep(nullptr)
269 , sweep_no(numbers::invalid_unsigned_int)
270 , timestep_no(numbers::invalid_unsigned_int)
271 , time(time)
272 , next_action(numbers::invalid_unsigned_int)
273{}
274
275
276
277void
278TimeStepBase::wake_up(const unsigned int)
279{}
280
281
282
283void
284TimeStepBase::sleep(const unsigned)
285{}
286
287
288
289void
292
293
294
295void
298
299
300
301void
306
307
308
309void
314
315
316
317void
322
323
324
325void
330
331
332
333void
338
339
340
341double
343{
344 return time;
345}
346
347
348
349unsigned int
351{
352 return timestep_no;
353}
354
355
356
357double
359{
360 Assert(previous_timestep != nullptr,
361 ExcMessage("The backward time step cannot be computed because "
362 "there is no previous time step."));
363 return time - previous_timestep->time;
364}
365
366
367
368double
370{
371 Assert(next_timestep != nullptr,
372 ExcMessage("The forward time step cannot be computed because "
373 "there is no next time step."));
374 return next_timestep->time - time;
375}
376
377
378
379void
381{
382 previous_timestep = previous;
383}
384
385
386
387void
392
393
394
395void
396TimeStepBase::set_timestep_no(const unsigned int step_no)
397{
398 timestep_no = step_no;
399}
400
401
402
403void
404TimeStepBase::set_sweep_no(const unsigned int sweep)
405{
406 sweep_no = sweep;
407}
408
409
410
411std::size_t
413{
414 // only simple data types
415 return sizeof(*this);
416}
417
418
419
420template <int dim>
422 : TimeStepBase(0)
423 , tria(nullptr, typeid(*this).name())
424 , coarse_grid(nullptr, typeid(*this).name())
425 , flags()
426 , refinement_flags(0)
427{
429}
430
431
432
433#ifndef DOXYGEN
434template <int dim>
436 const double time,
437 const Triangulation<dim> &coarse_grid,
438 const Flags &flags,
439 const RefinementFlags &refinement_flags)
440 : TimeStepBase(time)
441 , tria(nullptr, typeid(*this).name())
442 , coarse_grid(&coarse_grid, typeid(*this).name())
443 , flags(flags)
444 , refinement_flags(refinement_flags)
445{}
446#endif
447
448
449
450template <int dim>
452{
453 if (!flags.delete_and_rebuild_tria)
454 {
455 Triangulation<dim> *t = tria;
456 tria = nullptr;
457 delete t;
458 }
459 else
460 AssertNothrow(tria == nullptr, ExcInternalError());
461
462 coarse_grid = nullptr;
463}
464
465
466
467template <int dim>
468void
469TimeStepBase_Tria<dim>::wake_up(const unsigned int wakeup_level)
470{
471 TimeStepBase::wake_up(wakeup_level);
472
473 if (wakeup_level == flags.wakeup_level_to_build_grid)
474 if (flags.delete_and_rebuild_tria || !tria)
475 restore_grid();
476}
477
478
479
480template <int dim>
481void
482TimeStepBase_Tria<dim>::sleep(const unsigned int sleep_level)
483{
484 if (sleep_level == flags.sleep_level_to_delete_grid)
485 {
486 Assert(tria != nullptr, ExcInternalError());
487
488 if (flags.delete_and_rebuild_tria)
489 {
490 Triangulation<dim> *t = tria;
491 tria = nullptr;
492 delete t;
493 }
494 }
495
496 TimeStepBase::sleep(sleep_level);
497}
498
499
500
501template <int dim>
502void
504{
505 // for any of the non-initial grids
506 // store the refinement flags
507 refine_flags.emplace_back();
508 coarsen_flags.emplace_back();
509 tria->save_refine_flags(refine_flags.back());
510 tria->save_coarsen_flags(coarsen_flags.back());
511}
512
513
514
515template <int dim>
516void
518{
519 Assert(tria == nullptr, ExcGridNotDeleted());
520 Assert(refine_flags.size() == coarsen_flags.size(), ExcInternalError());
521
522 // create an empty triangulation and
523 // set it to a copy of the coarse grid
524 tria = new Triangulation<dim>();
525 tria->copy_triangulation(*coarse_grid);
526
527 // for each of the previous refinement
528 // sweeps
529 for (unsigned int previous_sweep = 0; previous_sweep < refine_flags.size();
530 ++previous_sweep)
531 {
532 // get flags
533 tria->load_refine_flags(refine_flags[previous_sweep]);
534 tria->load_coarsen_flags(coarsen_flags[previous_sweep]);
535
536 // limit refinement depth if the user
537 // desired so
538 // if (flags.max_refinement_level != 0)
539 // {
540 // typename Triangulation<dim>::active_cell_iterator cell, endc;
541 // for (const auto &cell : tria->active_cell_iterators())
542 // if (static_cast<unsigned int>(cell->level()) >=
543 // flags.max_refinement_level)
544 // cell->clear_refine_flag();
545 // }
546
547 tria->execute_coarsening_and_refinement();
548 }
549}
550
551
552
553// have a few helper functions
554namespace
555{
556 template <int dim>
557 void
558 mirror_refinement_flags(
559 const typename Triangulation<dim>::cell_iterator &new_cell,
560 const typename Triangulation<dim>::cell_iterator &old_cell)
561 {
562 // mirror the refinement
563 // flags from the present time level to
564 // the previous if the dual problem was
565 // used for the refinement, since the
566 // error is computed on a time-space cell
567 //
568 // we don't mirror the coarsening flags
569 // since we want stronger refinement. if
570 // this was the wrong decision, the error
571 // on the child cells of the previous
572 // time slab will indicate coarsening
573 // in the next iteration, so this is not
574 // so dangerous here.
575 //
576 // also, we only have to check whether
577 // the present cell flagged for
578 // refinement and the previous one is on
579 // the same level and also active. If it
580 // already has children, then there is
581 // no problem at all, if it is on a lower
582 // level than the present one, then it
583 // will be refined below anyway.
584 if (new_cell->is_active())
585 {
586 if (new_cell->refine_flag_set() && old_cell->is_active())
587 {
588 if (old_cell->coarsen_flag_set())
589 old_cell->clear_coarsen_flag();
590
591 old_cell->set_refine_flag();
592 }
593
594 return;
595 }
596
597 if (old_cell->has_children() && new_cell->has_children())
598 {
599 Assert(old_cell->n_children() == new_cell->n_children(),
601 for (unsigned int c = 0; c < new_cell->n_children(); ++c)
602 ::mirror_refinement_flags<dim>(new_cell->child(c),
603 old_cell->child(c));
604 }
605 }
606
607
608
609 template <int dim>
610 bool
611 adapt_grid_cells(const typename Triangulation<dim>::cell_iterator &cell1,
612 const typename Triangulation<dim>::cell_iterator &cell2)
613 {
614 if (cell2->has_children() && cell1->has_children())
615 {
616 bool grids_changed = false;
617
618 Assert(cell2->n_children() == cell1->n_children(), ExcNotImplemented());
619 for (unsigned int c = 0; c < cell1->n_children(); ++c)
620 grids_changed |=
621 ::adapt_grid_cells<dim>(cell1->child(c), cell2->child(c));
622 return grids_changed;
623 }
624
625
626 if (!cell1->has_children() && !cell2->has_children())
627 // none of the two have children, so
628 // make sure that not one is flagged
629 // for refinement and the other for
630 // coarsening
631 {
632 if (cell1->refine_flag_set() && cell2->coarsen_flag_set())
633 {
634 cell2->clear_coarsen_flag();
635 return true;
636 }
637 else if (cell1->coarsen_flag_set() && cell2->refine_flag_set())
638 {
639 cell1->clear_coarsen_flag();
640 return true;
641 }
642
643 return false;
644 }
645
646
647 if (cell1->has_children() && !cell2->has_children())
648 // cell1 has children, cell2 has not
649 // -> cell2 needs to be refined if any
650 // of cell1's children is flagged
651 // for refinement. None of them should
652 // be refined further, since then in the
653 // last round something must have gone
654 // wrong
655 //
656 // if cell2 was flagged for coarsening,
657 // we need to clear that flag in any
658 // case. The only exception would be
659 // if all children of cell1 were
660 // flagged for coarsening, but rules
661 // for coarsening are so complicated
662 // that we will not attempt to cover
663 // them. Rather accept one cell which
664 // is not coarsened...
665 {
666 bool changed_grid = false;
667 if (cell2->coarsen_flag_set())
668 {
669 cell2->clear_coarsen_flag();
670 changed_grid = true;
671 }
672
673 if (!cell2->refine_flag_set())
674 for (unsigned int c = 0; c < cell1->n_children(); ++c)
675 if (cell1->child(c)->refine_flag_set() ||
676 cell1->child(c)->has_children())
677 {
678 cell2->set_refine_flag();
679 changed_grid = true;
680 break;
681 }
682 return changed_grid;
683 }
684
685 if (!cell1->has_children() && cell2->has_children())
686 // same thing, other way round...
687 {
688 bool changed_grid = false;
689 if (cell1->coarsen_flag_set())
690 {
691 cell1->clear_coarsen_flag();
692 changed_grid = true;
693 }
694
695 if (!cell1->refine_flag_set())
696 for (unsigned int c = 0; c < cell2->n_children(); ++c)
697 if (cell2->child(c)->refine_flag_set() ||
698 cell2->child(c)->has_children())
699 {
700 cell1->set_refine_flag();
701 changed_grid = true;
702 break;
703 }
704 return changed_grid;
705 }
706
708 return false;
709 }
710
711
712
713 template <int dim>
714 bool
715 adapt_grids(Triangulation<dim> &tria1, Triangulation<dim> &tria2)
716 {
717 bool grids_changed = false;
718
719 typename Triangulation<dim>::cell_iterator cell1 = tria1.begin(),
720 cell2 = tria2.begin();
722 endc = (tria1.n_levels() == 1 ?
723 typename Triangulation<dim>::cell_iterator(tria1.end()) :
724 tria1.begin(1));
725 for (; cell1 != endc; ++cell1, ++cell2)
726 grids_changed |= ::adapt_grid_cells<dim>(cell1, cell2);
727
728 return grids_changed;
729 }
730} // namespace
731
732
733template <int dim>
734void
736{
737 Vector<float> criteria;
738 get_tria_refinement_criteria(criteria);
739
740 // copy the following two values since
741 // we may need modified values in the
742 // process of this function
743 double refinement_threshold = refinement_data.refinement_threshold,
744 coarsening_threshold = refinement_data.coarsening_threshold;
745
746 // prepare an array where the criteria
747 // are stored in a sorted fashion
748 // we need this if cell number correction
749 // is switched on.
750 // the criteria are sorted in ascending
751 // order
752 // only fill it when needed
753 Vector<float> sorted_criteria;
754 // two pointers into this array denoting
755 // the position where the two thresholds
756 // are assumed
757 Vector<float>::const_iterator p_refinement_threshold = nullptr,
758 p_coarsening_threshold = nullptr;
759
760
761 // if we are to do some cell number
762 // correction steps, we have to find out
763 // which further cells (beyond
764 // refinement_threshold) to refine in case
765 // we need more cells, and which cells
766 // to not refine in case we need less cells
767 // (or even to coarsen, if necessary). to
768 // this end, we first define pointers into
769 // a sorted array of criteria pointing
770 // to the thresholds of refinement or
771 // coarsening; moving these pointers amounts
772 // to changing the threshold such that the
773 // number of cells flagged for refinement
774 // or coarsening would be changed by one
775 if ((timestep_no != 0) &&
776 (sweep_no >= refinement_flags.first_sweep_with_correction) &&
777 (refinement_flags.cell_number_correction_steps > 0))
778 {
779 sorted_criteria = criteria;
780 std::sort(sorted_criteria.begin(), sorted_criteria.end());
781 p_refinement_threshold =
782 Utilities::lower_bound(sorted_criteria.begin(),
783 sorted_criteria.end(),
784 static_cast<float>(refinement_threshold));
785 p_coarsening_threshold =
786 std::upper_bound(sorted_criteria.begin(),
787 sorted_criteria.end(),
788 static_cast<float>(coarsening_threshold));
789 }
790
791
792 // actually flag cells the first time
793 GridRefinement::refine(*tria, criteria, refinement_threshold);
794 GridRefinement::coarsen(*tria, criteria, coarsening_threshold);
795
796 // store this number for the following
797 // since its computation is rather
798 // expensive and since it doesn't change
799 const unsigned int n_active_cells = tria->n_active_cells();
800
801 // if not on first time level: try to
802 // adjust the number of resulting
803 // cells to those on the previous
804 // time level. Only do the cell number
805 // correction for higher sweeps and if
806 // there are sufficiently many cells
807 // already to avoid "grid stall" i.e.
808 // that the grid's evolution is hindered
809 // by the correction (this usually
810 // happens if there are very few cells,
811 // since then the number of cells touched
812 // by the correction step may exceed the
813 // number of cells which are flagged for
814 // refinement; in this case it often
815 // happens that the number of cells
816 // does not grow between sweeps, which
817 // clearly is not the wanted behavior)
818 //
819 // however, if we do not do anything, we
820 // can get into trouble somewhen later.
821 // therefore, we also use the correction
822 // step for the first sweep or if the
823 // number of cells is between 100 and 300
824 // (unlike in the first version of the
825 // algorithm), but relax the conditions
826 // for the correction to allow deviations
827 // which are three times as high than
828 // allowed (sweep==1 || cell number<200)
829 // or twice as high (sweep==2 ||
830 // cell number<300). Also, since
831 // refinement never does any harm other
832 // than increased work, we allow for
833 // arbitrary growth of cell number if
834 // the estimated cell number is below
835 // 200.
836 //
837 // repeat this loop several times since
838 // the first estimate may not be totally
839 // correct
840 if ((timestep_no != 0) &&
841 (sweep_no >= refinement_flags.first_sweep_with_correction))
842 for (unsigned int loop = 0;
843 loop < refinement_flags.cell_number_correction_steps;
844 ++loop)
845 {
846 Triangulation<dim> *previous_tria =
847 dynamic_cast<const TimeStepBase_Tria<dim> *>(previous_timestep)->tria;
848
849 // do one adaption step if desired
850 // (there are more coming below then
851 // also)
852 if (refinement_flags.adapt_grids)
853 ::adapt_grids<dim>(*previous_tria, *tria);
854
855 // perform flagging of cells
856 // needed to regularize the
857 // triangulation
858 tria->prepare_coarsening_and_refinement();
859 previous_tria->prepare_coarsening_and_refinement();
860
861
862 // now count the number of elements
863 // which will result on the previous
864 // grid after it will be refined. The
865 // number which will really result
866 // should be approximately that that we
867 // compute here, since we already
868 // performed most of the prepare*
869 // steps for the previous grid
870 //
871 // use a double value since for each
872 // four cells (in 2d) that we flagged
873 // for coarsening we result in one
874 // new. but since we loop over flagged
875 // cells, we have to subtract 3/4 of
876 // a cell for each flagged cell
877 Assert(!tria->get_anisotropic_refinement_flag(), ExcNotImplemented());
878 Assert(!previous_tria->get_anisotropic_refinement_flag(),
880 double previous_cells = previous_tria->n_active_cells();
882 cell = previous_tria->begin_active();
883 endc = previous_tria->end();
884 for (; cell != endc; ++cell)
885 if (cell->refine_flag_set())
886 previous_cells += (GeometryInfo<dim>::max_children_per_cell - 1);
887 else if (cell->coarsen_flag_set())
888 previous_cells -= static_cast<double>(
891
892 // @p{previous_cells} now gives the
893 // number of cells which would result
894 // from the flags on the previous grid
895 // if we refined it now. However, some
896 // more flags will be set when we adapt
897 // the previous grid with this one
898 // after the flags have been set for
899 // this time level; on the other hand,
900 // we don't account for this, since the
901 // number of cells on this time level
902 // will be changed afterwards by the
903 // same way, when it is adapted to the
904 // next time level
905
906 // now estimate the number of cells which
907 // will result on this level
908 double estimated_cells = n_active_cells;
909 cell = tria->begin_active();
910 endc = tria->end();
911 for (; cell != endc; ++cell)
912 if (cell->refine_flag_set())
913 estimated_cells += (GeometryInfo<dim>::max_children_per_cell - 1);
914 else if (cell->coarsen_flag_set())
915 estimated_cells -= static_cast<double>(
918
919 // calculate the allowed delta in
920 // cell numbers; be more lenient
921 // if there are few cells
922 double delta_up = refinement_flags.cell_number_corridor_top,
923 delta_down = refinement_flags.cell_number_corridor_bottom;
924
925 const std::vector<std::pair<unsigned int, double>> &relaxations =
926 (sweep_no >= refinement_flags.correction_relaxations.size() ?
927 refinement_flags.correction_relaxations.back() :
928 refinement_flags.correction_relaxations[sweep_no]);
929 for (const auto &relaxation : relaxations)
930 if (n_active_cells < relaxation.first)
931 {
932 delta_up *= relaxation.second;
933 delta_down *= relaxation.second;
934 break;
935 }
936
937 // now, if the number of estimated
938 // cells exceeds the number of cells
939 // on the old time level by more than
940 // delta: cut the top threshold
941 //
942 // note that for each cell that
943 // we unflag we have to diminish the
944 // estimated number of cells by
945 // @p{children_per_cell}.
946 if (estimated_cells > previous_cells * (1. + delta_up))
947 {
948 // only limit the cell number
949 // if there will not be less
950 // than some number of cells
951 //
952 // also note that when using the
953 // dual estimator, the initial
954 // time level is not refined
955 // on its own, so we may not
956 // limit the number of the second
957 // time level on the basis of
958 // the initial one; since for
959 // the dual estimator, we
960 // mirror the refinement
961 // flags, the initial level
962 // will be passively refined
963 // later on.
964 if (estimated_cells > refinement_flags.min_cells_for_correction)
965 {
966 // number of cells by which the
967 // new grid is to be diminished
968 double delta_cells =
969 estimated_cells - previous_cells * (1. + delta_up);
970
971 // if we need to reduce the
972 // number of cells, we need
973 // to raise the thresholds,
974 // i.e. move ahead in the
975 // sorted array, since this
976 // is sorted in ascending
977 // order. do so by removing
978 // cells tagged for refinement
979
980 for (unsigned int i = 0; i < delta_cells;
982 if (p_refinement_threshold != sorted_criteria.end())
983 ++p_refinement_threshold;
984 else
985 break;
986 }
987 else
988 // too many cells, but we
989 // won't do anything about
990 // that
991 break;
992 }
993 else
994 // likewise: if the estimated number
995 // of cells is less than 90 per cent
996 // of those at the previous time level:
997 // raise threshold by refining
998 // additional cells. if we start to
999 // run into the area of cells
1000 // which are to be coarsened, we
1001 // raise the limit for these too
1002 if (estimated_cells < previous_cells * (1. - delta_down))
1003 {
1004 // number of cells by which the
1005 // new grid is to be enlarged
1006 double delta_cells =
1007 previous_cells * (1. - delta_down) - estimated_cells;
1008 // heuristics: usually, if we
1009 // add @p{delta_cells} to the
1010 // present state, we end up
1011 // with much more than only
1012 // (1-delta_down)*prev_cells
1013 // because of the effect of
1014 // regularization and because
1015 // of adaption to the
1016 // following grid. Therefore,
1017 // if we are not in the last
1018 // correction loop, we try not
1019 // to add as many cells as seem
1020 // necessary at first and hope
1021 // to get closer to the limit
1022 // this way. Only in the last
1023 // loop do we have to take the
1024 // full number to guarantee the
1025 // wanted result.
1026 //
1027 // The value 0.9 is taken from
1028 // practice, as the additional
1029 // number of cells introduced
1030 // by regularization is
1031 // approximately 10 per cent
1032 // of the flagged cells.
1033 if (loop != refinement_flags.cell_number_correction_steps - 1)
1034 delta_cells *= 0.9;
1035
1036 // if more cells need to be
1037 // refined, we need to lower
1038 // the thresholds, i.e. to
1039 // move to the beginning
1040 // of sorted_criteria, which is
1041 // sorted in ascending order
1042 for (unsigned int i = 0; i < delta_cells;
1044 if (p_refinement_threshold != p_coarsening_threshold)
1045 --refinement_threshold;
1046 else if (p_coarsening_threshold != sorted_criteria.begin())
1047 --p_coarsening_threshold, --p_refinement_threshold;
1048 else
1049 break;
1050 }
1051 else
1052 // estimated cell number is ok,
1053 // stop correction steps
1054 break;
1055
1056 if (p_refinement_threshold == sorted_criteria.end())
1057 {
1058 Assert(p_coarsening_threshold != p_refinement_threshold,
1060 --p_refinement_threshold;
1061 }
1062
1063 coarsening_threshold = *p_coarsening_threshold;
1064 refinement_threshold = *p_refinement_threshold;
1065
1066 if (coarsening_threshold >= refinement_threshold)
1067 coarsening_threshold = 0.999 * refinement_threshold;
1068
1069 // now that we have re-adjusted
1070 // thresholds: clear all refine and
1071 // coarsening flags and do it all
1072 // over again
1073 cell = tria->begin_active();
1074 endc = tria->end();
1075 for (; cell != endc; ++cell)
1076 {
1077 cell->clear_refine_flag();
1078 cell->clear_coarsen_flag();
1079 }
1080
1081
1082 // flag cells finally
1083 GridRefinement::refine(*tria, criteria, refinement_threshold);
1084 GridRefinement::coarsen(*tria, criteria, coarsening_threshold);
1085 }
1086
1087 // if step number is greater than
1088 // one: adapt this and the previous
1089 // grid to each other. Don't do so
1090 // for the initial grid because
1091 // it is always taken to be the first
1092 // grid and needs therefore no
1093 // treatment of its own.
1094 if ((timestep_no >= 1) && (refinement_flags.adapt_grids))
1095 {
1096 Triangulation<dim> *previous_tria =
1097 dynamic_cast<const TimeStepBase_Tria<dim> *>(previous_timestep)->tria;
1098 Assert(previous_tria != nullptr, ExcInternalError());
1099
1100 // if we used the dual estimator, we
1101 // computed the error information on
1102 // a time slab, rather than on a level
1103 // of its own. we then mirror the
1104 // refinement flags we determined for
1105 // the present level to the previous
1106 // one
1107 //
1108 // do this mirroring only, if cell number
1109 // adjustment is on, since otherwise
1110 // strange things may happen
1111 if (refinement_flags.mirror_flags_to_previous_grid)
1112 {
1113 ::adapt_grids<dim>(*previous_tria, *tria);
1114
1115 typename Triangulation<dim>::cell_iterator old_cell, new_cell, endc;
1116 old_cell = previous_tria->begin(0);
1117 new_cell = tria->begin(0);
1118 endc = tria->end(0);
1119 for (; new_cell != endc; ++new_cell, ++old_cell)
1120 ::mirror_refinement_flags<dim>(new_cell, old_cell);
1121 }
1122
1123 tria->prepare_coarsening_and_refinement();
1124 previous_tria->prepare_coarsening_and_refinement();
1125
1126 // adapt present and previous grids
1127 // to each other: flag additional
1128 // cells to avoid the previous grid
1129 // to have cells refined twice more
1130 // than the present one and vica versa.
1131 ::adapt_grids<dim>(*previous_tria, *tria);
1132 }
1133}
1134
1135
1136
1137template <int dim>
1138void
1140{
1141 next_action = grid_refinement;
1142}
1143
1144
1145
1146template <int dim>
1147std::size_t
1149{
1150 return (TimeStepBase::memory_consumption() + sizeof(tria) +
1151 MemoryConsumption::memory_consumption(coarse_grid) + sizeof(flags) +
1152 sizeof(refinement_flags) +
1155}
1156
1157
1158
1159template <int dim>
1161 : delete_and_rebuild_tria(false)
1162 , wakeup_level_to_build_grid(0)
1163 , sleep_level_to_delete_grid(0)
1164{
1166}
1167
1168
1169
1170template <int dim>
1172 const bool delete_and_rebuild_tria,
1173 const unsigned int wakeup_level_to_build_grid,
1174 const unsigned int sleep_level_to_delete_grid)
1175 : delete_and_rebuild_tria(delete_and_rebuild_tria)
1176 , wakeup_level_to_build_grid(wakeup_level_to_build_grid)
1177 , sleep_level_to_delete_grid(sleep_level_to_delete_grid)
1178{
1179 // Assert (!delete_and_rebuild_tria || (wakeup_level_to_build_grid>=1),
1180 // ExcInvalidParameter(wakeup_level_to_build_grid));
1181 // Assert (!delete_and_rebuild_tria || (sleep_level_to_delete_grid>=1),
1182 // ExcInvalidParameter(sleep_level_to_delete_grid));
1183}
1184
1185
1186template <int dim>
1189 1, // one element, denoting the first and all subsequent sweeps
1190 std::vector<std::pair<unsigned int, double>>(1, // one element, denoting the
1191 // upper bound for the
1192 // following relaxation
1193 std::make_pair(0U, 0.)));
1194
1195
1196template <int dim>
1198 const unsigned int max_refinement_level,
1199 const unsigned int first_sweep_with_correction,
1200 const unsigned int min_cells_for_correction,
1201 const double cell_number_corridor_top,
1202 const double cell_number_corridor_bottom,
1203 const CorrectionRelaxations &correction_relaxations,
1204 const unsigned int cell_number_correction_steps,
1205 const bool mirror_flags_to_previous_grid,
1206 const bool adapt_grids)
1207 : max_refinement_level(max_refinement_level)
1208 , first_sweep_with_correction(first_sweep_with_correction)
1209 , min_cells_for_correction(min_cells_for_correction)
1210 , cell_number_corridor_top(cell_number_corridor_top)
1211 , cell_number_corridor_bottom(cell_number_corridor_bottom)
1212 , correction_relaxations(correction_relaxations.size() != 0 ?
1213 correction_relaxations :
1214 default_correction_relaxations)
1215 , cell_number_correction_steps(cell_number_correction_steps)
1216 , mirror_flags_to_previous_grid(mirror_flags_to_previous_grid)
1217 , adapt_grids(adapt_grids)
1218{
1225}
1226
1227
1228template <int dim>
1230 const double _refinement_threshold,
1231 const double _coarsening_threshold)
1232 : refinement_threshold(_refinement_threshold)
1233 ,
1234 // in some rare cases it may happen that
1235 // both thresholds are the same (e.g. if
1236 // there are many cells with the same
1237 // error indicator). That would mean that
1238 // all cells will be flagged for
1239 // refinement or coarsening, but some will
1240 // be flagged for both, namely those for
1241 // which the indicator equals the
1242 // thresholds. This is forbidden, however.
1243 //
1244 // In some rare cases with very few cells
1245 // we also could get integer round off
1246 // errors and get problems with
1247 // the top and bottom fractions.
1248 //
1249 // In these case we arbitrarily reduce the
1250 // bottom threshold by one permille below
1251 // the top threshold
1252 coarsening_threshold((_coarsening_threshold == _refinement_threshold ?
1253 _coarsening_threshold :
1254 0.999 * _coarsening_threshold))
1255{
1258 // allow both thresholds to be zero,
1259 // since this is needed in case all indicators
1260 // are zero
1262 ((coarsening_threshold == 0) && (refinement_threshold == 0)),
1264}
1265
1266
1267
1268/*-------------- Explicit Instantiations -------------------------------*/
1269#include "numerics/time_dependent.inst"
1270
1271
*  iterator end()
*  *  iterator begin()
void insert_timestep(const TimeStepBase *position, TimeStepBase *new_timestep)
virtual void start_sweep(const unsigned int sweep_no)
std::size_t memory_consumption() const
std::vector< ObserverPointer< TimeStepBase, TimeDependent > > timesteps
const TimeSteppingData timestepping_data_primal
virtual void end_sweep()
void solve_dual_problem()
virtual ~TimeDependent()
void do_loop(InitFunctionObject init_function, LoopFunctionObject loop_function, const TimeSteppingData &timestepping_data, const Direction direction)
const TimeSteppingData timestepping_data_dual
void solve_primal_problem()
unsigned int sweep_no
TimeDependent(const TimeSteppingData &data_primal, const TimeSteppingData &data_dual, const TimeSteppingData &data_postprocess)
void delete_timestep(const unsigned int position)
void add_timestep(TimeStepBase *new_timestep)
const TimeSteppingData timestepping_data_postprocess
virtual void wake_up(const unsigned int wakeup_level) override
virtual void sleep(const unsigned int) override
virtual std::size_t memory_consumption() const override
void refine_grid(const RefinementData data)
virtual void init_for_refinement()
typename TimeStepBase_Tria_Flags::RefinementData< dim > RefinementData
virtual ~TimeStepBase_Tria() override
virtual std::size_t memory_consumption() const
double get_forward_timestep() const
TimeStepBase(const double time)
virtual void wake_up(const unsigned int)
void set_timestep_no(const unsigned int step_no)
void set_previous_timestep(const TimeStepBase *previous)
const TimeStepBase * previous_timestep
virtual void postprocess_timestep()
virtual void sleep(const unsigned int)
unsigned int timestep_no
void set_next_timestep(const TimeStepBase *next)
unsigned int get_timestep_no() const
unsigned int next_action
double get_backward_timestep() const
void set_sweep_no(const unsigned int sweep_no)
const double time
unsigned int sweep_no
virtual void end_sweep()
virtual void solve_primal_problem()=0
virtual void init_for_postprocessing()
virtual void start_sweep()
virtual void init_for_primal_problem()
double get_time() const
virtual void solve_dual_problem()
virtual void init_for_dual_problem()
const TimeStepBase * next_timestep
bool get_anisotropic_refinement_flag() const
cell_iterator begin(const unsigned int level=0) const
unsigned int n_active_cells() const
unsigned int n_levels() const
cell_iterator end() const
virtual bool prepare_coarsening_and_refinement()
active_cell_iterator begin_active(const unsigned int level=0) const
const value_type * const_iterator
Definition vector.h:119
iterator end()
iterator begin()
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define DEAL_II_ASSERT_UNREACHABLE()
static ::ExceptionBase & ExcInvalidValue(double arg1)
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
static ::ExceptionBase & ExcPureFunctionCalled()
#define AssertNothrow(cond, exc)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcInvalidValue(double arg1)
static ::ExceptionBase & ExcMessage(std::string arg1)
static ::ExceptionBase & ExcInvalidPosition()
TriaIterator< CellAccessor< dim, spacedim > > cell_iterator
Definition tria.h:1621
std::size_t size
Definition mpi.cc:733
void refine(Triangulation< dim, spacedim > &tria, const Vector< Number > &criteria, const double threshold, const unsigned int max_to_mark=numbers::invalid_unsigned_int)
void coarsen(Triangulation< dim, spacedim > &tria, const Vector< Number > &criteria, const double threshold)
std::enable_if_t< std::is_fundamental_v< T >, std::size_t > memory_consumption(const T &t)
Iterator lower_bound(Iterator first, Iterator last, const T &val)
Definition utilities.h:1003
void apply_to_subranges(const Iterator &begin, const std_cxx20::type_identity_t< Iterator > &end, const Function &f, const unsigned int grainsize)
Definition parallel.h:266
TimeSteppingData(const unsigned int look_ahead, const unsigned int look_back)
RefinementData(const double refinement_threshold, const double coarsening_threshold=0)
RefinementFlags(const unsigned int max_refinement_level=0, const unsigned int first_sweep_with_correction=0, const unsigned int min_cells_for_correction=0, const double cell_number_corridor_top=(1<< dim), const double cell_number_corridor_bottom=1, const CorrectionRelaxations &correction_relaxations=CorrectionRelaxations(), const unsigned int cell_number_correction_steps=0, const bool mirror_flags_to_previous_grid=false, const bool adapt_grids=false)
std::vector< std::vector< std::pair< unsigned int, double > > > CorrectionRelaxations
static CorrectionRelaxations default_correction_relaxations