[P]arallel [Hi]gh-order [Li]brary for [P]DEs  Latest
Parallel High-Order Library for PDEs through hp-adaptive Discontinuous Galerkin methods
size_field.cpp
1 #include <iostream>
2 #include <algorithm>
3 #include <functional>
4 
5 #include <Sacado.hpp>
6 
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>
11 
12 #include <deal.II/base/geometry_info.h>
13 #include <deal.II/base/quadrature_lib.h>
14 #include <deal.II/base/quadrature.h>
15 
16 #include <deal.II/fe/fe.h>
17 #include <deal.II/fe/fe_values.h>
18 #include <deal.II/fe/mapping.h>
19 
20 #include <deal.II/grid/tria.h>
21 
22 #include "physics/manufactured_solution.h"
23 
24 #include "grid_refinement/field.h"
25 #include "size_field.h"
26 
27 namespace PHiLiP {
28 
29 namespace GridRefinement {
30 // functions for computing the target size field over a domain,
31 // need various implementations for Hessian-exact, reconstructed quadratic
32 // adjoint based and then hp-cases
33 
34 // eventually add a parameter file to select how to construct the size field
35 // takes as input a target complexity, computes the h(x,y) (target isotropic
36 // size field) and outputs to a cell-wise vector for gmsh_out
37 template <int dim, typename real>
39  const real & complexity, // (input) complexity target
40  const dealii::Vector<real> & B, // only one since p is constant
41  const dealii::DoFHandler<dim> & dof_handler, // dof_handler
42  std::unique_ptr<Field<dim,real>> & h_field, // (output) size field
43  const real & poly_degree) // (input) polynomial degree
44 {
45  const real q = 2.0;
46  const real exponent = 2.0/((poly_degree+1)*q+2.0);
47 
48  // integral value
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();
53 
54  // complexity per cell (based on polynomial orer)
55  integral_value *= pow(poly_degree+1, dim);
56 
57  real integral_value_mpi = dealii::Utilities::MPI::sum(integral_value, MPI_COMM_WORLD);
58 
59  // constant known (since q and p are uniform, otherwise would be a function of p and w)
60  const real K = complexity/integral_value_mpi;
61 
62  // looping over the elements to define the sizes
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));
67 }
68 
69 template <int dim, typename real>
71  const real complexity, // (input) complexity target
72  const dealii::Vector<real> & B, // only one since p is constant
73  const dealii::DoFHandler<dim> & dof_handler, // dof_handler
74  const dealii::hp::MappingCollection<dim> & mapping_collection, // mapping collection
75  const dealii::hp::FECollection<dim> & fe_collection, // fe collection
76  const dealii::hp::QCollection<dim> & quadrature_collection, // quadrature collection
77  const dealii::UpdateFlags & update_flags, // update flags for for volume fe
78  std::unique_ptr<Field<dim,real>> & h_field, // (output) size field
79  const dealii::Vector<real> & p_field) // (input) poly field
80 {
81  // setting up lambda function which, given a constant for the size field,
82  // updates the h distribution and outputs the new complexity
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;
87  };
88 
89  // call to the optimization (bisection)
90  real a = 0;
91  real b = 1000;
92  real lam = bisection(f, a, b);
93 
94  // final update with converged parameter
95  update_h_optimal(lam, B, dof_handler, h_field, p_field);
96 }
97 
98 template <int dim, typename real>
100  const dealii::DoFHandler<dim> & dof_handler, // dof_handler
101  const dealii::hp::MappingCollection<dim> & mapping_collection, // mapping collection
102  const dealii::hp::FECollection<dim> & fe_collection, // fe collection
103  const dealii::hp::QCollection<dim> & quadrature_collection, // quadrature collection
104  const dealii::UpdateFlags & update_flags, // update flags for for volume fe
105  const std::unique_ptr<Field<dim,real>> & h_field, // (input) size field
106  const dealii::Vector<real> & p_field) // (input) poly field
107 {
108  real complexity_sum = 0.0;
109 
110  // fe_values
111  dealii::hp::FEValues<dim,dim> fe_values_collection(
112  mapping_collection,
113  fe_collection,
114  quadrature_collection,
115  update_flags);
116 
117  // evaluate the complexity of a provided field
118  for(auto cell = dof_handler.begin_active(); cell != dof_handler.end(); ++cell){
119  if(!cell->is_locally_owned()) continue;
120 
121  const unsigned int index = cell->active_cell_index();
122 
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;
126 
127  const unsigned int n_quad = quadrature_collection[quad_index].size();
128 
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();
131 
132  real JxW = 0;
133  for(unsigned int iquad = 0; iquad < n_quad; ++iquad)
134  JxW += fe_values.JxW(iquad);
135 
136  complexity_sum += pow((p_field[index]+1)/h_field->get_scale(index), dim) * JxW;
137  }
138 
139  return dealii::Utilities::MPI::sum(complexity_sum, MPI_COMM_WORLD);
140 }
141 
142 template <int dim, typename real>
144  const real lam, // (input) bisection parameter
145  const dealii::Vector<real> & B, // constant for current p
146  const dealii::DoFHandler<dim> & dof_handler, // dof_handler
147  std::unique_ptr<Field<dim,real>> & h_field, // (output) size field
148  const dealii::Vector<real> & p_field) // (input) poly field
149 {
150  const real q = 2.0;
151 
152  // looping over the cells and updating the values
153  for(auto cell = dof_handler.begin_active(); cell != dof_handler.end(); ++cell){
154  if(!cell->is_locally_owned()) continue;
155 
156  const unsigned int index = cell->active_cell_index();
157 
158  const real p = p_field[index];
159 
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);
162 
163  h_field->set_scale(index, lam * pow(exponent, component));
164  }
165 }
166 
167 // computes updated p-field with a constant h-field
168 // NOT IMPLEMENTED yet
169 /*
170 template <int dim, typename real>
171 void SizeField<dim,real>::isotropic_p(
172  const dealii::Vector<real> & Bm, // constant for p-1
173  const dealii::Vector<real> & B, // constant for p
174  const dealii::Vector<real> & Bp, // constant for p+1
175  const dealii::DoFHandler<dim> & dof_handler, // dof_handler
176  const dealii::hp::MappingCollection<dim> & mapping_collection, // mapping collection
177  const dealii::hp::FECollection<dim> & fe_collection, // fe collection
178  const dealii::hp::QCollection<dim> & quadrature_collection, // quadrature collection
179  const dealii::UpdateFlags & update_flags, // update flags for for volume fe
180  const std::unique_ptr<Field<dim,real>> & h_field, // (input) size field
181  dealii::Vector<real> & p_field) // (output) poly field
182 {
183  (void)Bm;
184  (void)B;
185  (void)Bp;
186  (void)dof_handler;
187  (void)mapping_collection;
188  (void)fe_collection;
189  (void)quadrature_collection;
190  (void)update_flags;
191  (void)h_field;
192  (void)p_field;
193 
194  // this is like its own thing, might have to do the integration or something
195  // because we can't adjust the local h to compensate for p increases, needs
196  // to be adjusted as a global system
197 
198  // maybe: start from current, check dofs/error and adjust to anything above/below the average
199  // refine progressively if complexity is below the limit
200  // coarsen progressively if above
201  // need some way of measuring when stability is reached. Maybe can be done as a bulk criterion
202 }
203 */
204 
205 template <int dim, typename real>
207  const real complexity, // complexity target
208  const dealii::Vector<real> & Bm, // constant for p-1
209  const dealii::Vector<real> & B, // constant for p
210  const dealii::Vector<real> & Bp, // constant for p+1
211  const dealii::DoFHandler<dim> & dof_handler, // dof_handler
212  const dealii::hp::MappingCollection<dim> & mapping_collection, // mapping collection
213  const dealii::hp::FECollection<dim> & fe_collection, // fe collection
214  const dealii::hp::QCollection<dim> & quadrature_collection, // quadrature collection
215  const dealii::UpdateFlags & update_flags, // update flags for for volume fe
216  std::unique_ptr<Field<dim,real>> & h_field, // (output) size field
217  dealii::Vector<real> & p_field) // (output) poly field
218 {
219  isotropic_h(
220  complexity,
221  B,
222  dof_handler,
223  mapping_collection,
224  fe_collection,
225  quadrature_collection,
226  update_flags,
227  h_field,
228  p_field);
229 
230  const real q = 2.0;
231 
232  // two options here, either constant error (preferable)
233  // or constant complexity target (Dolejsi)
234  for(auto cell = dof_handler.begin_active(); cell != dof_handler.end(); ++cell){
235  if(!cell->is_locally_owned()) continue;
236 
237  unsigned int index = cell->active_cell_index();
238 
239  // computing the reference error
240  const real e_ref = pow(abs(B[index]), q)
241  * pow(h_field->get_scale(index), dim*q*(p_field[index]+1)/2);
242 
243  // local complexity
244  const real N_ref = pow((p_field[index]+1)/h_field->get_scale(index), dim);
245 
246  // constant error
247  // computing the error for increased/decreased p with the same local complexity
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);
250 
251  // computing the local error for each
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);
256 
257  // determining which is the smallest and adjusting
258  if(e_m < e_ref && e_m <= e_p){
259  h_field->set_scale(index, h_m);
260  p_field[index]--;
261  }else if(e_p < e_ref && e_p <= e_m){
262  h_field->set_scale(index, h_p);
263  p_field[index]++;
264  }// else, p stays the same
265  }
266 
267  // either add a check here for which is obtained or add an output for the +/-
268  // only if another change needs to be made here
269 }
270 
271 template <int dim, typename real>
273  const real complexity, // target complexity
274  const real r_max, // maximum refinement factor
275  const real c_max, // maximum coarsening factor
276  const dealii::Vector<real> & eta, // error indicator (DWR)
277  const dealii::DoFHandler<dim> & dof_handler, // dof_handler
278  const dealii::hp::MappingCollection<dim> & mapping_collection, // mapping collection
279  const dealii::hp::FECollection<dim> & fe_collection, // fe collection
280  const dealii::hp::QCollection<dim> & quadrature_collection, // quadrature collection
281  const dealii::UpdateFlags & update_flags, // update flags for for volume fe
282  std::unique_ptr<Field<dim,real>>& h_field, // (output) target size_field
283  const real & poly_degree) // uniform polynomial degree
284 {
285  // creating a proper polynomial vector
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;
290 
291  // calling the regular version of adjoint_h
292  adjoint_h_balan(
293  complexity,
294  r_max,
295  c_max,
296  eta,
297  dof_handler,
298  mapping_collection,
299  fe_collection,
300  quadrature_collection,
301  update_flags,
302  h_field,
303  p_field);
304 }
305 
306 template <int dim, typename real>
308  const real complexity, // target complexity
309  const real r_max, // maximum refinement factor
310  const real c_max, // maximum coarsening factor
311  const dealii::Vector<real> & eta, // error indicator (DWR)
312  const dealii::DoFHandler<dim> & dof_handler, // dof_handler
313  const dealii::hp::MappingCollection<dim> & mapping_collection, // mapping collection
314  const dealii::hp::FECollection<dim> & fe_collection, // fe collection
315  const dealii::hp::QCollection<dim> & quadrature_collection, // quadrature collection
316  const dealii::UpdateFlags & update_flags, // update flags for for volume fe
317  std::unique_ptr<Field<dim,real>>& h_field, // (output) target size_field
318  const dealii::Vector<real> & p_field) // polynomial degree vector
319 {
320  // getting the I_c vector of the initial sizes
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);
325 
326  // getting minimum and maximum of eta
327  real eta_min_local, eta_max_local;
328  bool first = true;
329  for(auto cell = dof_handler.begin_active(); cell != dof_handler.end(); ++cell){
330  if(!cell->is_locally_owned()) continue;
331 
332  unsigned int index = cell->active_cell_index();
333 
334  // for first cell found, setting the value
335  if(first){
336  eta_min_local = eta[index];
337  eta_max_local = eta[index];
338  first = false;
339  }else{
340 
341  // performing checks
342  if(eta[index] < eta_min_local)
343  eta_min_local = eta[index];
344 
345  if(eta[index] > eta_max_local)
346  eta_max_local = eta[index];
347 
348  }
349  }
350 
351  // each processor needs atleast 1 cell
352  Assert(first, dealii::ExcInternalError());
353 
354  // perform mpi call
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);
357 
358  real initial_complexity = evaluate_complexity(
359  dof_handler,
360  mapping_collection,
361  fe_collection,
362  quadrature_collection,
363  update_flags,
364  h_field,
365  p_field);
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;
369 
370  // setting up the bisection functional, based on an input value of
371  // eta_ref, determines the complexity value for the mesh (using DWR estimates
372  // weighted in the quadratic logarithmic space).
373  auto f = [&](real eta_ref) -> real{
374  // updating the size field
375  update_alpha_vector_balan(
376  eta,
377  r_max,
378  c_max,
379  eta_min,
380  eta_max,
381  eta_ref,
382  dof_handler,
383  I_c,
384  h_field);
385 
386  // getting the complexity and returning the difference with the target
387  real current_complexity = evaluate_complexity(
388  dof_handler,
389  mapping_collection,
390  fe_collection,
391  quadrature_collection,
392  update_flags,
393  h_field,
394  p_field);
395  return current_complexity - complexity;
396  };
397 
398  // call to optimization (bisection), using min and max as initial bounds
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;
401 
402  // final uppdate using the converged parameter
403  update_alpha_vector_balan(
404  eta,
405  r_max,
406  c_max,
407  eta_min,
408  eta_max,
409  eta_target,
410  dof_handler,
411  I_c,
412  h_field);
413 
414 }
415 
416 // performs adjoint based size field adaptatation with uniform p-field
417 // peforms equidistribution of DWR to sizes based on 2p+1 power of convergence
418 template <int dim, typename real>
420  const real complexity, // target complexity
421  const dealii::Vector<real> & eta, // error indicator (DWR)
422  const dealii::DoFHandler<dim> & dof_handler, // dof_handler
423  const dealii::hp::MappingCollection<dim> & mapping_collection, // mapping collection
424  const dealii::hp::FECollection<dim> & fe_collection, // fe collection
425  const dealii::hp::QCollection<dim> & quadrature_collection, // quadrature collection
426  const dealii::UpdateFlags & update_flags, // update flags for for volume fe
427  std::unique_ptr<Field<dim,real>>& h_field, // (output) target size_field
428  const real & poly_degree) // uniform polynomial degree
429 {
430  std::cout << "Starting equal distribution of DWR based on 2p+1 power." << std::endl;
431 
432  // creating a proper polynomial vector
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;
437 
438  // getting minimum and maximum of eta
439  real eta_min_local, eta_max_local;
440  bool first = true;
441  for(auto cell = dof_handler.begin_active(); cell != dof_handler.end(); ++cell){
442  if(!cell->is_locally_owned()) continue;
443 
444  unsigned int index = cell->active_cell_index();
445 
446  // for first cell found, setting the value
447  if(first){
448  eta_min_local = eta[index];
449  eta_max_local = eta[index];
450  first = false;
451  }else{
452 
453  // performing checks
454  if(eta[index] < eta_min_local)
455  eta_min_local = eta[index];
456 
457  if(eta[index] > eta_max_local)
458  eta_max_local = eta[index];
459 
460  }
461  }
462 
463  // each processor needs atleast 1 cell
464  Assert(first, dealii::ExcInternalError());
465 
466  // perform mpi call
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);
469 
470  // setting up the bisection functional, based on an input value of tau
471  // determines new size from 2p+1 root relative to local DWR
472  auto f = [&](real tau) -> real{
473  // updating the size field
474  update_h_dwr(
475  tau,
476  eta,
477  dof_handler,
478  h_field,
479  poly_degree);
480 
481  // getting the complexity and returning the difference with the target
482  real current_complexity = evaluate_complexity(
483  dof_handler,
484  mapping_collection,
485  fe_collection,
486  quadrature_collection,
487  update_flags,
488  h_field,
489  p_field);
490  return current_complexity - complexity;
491  };
492 
493  // performing the bisection call
494  real tau_target = bisection(f, eta_min, eta_max, 1e-10);
495 
496  // updating the size field
497  update_h_dwr(
498  tau_target,
499  eta,
500  dof_handler,
501  h_field,
502  poly_degree);
503 }
504 
505 // sets the h_field sizes based on a reference value and DWR distribution
506 template <int dim, typename real>
508  const real tau, // reference value for settings sizes
509  const dealii::Vector<real> & eta, // error indicator (DWR)
510  const dealii::DoFHandler<dim> & dof_handler, // dof_handler
511  std::unique_ptr<Field<dim,real>>& h_field, // (output) target size_field
512  const real & poly_degree) // uniform polynomial degree
513 {
514  // exponent for inverse DWR scaling
515  const real Nrt = 1.0/(2*poly_degree+1);
516 
517  // looping through the cells and updating their size using tau
518  for(auto cell = dof_handler.begin_active(); cell != dof_handler.end(); ++cell){
519  if(!cell->is_locally_owned()) continue;
520 
521  unsigned int index = cell->active_cell_index();
522 
523  // getting the new length based on Nrt
524  const real h_target = pow(tau/eta[index], Nrt);
525 
526  // applying in the field
527  h_field->set_scale(index, h_target);
528  }
529 
530 }
531 
532 // updates the size targets for the entire mesh (from alpha)
533 // based on the input of a bisection parameter eta_ref
534 template <int dim, typename real>
536  const dealii::Vector<real>& eta, // vector of DWR indicators
537  const real r_max, // max refinement factor
538  const real c_max, // max coarsening factor
539  const real eta_min, // minimum DWR
540  const real eta_max, // maximum DWR
541  const real eta_ref, // reference parameter for bisection
542  const dealii::DoFHandler<dim>& dof_handler, // dof_handler
543  const dealii::Vector<real>& I_c, // cell area measure
544  std::unique_ptr<Field<dim,real>>& h_field) // (output) size-field
545 {
546  // looping through the cells and updating their size (h_field)
547  for(auto cell = dof_handler.begin_active(); cell != dof_handler.end(); ++cell){
548  if(!cell->is_locally_owned()) continue;
549 
550  unsigned int index = cell->active_cell_index();
551 
552  // getting the alpha factor for the cell update
553  real alpha_k = update_alpha_k_balan(
554  eta[index],
555  r_max,
556  c_max,
557  eta_min,
558  eta_max,
559  eta_ref);
560 
561  // getting the new length based on I_c (cell area)
562  real h_target = pow(alpha_k * I_c[index], 1.0/dim);
563 
564  // real h = h_field->get_scale(index);
565  // std::cout << "h = " << h << ", h_t = " << h_target << ", alpha = " << alpha_k << std::endl;
566  // std::cout << "I_c = " << I_c[index] << ", sqrt(I_c) = " << pow(I_c[index], 1.0/dim) << std::endl;;
567 
568  // updating the h_field
569  h_field->set_scale(index, h_target);
570 
571  }
572 }
573 
574 // function that determines local alpha size refinement factor (from adjoint estimates)
575 // from eq. 30-33 of Balan et al. "djoint-based hp-adaptivity on anisotropic meshes for high-order..."
576 template <int dim, typename real>
578  const real eta_k, // local DWR factor
579  const real r_max, // maximum refinement factor
580  const real c_max, // maximum coarsening factor
581  const real eta_min, // minimum DWR indicator
582  const real eta_max, // maximum DWR indicator
583  const real eta_ref) // referebce DWR for determining coarsening/refinement
584 {
585  // considering two possible cases (above or below reference)
586  // also need to check close to equality to avoid divide by ~= 0
587  real alpha_k;
588 
589  if(eta_k > eta_ref){
590 
591  // getting the quadratic coefficient
592  real xi_k = (log(eta_k) - log(eta_ref)) / (log(eta_max) - log(eta_ref));
593 
594 
595  // getting the refinement factor
596  alpha_k = 1.0 / ((r_max-1)*xi_k*xi_k + 1.0);
597 
598  }else if(eta_k < eta_ref){
599 
600  // getting the quadratic coefficient
601  real xi_k = (log(eta_k) - log(eta_ref)) / (log(eta_min) - log(eta_ref));
602 
603  // getting the coarsening factor
604  alpha_k = ((c_max-1)*xi_k*xi_k + 1.0);
605 
606  }else{
607 
608  // performing no change (right on)
609  alpha_k = 1.0;
610 
611  }
612 
613  // update area fraction (relative to initial area)
614  return alpha_k;
615 }
616 
617 // functions for solving non-linear problems
618 template <int dim, typename real>
620  const std::function<real(real)> func,
621  real lower_bound,
622  real upper_bound,
623  real rel_tolerance,
624  real abs_tolerance)
625 {
626  real f_lb = func(lower_bound);
627  real f_ub = func(upper_bound);
628 
629  std::cout << "lb = " << lower_bound << ", f_lb = " << f_lb << std::endl;
630  std::cout << "ub = " << upper_bound << ", f_ub = " << f_ub << std::endl;
631 
632  // f_ub is unused before being reset if not present here
633  AssertThrow(f_lb * f_ub < 0, dealii::ExcInternalError());
634 
635  real x = (lower_bound + upper_bound)/2.0;
636  real f_x = func(x);
637 
638  // const real rel_tolerance = 1e-6;
639  const unsigned int max_iter = 1000;
640 
641  real tolerance = rel_tolerance * abs(f_ub-f_lb);
642  if(abs_tolerance < tolerance)
643  tolerance = abs_tolerance;
644 
645  unsigned int i = 0;
646  while(abs(f_x) > tolerance && i < max_iter){
647  if(f_x * f_lb < 0){
648  upper_bound = x;
649  f_ub = f_x;
650  }else{
651  lower_bound = x;
652  f_lb = f_x;
653  }
654 
655  x = (lower_bound + upper_bound)/2.0;
656  f_x = func(x);
657 
658  std::cout << "iter #" << i << ", x = " << x << ", fx = " << f_x << std::endl;
659 
660  i++;
661  }
662 
663  Assert(i < max_iter, dealii::ExcInternalError());
664 
665  return x;
666 }
667 
668 template class SizeField <PHILIP_DIM, double>;
669 // template class SizeField <PHILIP_DIM, float>; // manufactured solution isn't defined for this
670 
671 } // namespace GridRefinement
672 
673 } // namespace PHiLiP
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 ...
Definition: size_field.cpp:272
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...
Definition: size_field.cpp:206
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.
Definition: size_field.cpp:70
Files for the baseline physics.
Definition: ADTypes.hpp:10
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.
Definition: size_field.cpp:619
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.
Definition: size_field.cpp:143
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, .
Definition: size_field.cpp:507
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...
Definition: size_field.cpp:99
Field element class.
Definition: field.h:452
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.
Definition: size_field.cpp:38
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...
Definition: size_field.cpp:307
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.
Definition: size_field.cpp:535
Size Field Static Class.
Definition: size_field.h:64
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 ...
Definition: size_field.cpp:419
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)
Definition: size_field.cpp:577