17 #include <deal.II/base/utilities.h> 19 #include <deal.II/lac/block_vector.h> 20 #include <deal.II/lac/trilinos_parallel_block_vector.h> 21 #include <deal.II/lac/trilinos_vector.h> 22 #include <deal.II/lac/vector.h> 24 #ifdef DEAL_II_WITH_P4EST 26 # include <deal.II/distributed/grid_refinement.h> 28 # include <deal.II/grid/grid_refinement.h> 29 # include <deal.II/grid/tria.h> 30 # include <deal.II/grid/tria_accessor.h> 31 # include <deal.II/grid/tria_iterator.h> 34 # include <functional> 39 DEAL_II_NAMESPACE_OPEN
44 template <
typename number>
46 max_element(const ::Vector<number> &criteria)
48 return (criteria.size() > 0) ?
49 (*std::max_element(criteria.begin(), criteria.end())) :
50 std::numeric_limits<number>::min();
55 template <
typename number>
57 min_element(const ::Vector<number> &criteria)
59 return (criteria.size() > 0) ?
60 (*std::min_element(criteria.begin(), criteria.end())) :
61 std::numeric_limits<number>::max();
69 template <
typename number>
70 std::pair<number, number>
71 compute_global_min_and_max_at_root(const ::Vector<number> &criteria,
72 MPI_Comm mpi_communicator)
78 const double local_min = min_element(criteria),
79 local_max = max_element(criteria);
80 double comp[2] = {local_min, -local_max};
81 double result[2] = {0, 0};
85 MPI_Reduce(comp, result, 2, MPI_DOUBLE, MPI_MIN, 0, mpi_communicator);
92 return std::make_pair(result[0], -result[1]);
102 template <
typename number>
104 compute_global_sum(const ::Vector<number> &criteria,
105 MPI_Comm mpi_communicator)
108 std::accumulate(criteria.begin(),
116 MPI_Reduce(&my_sum, &result, 1, MPI_DOUBLE, MPI_SUM, 0, mpi_communicator);
132 template <
int dim,
int spacedim,
typename Number>
134 get_locally_owned_indicators(
136 const ::Vector<Number> & criteria,
137 Vector<Number> &locally_owned_indicators)
139 Assert(locally_owned_indicators.size() ==
143 unsigned int owned_index = 0;
150 locally_owned_indicators(owned_index) =
151 criteria(cell->active_cell_index());
167 adjust_interesting_range(
double (&interesting_range)[2])
175 if (interesting_range[0] > 0)
176 interesting_range[0] *= 0.99;
178 if (interesting_range[1] > 0)
179 interesting_range[1] *= 1.01;
181 interesting_range[1] +=
182 0.01 * (interesting_range[1] - interesting_range[0]);
192 template <
int dim,
int spacedim,
typename Number>
195 const ::Vector<Number> & criteria,
196 const double top_threshold,
197 const double bottom_threshold)
199 ::GridRefinement::refine(tria, criteria, top_threshold);
200 ::GridRefinement::coarsen(tria, criteria, bottom_threshold);
210 cell->clear_refine_flag();
211 cell->clear_coarsen_flag();
223 template <
typename number>
225 compute_threshold(const ::Vector<number> & criteria,
226 const std::pair<double, double> &global_min_and_max,
227 const unsigned int n_target_cells,
228 MPI_Comm mpi_communicator)
230 double interesting_range[2] = {global_min_and_max.first,
231 global_min_and_max.second};
232 adjust_interesting_range(interesting_range);
234 const unsigned int master_mpi_rank = 0;
235 unsigned int iteration = 0;
239 int ierr = MPI_Bcast(interesting_range,
246 if (interesting_range[0] == interesting_range[1])
247 return interesting_range[0];
249 const double test_threshold =
250 (interesting_range[0] > 0 ?
251 std::sqrt(interesting_range[0] * interesting_range[1]) :
252 (interesting_range[0] + interesting_range[1]) / 2);
256 unsigned int my_count =
257 std::count_if(criteria.begin(),
259 [test_threshold](
const double c) {
260 return c > test_threshold;
263 unsigned int total_count = 0;
265 ierr = MPI_Reduce(&my_count,
280 if (total_count > n_target_cells)
281 interesting_range[0] = test_threshold;
282 else if (total_count < n_target_cells)
283 interesting_range[1] = test_threshold;
285 interesting_range[0] = interesting_range[1] = test_threshold;
298 interesting_range[0] = interesting_range[1] = test_threshold;
317 template <
typename number>
319 compute_threshold(const ::Vector<number> & criteria,
320 const std::pair<double, double> &global_min_and_max,
321 const double target_error,
322 MPI_Comm mpi_communicator)
324 double interesting_range[2] = {global_min_and_max.first,
325 global_min_and_max.second};
326 adjust_interesting_range(interesting_range);
328 const unsigned int master_mpi_rank = 0;
329 unsigned int iteration = 0;
333 int ierr = MPI_Bcast(interesting_range,
340 if (interesting_range[0] == interesting_range[1])
349 double final_threshold =
350 std::min(interesting_range[0], global_min_and_max.second);
351 ierr = MPI_Bcast(&final_threshold,
358 return final_threshold;
361 const double test_threshold =
362 (interesting_range[0] > 0 ?
363 std::sqrt(interesting_range[0] * interesting_range[1]) :
364 (interesting_range[0] + interesting_range[1]) / 2);
369 for (
unsigned int i = 0; i < criteria.size(); ++i)
370 if (criteria(i) > test_threshold)
371 my_error += criteria(i);
373 double total_error = 0.;
375 ierr = MPI_Reduce(&my_error,
390 if (total_error > target_error)
391 interesting_range[0] = test_threshold;
392 else if (total_error < target_error)
393 interesting_range[1] = test_threshold;
395 interesting_range[0] = interesting_range[1] = test_threshold;
409 interesting_range[0] = interesting_range[1] = test_threshold;
423 namespace distributed
427 template <
int dim,
typename Number,
int spacedim>
431 const ::Vector<Number> & criteria,
432 const double top_fraction_of_cells,
433 const double bottom_fraction_of_cells,
434 const unsigned int max_n_cells)
438 Assert((top_fraction_of_cells >= 0) && (top_fraction_of_cells <= 1),
440 Assert((bottom_fraction_of_cells >= 0) &&
441 (bottom_fraction_of_cells <= 1),
443 Assert(top_fraction_of_cells + bottom_fraction_of_cells <= 1,
445 Assert(criteria.is_non_negative(),
448 const std::pair<double, double> adjusted_fractions =
449 ::GridRefinement::adjust_refine_and_coarsen_number_fraction<
452 top_fraction_of_cells,
453 bottom_fraction_of_cells);
459 get_locally_owned_indicators(tria, criteria, locally_owned_indicators);
465 const std::pair<Number, Number> global_min_and_max =
466 compute_global_min_and_max_at_root(locally_owned_indicators,
470 double top_threshold, bottom_threshold;
471 top_threshold = RefineAndCoarsenFixedNumber::compute_threshold(
472 locally_owned_indicators,
474 static_cast<unsigned int>(adjusted_fractions.first *
480 if (adjusted_fractions.second > 0)
481 bottom_threshold = RefineAndCoarsenFixedNumber::compute_threshold(
482 locally_owned_indicators,
484 static_cast<unsigned int>((1 - adjusted_fractions.second) *
490 *std::min_element(criteria.begin(), criteria.end());
491 bottom_threshold -= std::fabs(bottom_threshold);
495 mark_cells(tria, criteria, top_threshold, bottom_threshold);
499 template <
int dim,
typename Number,
int spacedim>
503 const ::Vector<Number> & criteria,
504 const double top_fraction_of_error,
505 const double bottom_fraction_of_error)
509 Assert((top_fraction_of_error >= 0) && (top_fraction_of_error <= 1),
511 Assert((bottom_fraction_of_error >= 0) &&
512 (bottom_fraction_of_error <= 1),
514 Assert(top_fraction_of_error + bottom_fraction_of_error <= 1,
516 Assert(criteria.is_non_negative(),
523 get_locally_owned_indicators(tria, criteria, locally_owned_indicators);
529 const std::pair<double, double> global_min_and_max =
530 compute_global_min_and_max_at_root(locally_owned_indicators,
533 const double total_error =
534 compute_global_sum(locally_owned_indicators, mpi_communicator);
535 double top_threshold, bottom_threshold;
536 top_threshold = RefineAndCoarsenFixedFraction::compute_threshold(
537 locally_owned_indicators,
539 top_fraction_of_error * total_error,
543 if (bottom_fraction_of_error > 0)
544 bottom_threshold = RefineAndCoarsenFixedFraction::compute_threshold(
545 locally_owned_indicators,
547 (1 - bottom_fraction_of_error) * total_error,
552 *std::min_element(criteria.begin(), criteria.end());
553 bottom_threshold -= std::fabs(bottom_threshold);
557 mark_cells(tria, criteria, top_threshold, bottom_threshold);
565 # include "grid_refinement.inst" 567 DEAL_II_NAMESPACE_CLOSE
unsigned int n_active_cells() const
types::subdomain_id locally_owned_subdomain() const override
active_cell_iterator begin_active(const unsigned int level=0) const
void refine_and_coarsen_fixed_fraction(parallel::distributed::Triangulation< dim, spacedim > &tria, const ::Vector< Number > &criteria, const double top_fraction_of_error, const double bottom_fraction_of_error)
cell_iterator end() const
static ::ExceptionBase & ExcNegativeCriteria()
#define Assert(cond, exc)
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
void refine_and_coarsen_fixed_number(parallel::distributed::Triangulation< dim, spacedim > &tria, 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())
virtual MPI_Comm get_communicator() const
unsigned int n_locally_owned_active_cells() const
#define AssertThrowMPI(error_code)
unsigned int this_mpi_process(const MPI_Comm &mpi_communicator)
virtual types::global_dof_index n_global_active_cells() const override
static ::ExceptionBase & ExcInvalidParameterValue()
static ::ExceptionBase & ExcInternalError()