7 #include <deal.II/hp/fe_collection.h> 8 #include <deal.II/hp/fe_values.h> 9 #include <deal.II/hp/mapping_collection.h> 10 #include <deal.II/hp/q_collection.h> 12 #include <deal.II/base/geometry_info.h> 13 #include <deal.II/base/quadrature_lib.h> 14 #include <deal.II/base/quadrature.h> 16 #include <deal.II/fe/fe.h> 17 #include <deal.II/fe/fe_values.h> 18 #include <deal.II/fe/mapping.h> 20 #include <deal.II/grid/tria.h> 22 #include "physics/manufactured_solution.h" 24 #include "grid_refinement/field.h" 25 #include "size_field.h" 29 namespace GridRefinement {
37 template <
int dim,
typename real>
39 const real & complexity,
40 const dealii::Vector<real> & B,
41 const dealii::DoFHandler<dim> & dof_handler,
43 const real & poly_degree)
46 const real exponent = 2.0/((poly_degree+1)*q+2.0);
49 real integral_value = 0.0;
50 for(
auto cell = dof_handler.begin_active(); cell != dof_handler.end(); ++cell)
51 if(cell->is_locally_owned())
52 integral_value += pow(B[cell->active_cell_index()], exponent) * cell->measure();
55 integral_value *= pow(poly_degree+1, dim);
57 real integral_value_mpi = dealii::Utilities::MPI::sum(integral_value, MPI_COMM_WORLD);
60 const real K = complexity/integral_value_mpi;
63 h_field->reinit(dof_handler.get_triangulation().n_active_cells());
64 for(
auto cell = dof_handler.begin_active(); cell != dof_handler.end(); ++cell)
65 if(cell->is_locally_owned())
66 h_field->set_scale(cell->active_cell_index(), pow(K*pow(B[cell->active_cell_index()], exponent), -1.0/dim));
69 template <
int dim,
typename real>
71 const real complexity,
72 const dealii::Vector<real> & B,
73 const dealii::DoFHandler<dim> & dof_handler,
74 const dealii::hp::MappingCollection<dim> & mapping_collection,
75 const dealii::hp::FECollection<dim> & fe_collection,
76 const dealii::hp::QCollection<dim> & quadrature_collection,
77 const dealii::UpdateFlags & update_flags,
79 const dealii::Vector<real> & p_field)
83 auto f = [&](real lam) -> real{
84 update_h_optimal(lam, B, dof_handler, h_field, p_field);
85 real current_complexity = evaluate_complexity(dof_handler, mapping_collection, fe_collection, quadrature_collection, update_flags, h_field, p_field);
86 return current_complexity - complexity;
92 real lam = bisection(f, a, b);
95 update_h_optimal(lam, B, dof_handler, h_field, p_field);
98 template <
int dim,
typename real>
100 const dealii::DoFHandler<dim> & dof_handler,
101 const dealii::hp::MappingCollection<dim> & mapping_collection,
102 const dealii::hp::FECollection<dim> & fe_collection,
103 const dealii::hp::QCollection<dim> & quadrature_collection,
104 const dealii::UpdateFlags & update_flags,
106 const dealii::Vector<real> & p_field)
108 real complexity_sum = 0.0;
111 dealii::hp::FEValues<dim,dim> fe_values_collection(
114 quadrature_collection,
118 for(
auto cell = dof_handler.begin_active(); cell != dof_handler.end(); ++cell){
119 if(!cell->is_locally_owned())
continue;
121 const unsigned int index = cell->active_cell_index();
123 const unsigned int mapping_index = 0;
124 const unsigned int fe_index = cell->active_fe_index();
125 const unsigned int quad_index = fe_index;
127 const unsigned int n_quad = quadrature_collection[quad_index].size();
129 fe_values_collection.reinit(cell, quad_index, mapping_index, fe_index);
130 const dealii::FEValues<dim,dim> &fe_values = fe_values_collection.get_present_fe_values();
133 for(
unsigned int iquad = 0; iquad < n_quad; ++iquad)
134 JxW += fe_values.JxW(iquad);
136 complexity_sum += pow((p_field[index]+1)/h_field->get_scale(index), dim) * JxW;
139 return dealii::Utilities::MPI::sum(complexity_sum, MPI_COMM_WORLD);
142 template <
int dim,
typename real>
145 const dealii::Vector<real> & B,
146 const dealii::DoFHandler<dim> & dof_handler,
148 const dealii::Vector<real> & p_field)
153 for(
auto cell = dof_handler.begin_active(); cell != dof_handler.end(); ++cell){
154 if(!cell->is_locally_owned())
continue;
156 const unsigned int index = cell->active_cell_index();
158 const real p = p_field[index];
160 const real exponent = -1.0/(q*(p+1)+2.0);
161 const real component = q*(p+1.0)/(q*(p+1)+2.0) * B[index]/pow(p+1, dim);
163 h_field->set_scale(index, lam * pow(exponent, component));
205 template <
int dim,
typename real>
207 const real complexity,
208 const dealii::Vector<real> & Bm,
209 const dealii::Vector<real> & B,
210 const dealii::Vector<real> & Bp,
211 const dealii::DoFHandler<dim> & dof_handler,
212 const dealii::hp::MappingCollection<dim> & mapping_collection,
213 const dealii::hp::FECollection<dim> & fe_collection,
214 const dealii::hp::QCollection<dim> & quadrature_collection,
215 const dealii::UpdateFlags & update_flags,
217 dealii::Vector<real> & p_field)
225 quadrature_collection,
234 for(
auto cell = dof_handler.begin_active(); cell != dof_handler.end(); ++cell){
235 if(!cell->is_locally_owned())
continue;
237 unsigned int index = cell->active_cell_index();
240 const real e_ref = pow(abs(B[index]), q)
241 * pow(h_field->get_scale(index), dim*q*(p_field[index]+1)/2);
244 const real N_ref = pow((p_field[index]+1)/h_field->get_scale(index), dim);
248 const real h_m = (p_field[index]) /pow(N_ref, 1.0/dim);
249 const real h_p = (p_field[index]+2)/pow(N_ref, 1.0/dim);
252 const real e_m = pow(abs(Bm[index]), q)
253 * pow(h_m, dim*q*(p_field[index] )/2);
254 const real e_p = pow(abs(Bp[index]), q)
255 * pow(h_p, dim*q*(p_field[index]+2)/2);
258 if(e_m < e_ref && e_m <= e_p){
259 h_field->set_scale(index, h_m);
261 }
else if(e_p < e_ref && e_p <= e_m){
262 h_field->set_scale(index, h_p);
271 template <
int dim,
typename real>
273 const real complexity,
276 const dealii::Vector<real> & eta,
277 const dealii::DoFHandler<dim> & dof_handler,
278 const dealii::hp::MappingCollection<dim> & mapping_collection,
279 const dealii::hp::FECollection<dim> & fe_collection,
280 const dealii::hp::QCollection<dim> & quadrature_collection,
281 const dealii::UpdateFlags & update_flags,
283 const real & poly_degree)
286 dealii::Vector<real> p_field(dof_handler.get_triangulation().n_active_cells());
287 for(
auto cell = dof_handler.begin_active(); cell != dof_handler.end(); ++cell)
288 if(cell->is_locally_owned())
289 p_field[cell->active_cell_index()] = poly_degree;
300 quadrature_collection,
306 template <
int dim,
typename real>
308 const real complexity,
311 const dealii::Vector<real> & eta,
312 const dealii::DoFHandler<dim> & dof_handler,
313 const dealii::hp::MappingCollection<dim> & mapping_collection,
314 const dealii::hp::FECollection<dim> & fe_collection,
315 const dealii::hp::QCollection<dim> & quadrature_collection,
316 const dealii::UpdateFlags & update_flags,
318 const dealii::Vector<real> & p_field)
321 dealii::Vector<real> I_c(dof_handler.get_triangulation().n_active_cells());
322 for(
auto cell = dof_handler.begin_active(); cell != dof_handler.end(); ++cell)
323 if(cell->is_locally_owned())
324 I_c[cell->active_cell_index()] = pow(h_field->get_scale(cell->active_cell_index()), (real)dim);
327 real eta_min_local, eta_max_local;
329 for(
auto cell = dof_handler.begin_active(); cell != dof_handler.end(); ++cell){
330 if(!cell->is_locally_owned())
continue;
332 unsigned int index = cell->active_cell_index();
336 eta_min_local = eta[index];
337 eta_max_local = eta[index];
342 if(eta[index] < eta_min_local)
343 eta_min_local = eta[index];
345 if(eta[index] > eta_max_local)
346 eta_max_local = eta[index];
352 Assert(first, dealii::ExcInternalError());
355 real eta_min = dealii::Utilities::MPI::min(eta_min_local, MPI_COMM_WORLD);
356 real eta_max = dealii::Utilities::MPI::max(eta_max_local, MPI_COMM_WORLD);
358 real initial_complexity = evaluate_complexity(
362 quadrature_collection,
366 std::cout <<
"Starting complexity = " << initial_complexity << std::endl;
367 std::cout <<
"Target complexity = " << complexity << std::endl;
368 std::cout <<
"f_0 = " << (initial_complexity - complexity) << std::endl;
373 auto f = [&](real eta_ref) -> real{
375 update_alpha_vector_balan(
387 real current_complexity = evaluate_complexity(
391 quadrature_collection,
395 return current_complexity - complexity;
399 real eta_target = bisection(f, eta_max, eta_min);
400 std::cout <<
"Bisection finished with eta_ref = "<< eta_target <<
", f(eta_ref)=" << f(eta_target) << std::endl;
403 update_alpha_vector_balan(
418 template <
int dim,
typename real>
420 const real complexity,
421 const dealii::Vector<real> & eta,
422 const dealii::DoFHandler<dim> & dof_handler,
423 const dealii::hp::MappingCollection<dim> & mapping_collection,
424 const dealii::hp::FECollection<dim> & fe_collection,
425 const dealii::hp::QCollection<dim> & quadrature_collection,
426 const dealii::UpdateFlags & update_flags,
428 const real & poly_degree)
430 std::cout <<
"Starting equal distribution of DWR based on 2p+1 power." << std::endl;
433 dealii::Vector<real> p_field(dof_handler.get_triangulation().n_active_cells());
434 for(
auto cell = dof_handler.begin_active(); cell != dof_handler.end(); ++cell)
435 if(cell->is_locally_owned())
436 p_field[cell->active_cell_index()] = poly_degree;
439 real eta_min_local, eta_max_local;
441 for(
auto cell = dof_handler.begin_active(); cell != dof_handler.end(); ++cell){
442 if(!cell->is_locally_owned())
continue;
444 unsigned int index = cell->active_cell_index();
448 eta_min_local = eta[index];
449 eta_max_local = eta[index];
454 if(eta[index] < eta_min_local)
455 eta_min_local = eta[index];
457 if(eta[index] > eta_max_local)
458 eta_max_local = eta[index];
464 Assert(first, dealii::ExcInternalError());
467 real eta_min = dealii::Utilities::MPI::min(eta_min_local, MPI_COMM_WORLD);
468 real eta_max = dealii::Utilities::MPI::max(eta_max_local, MPI_COMM_WORLD);
472 auto f = [&](real tau) -> real{
482 real current_complexity = evaluate_complexity(
486 quadrature_collection,
490 return current_complexity - complexity;
494 real tau_target = bisection(f, eta_min, eta_max, 1e-10);
506 template <
int dim,
typename real>
509 const dealii::Vector<real> & eta,
510 const dealii::DoFHandler<dim> & dof_handler,
512 const real & poly_degree)
515 const real Nrt = 1.0/(2*poly_degree+1);
518 for(
auto cell = dof_handler.begin_active(); cell != dof_handler.end(); ++cell){
519 if(!cell->is_locally_owned())
continue;
521 unsigned int index = cell->active_cell_index();
524 const real h_target = pow(tau/eta[index], Nrt);
527 h_field->set_scale(index, h_target);
534 template <
int dim,
typename real>
536 const dealii::Vector<real>& eta,
542 const dealii::DoFHandler<dim>& dof_handler,
543 const dealii::Vector<real>& I_c,
547 for(
auto cell = dof_handler.begin_active(); cell != dof_handler.end(); ++cell){
548 if(!cell->is_locally_owned())
continue;
550 unsigned int index = cell->active_cell_index();
553 real alpha_k = update_alpha_k_balan(
562 real h_target = pow(alpha_k * I_c[index], 1.0/dim);
569 h_field->set_scale(index, h_target);
576 template <
int dim,
typename real>
592 real xi_k = (log(eta_k) - log(eta_ref)) / (log(eta_max) - log(eta_ref));
596 alpha_k = 1.0 / ((r_max-1)*xi_k*xi_k + 1.0);
598 }
else if(eta_k < eta_ref){
601 real xi_k = (log(eta_k) - log(eta_ref)) / (log(eta_min) - log(eta_ref));
604 alpha_k = ((c_max-1)*xi_k*xi_k + 1.0);
618 template <
int dim,
typename real>
620 const std::function<real(real)> func,
626 real f_lb = func(lower_bound);
627 real f_ub = func(upper_bound);
629 std::cout <<
"lb = " << lower_bound <<
", f_lb = " << f_lb << std::endl;
630 std::cout <<
"ub = " << upper_bound <<
", f_ub = " << f_ub << std::endl;
633 AssertThrow(f_lb * f_ub < 0, dealii::ExcInternalError());
635 real x = (lower_bound + upper_bound)/2.0;
639 const unsigned int max_iter = 1000;
641 real tolerance = rel_tolerance * abs(f_ub-f_lb);
642 if(abs_tolerance < tolerance)
643 tolerance = abs_tolerance;
646 while(abs(f_x) > tolerance && i < max_iter){
655 x = (lower_bound + upper_bound)/2.0;
658 std::cout <<
"iter #" << i <<
", x = " << x <<
", fx = " << f_x << std::endl;
663 Assert(i < max_iter, dealii::ExcInternalError());
static void adjoint_uniform_balan(const real complexity, const real r_max, const real c_max, const dealii::Vector< real > &eta, const dealii::DoFHandler< dim > &dof_handler, const dealii::hp::MappingCollection< dim > &mapping_collection, const dealii::hp::FECollection< dim > &fe_collection, const dealii::hp::QCollection< dim > &quadrature_collection, const dealii::UpdateFlags &update_flags, std::unique_ptr< Field< dim, real >> &h_field, const real &poly_degree)
Performs adjoint based size field adaptation for uniform polynomial distribution based on the method ...
static void isotropic_hp(const real complexity, const dealii::Vector< real > &Bm, const dealii::Vector< real > &B, const dealii::Vector< real > &Bp, const dealii::DoFHandler< dim > &dof_handler, const dealii::hp::MappingCollection< dim > &mapping_collection, const dealii::hp::FECollection< dim > &fe_collection, const dealii::hp::QCollection< dim > &quadrature_collection, const dealii::UpdateFlags &update_flags, std::unique_ptr< Field< dim, real >> &h_field, dealii::Vector< real > &p_field)
Computes the size field (element scale) and updated polynomial distrubition for high-order error func...
static void isotropic_h(const real complexity, const dealii::Vector< real > &B, const dealii::DoFHandler< dim > &dof_handler, const dealii::hp::MappingCollection< dim > &mapping_collection, const dealii::hp::FECollection< dim > &fe_collection, const dealii::hp::QCollection< dim > &quadrature_collection, const dealii::UpdateFlags &update_flags, std::unique_ptr< Field< dim, real >> &h_field, const dealii::Vector< real > &p_field)
Computes the size field (element scale) for a potentially non-uniform - distribution.
Files for the baseline physics.
static real bisection(const std::function< real(real)> func, real lower_bound, real upper_bound, real rel_tolerance=1e-6, real abs_tolerance=1.0)
Bisect function based on starting bounds.
static void update_h_optimal(const real lambda, const dealii::Vector< real > &B, const dealii::DoFHandler< dim > &dof_handler, std::unique_ptr< Field< dim, real >> &h_field, const dealii::Vector< real > &p_field)
Based on a chosen bisection paraemeter, updates the - field to an optimal distribution.
static void update_h_dwr(const real tau, const dealii::Vector< real > &eta, const dealii::DoFHandler< dim > &dof_handler, std::unique_ptr< Field< dim, real >> &h_field, const real &poly_degree)
Updates the size field based on the DWR disitribution and a reference value, .
static real evaluate_complexity(const dealii::DoFHandler< dim > &dof_handler, const dealii::hp::MappingCollection< dim > &mapping_collection, const dealii::hp::FECollection< dim > &fe_collection, const dealii::hp::QCollection< dim > &quadrature_collection, const dealii::UpdateFlags &update_flags, const std::unique_ptr< Field< dim, real >> &h_field, const dealii::Vector< real > &p_field)
Evaluates the continuous complexity (approximate degrees of freedom) for the target mesh representat...
static void isotropic_uniform(const real &complexity, const dealii::Vector< real > &B, const dealii::DoFHandler< dim > &dof_handler, std::unique_ptr< Field< dim, real >> &h_field, const real &poly_degree)
Computes the size field (element scale) for a uniform - distribution.
static void adjoint_h_balan(const real complexity, const real r_max, const real c_max, const dealii::Vector< real > &eta, const dealii::DoFHandler< dim > &dof_handler, const dealii::hp::MappingCollection< dim > &mapping_collection, const dealii::hp::FECollection< dim > &fe_collection, const dealii::hp::QCollection< dim > &quadrature_collection, const dealii::UpdateFlags &update_flags, std::unique_ptr< Field< dim, real >> &h_field, const dealii::Vector< real > &p_field)
Performs adjoint based size field adaptation for non-uniform polynomial distribution based on the met...
static void update_alpha_vector_balan(const dealii::Vector< real > &eta, const real r_max, const real c_max, const real eta_min, const real eta_max, const real eta_ref, const dealii::DoFHandler< dim > &dof_handler, const dealii::Vector< real > &I_c, std::unique_ptr< Field< dim, real >> &h_field)
Updates the size field for the mesh through the area measure based on reference value.
static void adjoint_h_equal(const real complexity, const dealii::Vector< real > &eta, const dealii::DoFHandler< dim > &dof_handler, const dealii::hp::MappingCollection< dim > &mapping_collection, const dealii::hp::FECollection< dim > &fe_collection, const dealii::hp::QCollection< dim > &quadrature_collection, const dealii::UpdateFlags &update_flags, std::unique_ptr< Field< dim, real >> &h_field, const real &poly_degree)
Performs adjoint based size field adaptation with a uniform - distribution based on equidistribution ...
static real update_alpha_k_balan(const real eta_k, const real r_max, const real c_max, const real eta_min, const real eta_max, const real eta_ref)
Determines local sizing factor (from adjoint estimates)