17 #include <deal.II/base/template_constraints.h> 19 #include <deal.II/grid/grid_refinement.h> 20 #include <deal.II/grid/tria.h> 21 #include <deal.II/grid/tria_accessor.h> 22 #include <deal.II/grid/tria_iterator.h> 24 #include <deal.II/lac/block_vector.h> 25 #include <deal.II/lac/block_vector_base.h> 26 #include <deal.II/lac/trilinos_parallel_block_vector.h> 27 #include <deal.II/lac/trilinos_vector.h> 28 #include <deal.II/lac/vector.h> 36 DEAL_II_NAMESPACE_OPEN
39 template <
int dim,
typename Number,
int spacedim>
42 const Vector<Number> & criteria,
43 const double threshold,
44 const unsigned int max_to_mark)
53 if (criteria.all_zero())
56 const unsigned int n_cells = criteria.size();
60 double new_threshold = threshold;
64 if (new_threshold == 0)
66 new_threshold = criteria(0);
67 for (
unsigned int index = 1; index < n_cells; ++index)
68 if (criteria(index) > 0 && (criteria(index) < new_threshold))
69 new_threshold = criteria(index);
72 unsigned int marked = 0;
77 if (std::fabs(criteria(cell->active_cell_index())) >= new_threshold)
80 marked >= max_to_mark)
83 cell->set_refine_flag();
89 template <
int dim,
typename Number,
int spacedim>
92 const Vector<Number> & criteria,
93 const double threshold)
103 if (std::fabs(criteria(cell->active_cell_index())) <= threshold)
104 if (!cell->refine_flag_set())
105 cell->set_coarsen_flag();
111 std::pair<double, double>
113 const unsigned int current_n_cells,
114 const unsigned int max_n_cells,
115 const double top_fraction,
116 const double bottom_fraction)
122 Assert(top_fraction + bottom_fraction <=
123 1 + 10 * std::numeric_limits<double>::epsilon(),
126 double refine_cells = current_n_cells * top_fraction;
127 double coarsen_cells = current_n_cells * bottom_fraction;
129 const double cell_increase_on_refine =
131 const double cell_decrease_on_coarsen =
134 std::pair<double, double> adjusted_fractions(top_fraction, bottom_fraction);
138 if (current_n_cells >= max_n_cells)
150 adjusted_fractions.first = 0;
152 (current_n_cells - max_n_cells) / cell_decrease_on_coarsen;
153 adjusted_fractions.second =
154 std::min(coarsen_cells / current_n_cells, 1.0);
169 else if (static_cast<unsigned int>(
170 current_n_cells + refine_cells * cell_increase_on_refine -
171 coarsen_cells * cell_decrease_on_coarsen) > max_n_cells)
181 const double alpha = 1. * (max_n_cells - current_n_cells) /
182 (refine_cells * cell_increase_on_refine -
183 coarsen_cells * cell_decrease_on_coarsen);
185 adjusted_fractions.first = alpha * top_fraction;
186 adjusted_fractions.second = alpha * bottom_fraction;
188 return (adjusted_fractions);
193 template <
int dim,
typename Number,
int spacedim>
197 const Vector<Number> & criteria,
198 const double top_fraction,
199 const double bottom_fraction,
200 const unsigned int max_n_cells)
204 Assert((top_fraction >= 0) && (top_fraction <= 1),
206 Assert((bottom_fraction >= 0) && (bottom_fraction <= 1),
208 Assert(top_fraction + bottom_fraction <=
209 1 + 10 * std::numeric_limits<double>::epsilon(),
213 const std::pair<double, double> adjusted_fractions =
214 adjust_refine_and_coarsen_number_fraction<dim>(criteria.size(),
219 const int refine_cells =
220 static_cast<int>(adjusted_fractions.first * criteria.size());
221 const int coarsen_cells =
222 static_cast<int>(adjusted_fractions.second * criteria.size());
224 if (refine_cells || coarsen_cells)
226 Vector<Number> tmp(criteria);
229 if (static_cast<size_t>(refine_cells) == criteria.size())
230 refine(tria, criteria, -std::numeric_limits<double>::max());
233 std::nth_element(tmp.begin(),
234 tmp.begin() + refine_cells,
236 std::greater<double>());
237 refine(tria, criteria, *(tmp.begin() + refine_cells));
243 if (static_cast<size_t>(coarsen_cells) == criteria.size())
244 coarsen(tria, criteria, std::numeric_limits<double>::max());
247 std::nth_element(tmp.begin(),
248 tmp.begin() + tmp.size() - coarsen_cells,
250 std::greater<double>());
253 *(tmp.begin() + tmp.size() - coarsen_cells));
261 template <
int dim,
typename Number,
int spacedim>
265 const Vector<Number> & criteria,
266 const double top_fraction,
267 const double bottom_fraction,
268 const unsigned int max_n_cells)
272 Assert((top_fraction >= 0) && (top_fraction <= 1),
274 Assert((bottom_fraction >= 0) && (bottom_fraction <= 1),
276 Assert(top_fraction + bottom_fraction <=
277 1 + 10 * std::numeric_limits<double>::epsilon(),
287 const double total_error = tmp.l1_norm();
291 std::sort(tmp.begin(), tmp.end(), std::greater<double>());
294 typename Vector<Number>::const_iterator pp = tmp.begin();
296 (
sum < top_fraction * total_error) && (pp != (tmp.end() - 1));
299 double top_threshold = (pp != tmp.begin() ? (*pp + *(pp - 1)) / 2 : *pp);
300 typename Vector<Number>::const_iterator qq = (tmp.end() - 1);
302 (
sum < bottom_fraction * total_error) && (qq != tmp.begin());
305 double bottom_threshold = (qq != (tmp.end() - 1) ? (*qq + *(qq + 1)) / 2 : 0);
320 const unsigned int refine_cells = pp - tmp.begin(),
321 coarsen_cells = tmp.end() - qq;
323 if (static_cast<unsigned int>(
329 refine_and_coarsen_fixed_number(tria,
331 1. * refine_cells / criteria.size(),
332 1. * coarsen_cells / criteria.size(),
370 const auto minmax_element =
371 std::minmax_element(criteria.begin(), criteria.end());
372 if ((top_threshold == *minmax_element.second) && (top_fraction != 1))
373 top_threshold *= 0.999;
375 if (bottom_threshold >= top_threshold)
376 bottom_threshold = 0.999 * top_threshold;
379 if (top_threshold < *minmax_element.second)
380 refine(tria, criteria, top_threshold, pp - tmp.
begin());
382 if (bottom_threshold > *minmax_element.first)
383 coarsen(tria, criteria, bottom_threshold);
388 template <
int dim,
typename Number,
int spacedim>
391 const Vector<Number> &criteria,
392 const unsigned int order)
399 std::vector<unsigned int> cell_indices(criteria.size());
400 std::iota(cell_indices.begin(), cell_indices.end(), 0u);
402 std::sort(cell_indices.begin(),
404 [&criteria](
const unsigned int left,
const unsigned int right) {
405 return criteria[left] > criteria[right];
408 double expected_error_reduction = 0;
409 const double original_error = criteria.l1_norm();
411 const std::size_t N = criteria.size();
414 double min_cost = std::numeric_limits<double>::max();
415 std::size_t min_arg = 0;
417 for (std::size_t M = 0; M < criteria.size(); ++M)
419 expected_error_reduction +=
420 (1 - std::pow(2., -1. * order)) * criteria(cell_indices[M]);
422 const double cost = std::pow(((std::pow(2., dim) - 1) * (1 + M) + N),
423 static_cast<double>(order) / dim) *
424 (original_error - expected_error_reduction);
425 if (cost <= min_cost)
432 refine(tria, criteria, criteria(cell_indices[min_arg]));
437 #include "grid_refinement.inst" 439 DEAL_II_NAMESPACE_CLOSE
unsigned int n_active_cells() const
static const unsigned int invalid_unsigned_int
active_cell_iterator begin_active(const unsigned int level=0) const
cell_iterator begin(const unsigned int level=0) const
cell_iterator end() const
void refine_and_coarsen_optimize(Triangulation< dim, spacedim > &tria, const Vector< Number > &criteria, const unsigned int order=2)
static ::ExceptionBase & ExcNegativeCriteria()
#define Assert(cond, exc)
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
void coarsen(Triangulation< dim, spacedim > &tria, const Vector< Number > &criteria, const double threshold)
SymmetricTensor< rank, dim, Number > sum(const SymmetricTensor< rank, dim, Number > &local, const MPI_Comm &mpi_communicator)
void refine_and_coarsen_fixed_fraction(Triangulation< dim, spacedim > &tria, const Vector< Number > &criteria, const double top_fraction, const double bottom_fraction, const unsigned int max_n_cells=std::numeric_limits< unsigned int >::max())
std::pair< double, double > adjust_refine_and_coarsen_number_fraction(const unsigned int current_n_cells, const unsigned int max_n_cells, const double top_fraction_of_cells, const double bottom_fraction_of_cells)
static ::ExceptionBase & ExcInvalidParameterValue()
void refine_and_coarsen_fixed_number(Triangulation< dim, spacedim > &triangulation, const Vector< Number > &criteria, const double top_fraction_of_cells, const double bottom_fraction_of_cells, const unsigned int max_n_cells=std::numeric_limits< unsigned int >::max())
void refine(Triangulation< dim, spacedim > &tria, const Vector< Number > &criteria, const double threshold, const unsigned int max_to_mark=numbers::invalid_unsigned_int)