libMesh
adaptivity_ex3.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2019 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 
20 // <h1>Adaptivity Example 3 - Laplace Equation in the L-Shaped Domain</h1>
21 // \author Benjamin S. Kirk
22 // \date 2003
23 //
24 // This example solves the Laplace equation on the classic "L-shaped"
25 // domain with adaptive mesh refinement. In this case, the exact
26 // solution is u(r,\theta) = r^{2/3} * \sin ( (2/3) * \theta), but
27 // the standard Kelly error indicator is used to estimate the error.
28 // The initial mesh contains three QUAD9 elements which represent the
29 // standard quadrants I, II, and III of the domain [-1,1]x[-1,1],
30 // i.e.
31 // Element 0: [-1,0]x[ 0,1]
32 // Element 1: [ 0,1]x[ 0,1]
33 // Element 2: [-1,0]x[-1,0]
34 // The mesh is provided in the standard libMesh ASCII format file
35 // named "lshaped.xda". In addition, an input file named "adaptivity_ex3.in"
36 // is provided which allows the user to set several parameters for
37 // the solution so that the problem can be re-run without a
38 // re-compile. The solution technique employed is to have a
39 // refinement loop with a linear solve inside followed by a
40 // refinement of the grid and projection of the solution to the new grid
41 // In the final loop iteration, there is no additional
42 // refinement after the solve. In the input file "adaptivity_ex3.in",
43 // the variable "max_r_steps" controls the number of refinement steps,
44 // "max_r_level" controls the maximum element refinement level, and
45 // "refine_percentage" / "coarsen_percentage" determine the number of
46 // elements which will be refined / coarsened at each step.
47 
48 // LibMesh include files.
49 #include "libmesh/mesh.h"
50 #include "libmesh/equation_systems.h"
51 #include "libmesh/linear_implicit_system.h"
52 #include "libmesh/exodusII_io.h"
53 #include "libmesh/tecplot_io.h"
54 #include "libmesh/fe.h"
55 #include "libmesh/quadrature_gauss.h"
56 #include "libmesh/dense_matrix.h"
57 #include "libmesh/dense_vector.h"
58 #include "libmesh/sparse_matrix.h"
59 #include "libmesh/mesh_refinement.h"
60 #include "libmesh/error_vector.h"
61 #include "libmesh/discontinuity_measure.h"
62 #include "libmesh/exact_error_estimator.h"
63 #include "libmesh/kelly_error_estimator.h"
64 #include "libmesh/patch_recovery_error_estimator.h"
65 #include "libmesh/uniform_refinement_estimator.h"
66 #include "libmesh/hp_coarsentest.h"
67 #include "libmesh/hp_singular.h"
68 #include "libmesh/sibling_coupling.h"
69 #include "libmesh/mesh_generation.h"
70 #include "libmesh/mesh_modification.h"
71 #include "libmesh/perf_log.h"
72 #include "libmesh/getpot.h"
73 #include "libmesh/exact_solution.h"
74 #include "libmesh/dof_map.h"
75 #include "libmesh/numeric_vector.h"
76 #include "libmesh/elem.h"
77 #include "libmesh/string_to_enum.h"
78 #include "libmesh/enum_solver_package.h"
79 #include "libmesh/dirichlet_boundaries.h"
80 #include "libmesh/wrapped_function.h"
81 
82 // Bring in everything from the libMesh namespace
83 using namespace libMesh;
84 
85 // Function prototype. This is the function that will assemble
86 // the linear system for our Laplace problem. Note that the
87 // function will take the EquationSystems object and the
88 // name of the system we are assembling as input. From the
89 // EquationSystems object we have access to the Mesh and
90 // other objects we might need.
92  const std::string & system_name);
93 
94 
95 // Prototype for calculation of the exact solution. Useful
96 // for setting boundary conditions.
97 Number exact_solution(const Point & p,
98  const Parameters &, // EquationSystem parameters, not needed
99  const std::string &, // sys_name, not needed
100  const std::string &); // unk_name, not needed);
101 
102 // Prototype for calculation of the gradient of the exact solution.
104  const Parameters &, // EquationSystems parameters, not needed
105  const std::string &, // sys_name, not needed
106  const std::string &); // unk_name, not needed);
107 
108 
109 // These are non-const because the input file may change it,
110 // It is global because our exact_* functions use it.
111 
112 // Set the dimensionality of the mesh
113 unsigned int dim = 2;
114 
115 // Set the number of variables to solve for
116 unsigned int n_vars = 1;
117 
118 // Choose whether or not to use the singular solution
119 bool singularity = true;
120 
121 
122 int main(int argc, char ** argv)
123 {
124  // Initialize libMesh.
125  LibMeshInit init (argc, argv);
126 
127  // This example requires a linear solver package.
128  libmesh_example_requires(libMesh::default_solver_package() != INVALID_SOLVER_PACKAGE,
129  "--enable-petsc, --enable-trilinos, or --enable-eigen");
130 
131  // Single precision is inadequate for p refinement
132  libmesh_example_requires(sizeof(Real) > 4, "--disable-singleprecision");
133 
134  // Skip adaptive examples on a non-adaptive libMesh build
135 #ifndef LIBMESH_ENABLE_AMR
136  libmesh_example_requires(false, "--enable-amr");
137 #else
138 
139  // Parse the input file
140  GetPot input_file("adaptivity_ex3.in");
141 
142  // But allow the command line to override it.
143  input_file.parse_command_line(argc, argv);
144 
145  // Read in parameters from the input file
146  const unsigned int max_r_steps = input_file("max_r_steps", 3);
147  const unsigned int max_r_level = input_file("max_r_level", 3);
148  const Real refine_percentage = input_file("refine_percentage", 0.5);
149  const Real coarsen_percentage = input_file("coarsen_percentage", 0.5);
150  const unsigned int uniform_refine = input_file("uniform_refine",0);
151  const std::string refine_type = input_file("refinement_type", "h");
152  const std::string approx_type = input_file("approx_type", "LAGRANGE");
153  const unsigned int approx_order = input_file("approx_order", 1);
154  n_vars = input_file("n_vars", n_vars);
155  const std::string element_type = input_file("element_type", "tensor");
156  const int extra_error_quadrature = input_file("extra_error_quadrature", 0);
157  const int max_linear_iterations = input_file("max_linear_iterations", 5000);
158 
159 #ifdef LIBMESH_HAVE_EXODUS_API
160  const bool output_intermediate = input_file("output_intermediate", false);
161 #endif
162 
163  // If libmesh is configured without second derivative support, we
164  // can't run this example with Hermite elements and will therefore
165  // fail gracefully.
166 #if !defined(LIBMESH_ENABLE_SECOND_DERIVATIVES)
167  libmesh_example_requires(approx_type != "HERMITE", "--enable-second");
168 #endif
169 
170  dim = input_file("dimension", 2);
171  const std::string indicator_type = input_file("indicator_type", "kelly");
172  singularity = input_file("singularity", true);
173 
174  // Skip higher-dimensional examples on a lower-dimensional libMesh build
175  libmesh_example_requires(dim <= LIBMESH_DIM, "2D/3D support");
176 
177  // Output file for plotting the error as a function of
178  // the number of degrees of freedom.
179  std::string approx_name = "";
180  if (element_type == "tensor")
181  approx_name += "bi";
182  if (approx_order == 1)
183  approx_name += "linear";
184  else if (approx_order == 2)
185  approx_name += "quadratic";
186  else if (approx_order == 3)
187  approx_name += "cubic";
188  else if (approx_order == 4)
189  approx_name += "quartic";
190 
191  std::string output_file = approx_name;
192  output_file += "_";
193  output_file += refine_type;
194  if (uniform_refine == 0)
195  output_file += "_adaptive.m";
196  else
197  output_file += "_uniform.m";
198 
199  std::ofstream out (output_file.c_str());
200  out << "% dofs L2-error H1-error" << std::endl;
201  out << "e = [" << std::endl;
202 
203  // Create a mesh, with dimension to be overridden later, on the
204  // default MPI communicator.
205  Mesh mesh(init.comm());
206 
207  // Create an equation systems object.
208  EquationSystems equation_systems (mesh);
209 
210  // Declare the system we will solve, named Laplace
211  LinearImplicitSystem & system =
212  equation_systems.add_system<LinearImplicitSystem> ("Laplace");
213 
214  // If we're doing HP refinement, then we'll need to be able to
215  // evaluate data on elements' siblings in HPCoarsenTest, which means
216  // we should instruct our system's DofMap to distribute that data.
217  // Create and add (and keep around! the DofMap will only be holding
218  // a pointer to it!) a SiblingCoupling functor to provide that
219  // instruction.
220  SiblingCoupling sibling_coupling;
221  if (refine_type == "hp")
222  system.get_dof_map().add_algebraic_ghosting_functor(sibling_coupling);
223 
224  // Read in the mesh
225  if (dim == 1)
227  else if (dim == 2)
228  mesh.read("lshaped.xda");
229  else
230  mesh.read("lshaped3D.xda");
231 
232  // Use triangles if the config file says so
233  if (element_type == "simplex")
235 
236  // We used first order elements to describe the geometry,
237  // but we may need second order elements to hold the degrees
238  // of freedom
239  if (approx_order > 1 || refine_type != "h")
241 
242  // Mesh Refinement object
243  MeshRefinement mesh_refinement(mesh);
244  mesh_refinement.refine_fraction() = refine_percentage;
245  mesh_refinement.coarsen_fraction() = coarsen_percentage;
246  mesh_refinement.max_h_level() = max_r_level;
247 
248  // Adds the variable "u" to "Laplace", using
249  // the finite element type and order specified
250  // in the config file
251  unsigned int u_var =
252  system.add_variable("u", static_cast<Order>(approx_order),
253  Utility::string_to_enum<FEFamily>(approx_type));
254 
255  std::vector<unsigned int> all_vars(1, u_var);
256 
257  // For benchmarking purposes, add more variables if requested.
258  for (unsigned int var_num=1; var_num < n_vars; ++var_num)
259  {
260  std::ostringstream var_name;
261  var_name << "u" << var_num;
262  unsigned int next_var =
263  system.add_variable(var_name.str(),
264  static_cast<Order>(approx_order),
265  Utility::string_to_enum<FEFamily>(approx_type));
266  all_vars.push_back(next_var);
267  }
268 
269  // Give the system a pointer to the matrix assembly
270  // function.
272 
273  // Add Dirichlet boundary conditions
274  std::set<boundary_id_type> all_bdys { 0 };
275 
276  WrappedFunction<Number> exact_val(system, exact_solution);
278  DirichletBoundary exact_bc(all_bdys, all_vars, exact_val, exact_grad);
279  system.get_dof_map().add_dirichlet_boundary(exact_bc);
280 
281  // Initialize the data structures for the equation system.
282  equation_systems.init();
283 
284  // Set linear solver max iterations
285  equation_systems.parameters.set<unsigned int>("linear solver maximum iterations")
286  = max_linear_iterations;
287 
288  // Linear solver tolerance.
289  equation_systems.parameters.set<Real>("linear solver tolerance") =
290  std::pow(TOLERANCE, 2.5);
291 
292  // Prints information about the system to the screen.
293  equation_systems.print_info();
294 
295  // Construct ExactSolution object and attach solution functions
296  ExactSolution exact_sol(equation_systems);
299 
300  // Use higher quadrature order for more accurate error results
301  exact_sol.extra_quadrature_order(extra_error_quadrature);
302 
303  // Compute the initial error
304  exact_sol.compute_error("Laplace", "u");
305 
306  // Print out the error values
307  libMesh::out << "Initial L2-Error is: "
308  << exact_sol.l2_error("Laplace", "u")
309  << std::endl;
310  libMesh::out << "Initial H1-Error is: "
311  << exact_sol.h1_error("Laplace", "u")
312  << std::endl;
313 
314  // A refinement loop.
315  for (unsigned int r_step=0; r_step<max_r_steps; r_step++)
316  {
317  libMesh::out << "Beginning Solve " << r_step << std::endl;
318 
319  // Solve the system "Laplace", just like example 2.
320  system.solve();
321 
322  libMesh::out << "System has: "
323  << equation_systems.n_active_dofs()
324  << " degrees of freedom."
325  << std::endl;
326 
327  libMesh::out << "Linear solver converged at step: "
328  << system.n_linear_iterations()
329  << ", final residual: "
330  << system.final_linear_residual()
331  << std::endl;
332 
333 #ifdef LIBMESH_HAVE_EXODUS_API
334  // After solving the system write the solution
335  // to a ExodusII-formatted plot file.
336  if (output_intermediate)
337  {
338  std::ostringstream outfile;
339  outfile << "lshaped_" << r_step << ".e";
340  ExodusII_IO (mesh).write_equation_systems (outfile.str(),
341  equation_systems);
342  }
343 #endif // #ifdef LIBMESH_HAVE_EXODUS_API
344 
345  // Compute the error.
346  exact_sol.compute_error("Laplace", "u");
347 
348  // Print out the error values
349  libMesh::out << "L2-Error is: "
350  << exact_sol.l2_error("Laplace", "u")
351  << std::endl;
352  libMesh::out << "H1-Error is: "
353  << exact_sol.h1_error("Laplace", "u")
354  << std::endl;
355 
356  // Compute any discontinuity. There should be none.
357  {
359  ErrorVector disc_error;
360  disc.estimate_error(system, disc_error);
361 
362  Real mean_disc_error = disc_error.mean();
363 
364  libMesh::out << "Mean discontinuity error = " << mean_disc_error << std::endl;
365 
366  // FIXME - this test fails when solving with Eigen?
367 #ifdef LIBMESH_ENABLE_PETSC
368  libmesh_assert_less (mean_disc_error, 1e-14);
369 #endif
370  }
371 
372  // Print to output file
373  out << equation_systems.n_active_dofs() << " "
374  << exact_sol.l2_error("Laplace", "u") << " "
375  << exact_sol.h1_error("Laplace", "u") << std::endl;
376 
377  // Possibly refine the mesh
378  if (r_step+1 != max_r_steps)
379  {
380  libMesh::out << " Refining the mesh..." << std::endl;
381 
382  if (uniform_refine == 0)
383  {
384 
385  // The ErrorVector is a particular StatisticsVector
386  // for computing error information on a finite element mesh.
387  ErrorVector error;
388 
389  if (indicator_type == "exact")
390  {
391  // The ErrorEstimator class interrogates a
392  // finite element solution and assigns to each
393  // element a positive error value.
394  // This value is used for deciding which elements to
395  // refine and which to coarsen.
396  // For these simple test problems, we can use
397  // numerical quadrature of the exact error between
398  // the approximate and analytic solutions.
399  // However, for real problems, we would need an error
400  // indicator which only relies on the approximate
401  // solution.
402  ExactErrorEstimator error_estimator;
403 
404  error_estimator.attach_exact_value(exact_solution);
405  error_estimator.attach_exact_deriv(exact_derivative);
406 
407  // We optimize in H1 norm, the default
408  // error_estimator.error_norm = H1;
409 
410  // Compute the error for each active element using
411  // the provided indicator. Note in general you
412  // will need to provide an error estimator
413  // specifically designed for your application.
414  error_estimator.estimate_error (system, error);
415  }
416  else if (indicator_type == "patch")
417  {
418  // The patch recovery estimator should give a
419  // good estimate of the solution interpolation
420  // error.
421  PatchRecoveryErrorEstimator error_estimator;
422 
423  error_estimator.estimate_error (system, error);
424  }
425  else if (indicator_type == "uniform")
426  {
427  // Error indication based on uniform refinement
428  // is reliable, but very expensive.
429  UniformRefinementEstimator error_estimator;
430 
431  error_estimator.estimate_error (system, error);
432  }
433  else
434  {
435  libmesh_assert_equal_to (indicator_type, "kelly");
436 
437  // The Kelly error estimator is based on
438  // an error bound for the Poisson problem
439  // on linear elements, but is useful for
440  // driving adaptive refinement in many problems
441  KellyErrorEstimator error_estimator;
442 
443  // This is a subclass of JumpErrorEstimator, based on
444  // measuring discontinuities across sides between
445  // elements, and we can tell it to use a cheaper
446  // "unweighted" quadrature rule when numerically
447  // integrating those discontinuities.
448  error_estimator.use_unweighted_quadrature_rules = true;
449 
450  error_estimator.estimate_error (system, error);
451  }
452 
453  // Write out the error distribution
454  std::ostringstream ss;
455  ss << r_step;
456 #ifdef LIBMESH_HAVE_EXODUS_API
457 # ifdef LIBMESH_HAVE_NEMESIS_API
458  std::string error_output = "error_" + ss.str() + ".n";
459 # else
460  std::string error_output = "error_" + ss.str() + ".e";
461 # endif
462 #else
463  std::string error_output = "error_" + ss.str() + ".gmv";
464 #endif
465  error.plot_error(error_output, mesh);
466 
467  // This takes the error in error and decides which elements
468  // will be coarsened or refined. Any element within 20% of the
469  // maximum error on any element will be refined, and any
470  // element within 10% of the minimum error on any element might
471  // be coarsened. Note that the elements flagged for refinement
472  // will be refined, but those flagged for coarsening _might_ be
473  // coarsened.
474  mesh_refinement.flag_elements_by_error_fraction (error);
475 
476  // If we are doing adaptive p refinement, we want
477  // elements flagged for that instead.
478  if (refine_type == "p")
479  mesh_refinement.switch_h_to_p_refinement();
480  // If we are doing "matched hp" refinement, we
481  // flag elements for both h and p
482  else if (refine_type == "matchedhp")
483  mesh_refinement.add_p_to_h_refinement();
484  // If we are doing hp refinement, we
485  // try switching some elements from h to p
486  else if (refine_type == "hp")
487  {
488  HPCoarsenTest hpselector;
489  hpselector.select_refinement(system);
490  }
491  // If we are doing "singular hp" refinement, we
492  // try switching most elements from h to p
493  else if (refine_type == "singularhp")
494  {
495  // This only differs from p refinement for
496  // the singular problem
498  HPSingularity hpselector;
499  // Our only singular point is at the origin
500  hpselector.singular_points.push_back(Point());
501  hpselector.select_refinement(system);
502  }
503  else if (refine_type != "h")
504  libmesh_error_msg("Unknown refinement_type = " << refine_type);
505 
506  // This call actually refines and coarsens the flagged
507  // elements.
508  mesh_refinement.refine_and_coarsen_elements();
509  }
510 
511  else if (uniform_refine == 1)
512  {
513  if (refine_type == "h" || refine_type == "hp" ||
514  refine_type == "matchedhp")
515  mesh_refinement.uniformly_refine(1);
516  if (refine_type == "p" || refine_type == "hp" ||
517  refine_type == "matchedhp")
518  mesh_refinement.uniformly_p_refine(1);
519  }
520 
521  // This call reinitializes the EquationSystems object for
522  // the newly refined mesh. One of the steps in the
523  // reinitialization is projecting the solution,
524  // old_solution, etc... vectors from the old mesh to
525  // the current one.
526  equation_systems.reinit ();
527  }
528  }
529 
530 #ifdef LIBMESH_HAVE_EXODUS_API
531  // Write out the solution
532  // After solving the system write the solution
533  // to a ExodusII-formatted plot file.
534  ExodusII_IO (mesh).write_equation_systems ("lshaped.e",
535  equation_systems);
536 #endif // #ifdef LIBMESH_HAVE_EXODUS_API
537 
538  // Close up the output file.
539  out << "];" << std::endl;
540  out << "hold on" << std::endl;
541  out << "plot(e(:,1), e(:,2), 'bo-');" << std::endl;
542  out << "plot(e(:,1), e(:,3), 'ro-');" << std::endl;
543  // out << "set(gca,'XScale', 'Log');" << std::endl;
544  // out << "set(gca,'YScale', 'Log');" << std::endl;
545  out << "xlabel('dofs');" << std::endl;
546  out << "title('" << approx_name << " elements');" << std::endl;
547  out << "legend('L2-error', 'H1-error');" << std::endl;
548  // out << "disp('L2-error linear fit');" << std::endl;
549  // out << "polyfit(log10(e(:,1)), log10(e(:,2)), 1)" << std::endl;
550  // out << "disp('H1-error linear fit');" << std::endl;
551  // out << "polyfit(log10(e(:,1)), log10(e(:,3)), 1)" << std::endl;
552 #endif // #ifndef LIBMESH_ENABLE_AMR
553 
554  // All done.
555  return 0;
556 }
557 
558 
559 
560 
561 // We now define the exact solution, being careful
562 // to obtain an angle from atan2 in the correct
563 // quadrant.
565  const Parameters &, // parameters, not needed
566  const std::string &, // sys_name, not needed
567  const std::string &) // unk_name, not needed
568 {
569  const Real x = p(0);
570  const Real y = (dim > 1) ? p(1) : 0.;
571 
572  if (singularity)
573  {
574  // The exact solution to the singular problem,
575  // u_exact = r^(2/3)*sin(2*theta/3).
576  Real theta = atan2(y, x);
577 
578  // Make sure 0 <= theta <= 2*pi
579  if (theta < 0)
580  theta += 2. * libMesh::pi;
581 
582  // Make the 3D solution similar
583  const Real z = (dim > 2) ? p(2) : 0;
584 
585  return pow(x*x + y*y, 1./3.)*sin(2./3.*theta) + z;
586  }
587  else
588  {
589  // The exact solution to a nonsingular problem,
590  // good for testing ideal convergence rates
591  const Real z = (dim > 2) ? p(2) : 0;
592 
593  return cos(x) * exp(y) * (1. - z);
594  }
595 }
596 
597 
598 
599 
600 
601 // We now define the gradient of the exact solution, again being careful
602 // to obtain an angle from atan2 in the correct
603 // quadrant.
605  const Parameters &, // parameters, not needed
606  const std::string &, // sys_name, not needed
607  const std::string &) // unk_name, not needed
608 {
609  // Gradient value to be returned.
610  Gradient gradu;
611 
612  // x and y coordinates in space
613  const Real x = p(0);
614  const Real y = dim > 1 ? p(1) : 0.;
615 
616  if (singularity)
617  {
618  // We can't compute the gradient at x=0, it is not defined.
619  libmesh_assert_not_equal_to (x, 0.);
620 
621  // For convenience...
622  const Real tt = 2./3.;
623  const Real ot = 1./3.;
624 
625  // The value of the radius, squared
626  const Real r2 = x*x + y*y;
627 
628  // The boundary value, given by the exact solution,
629  // u_exact = r^(2/3)*sin(2*theta/3).
630  Real theta = atan2(y, x);
631 
632  // Make sure 0 <= theta <= 2*pi
633  if (theta < 0)
634  theta += 2. * libMesh::pi;
635 
636  // du/dx
637  gradu(0) = tt*x*pow(r2,-tt)*sin(tt*theta) - pow(r2,ot)*cos(tt*theta)*tt/(1.+y*y/x/x)*y/x/x;
638 
639  // du/dy
640  if (dim > 1)
641  gradu(1) = tt*y*pow(r2,-tt)*sin(tt*theta) + pow(r2,ot)*cos(tt*theta)*tt/(1.+y*y/x/x)*1./x;
642 
643  if (dim > 2)
644  gradu(2) = 1.;
645  }
646  else
647  {
648  const Real z = (dim > 2) ? p(2) : 0;
649 
650  gradu(0) = -sin(x) * exp(y) * (1. - z);
651  if (dim > 1)
652  gradu(1) = cos(x) * exp(y) * (1. - z);
653  if (dim > 2)
654  gradu(2) = -cos(x) * exp(y);
655  }
656 
657  return gradu;
658 }
659 
660 
661 
662 
663 
664 
665 // We now define the matrix assembly function for the
666 // Laplace system. We need to first compute element
667 // matrices and right-hand sides, and then take into
668 // account the boundary conditions, which will be handled
669 // via a penalty method.
671  const std::string & system_name)
672 {
673  // Ignore unused parameter warnings when !LIBMESH_ENABLE_AMR.
674  libmesh_ignore(es, system_name);
675 
676 #ifdef LIBMESH_ENABLE_AMR
677  // It is a good idea to make sure we are assembling
678  // the proper system.
679  libmesh_assert_equal_to (system_name, "Laplace");
680 
681  // Declare a performance log. Give it a descriptive
682  // string to identify what part of the code we are
683  // logging, since there may be many PerfLogs in an
684  // application.
685  PerfLog perf_log ("Matrix Assembly", false);
686 
687  // Get a constant reference to the mesh object.
688  const MeshBase & mesh = es.get_mesh();
689 
690  // The dimension that we are running
691  const unsigned int mesh_dim = mesh.mesh_dimension();
692 
693  // Get a reference to the LinearImplicitSystem we are solving
694  LinearImplicitSystem & system = es.get_system<LinearImplicitSystem>("Laplace");
695 
696  // A reference to the DofMap object for this system. The DofMap
697  // object handles the index translation from node and element numbers
698  // to degree of freedom numbers. We will talk more about the DofMap
699  // in future examples.
700  const DofMap & dof_map = system.get_dof_map();
701 
702  // Get a constant reference to the Finite Element type
703  // for the first (and only) variable type in the system.
704  FEType fe_type = dof_map.variable_type(0);
705 
706  // Build a Finite Element object of the specified type. Since the
707  // FEBase::build() member dynamically creates memory we will
708  // store the object as a std::unique_ptr<FEBase>. This can be thought
709  // of as a pointer that will clean up after itself.
710  std::unique_ptr<FEBase> fe (FEBase::build(mesh_dim, fe_type));
711  std::unique_ptr<FEBase> fe_face (FEBase::build(mesh_dim, fe_type));
712 
713  // Quadrature rules for numerical integration.
714  std::unique_ptr<QBase> qrule(fe_type.default_quadrature_rule(mesh_dim));
715  std::unique_ptr<QBase> qface(fe_type.default_quadrature_rule(mesh_dim-1));
716 
717  // Tell the finite element object to use our quadrature rule.
718  fe->attach_quadrature_rule (qrule.get());
719  fe_face->attach_quadrature_rule (qface.get());
720 
721  // Here we define some references to cell-specific data that
722  // will be used to assemble the linear system.
723  // We begin with the element Jacobian * quadrature weight at each
724  // integration point.
725  const std::vector<Real> & JxW = fe->get_JxW();
726 
727  // The physical XY locations of the quadrature points on the element.
728  // These might be useful for evaluating spatially varying material
729  // properties or forcing functions at the quadrature points.
730  const std::vector<Point> & q_point = fe->get_xyz();
731 
732  // The element shape functions evaluated at the quadrature points.
733  const std::vector<std::vector<Real>> & phi = fe->get_phi();
734 
735  // The element shape function gradients evaluated at the quadrature
736  // points.
737  const std::vector<std::vector<RealGradient>> & dphi = fe->get_dphi();
738 
739  // Define data structures to contain the element matrix
740  // and right-hand-side vector contribution. Following
741  // basic finite element terminology we will denote these
742  // "Ke" and "Fe". More detail is in example 3.
745 
746  // This vector will hold the degree of freedom indices for
747  // the element. These define where in the global system
748  // the element degrees of freedom get mapped.
749  std::vector<dof_id_type> dof_indices;
750 
751  // Now we will loop over all the elements in the mesh. We will
752  // compute the element matrix and right-hand-side contribution. See
753  // example 3 for a discussion of the element iterators. Here we use
754  // the const_active_local_elem_iterator to indicate we only want
755  // to loop over elements that are assigned to the local processor
756  // which are "active" in the sense of AMR. This allows each
757  // processor to compute its components of the global matrix for
758  // active elements while ignoring parent elements which have been
759  // refined.
760  for (const auto & elem : mesh.active_local_element_ptr_range())
761  {
762  // Start logging the shape function initialization.
763  // This is done through a simple function call with
764  // the name of the event to log.
765  perf_log.push("elem init");
766 
767  // Get the degree of freedom indices for the
768  // current element. These define where in the global
769  // matrix and right-hand-side this element will
770  // contribute to.
771  dof_map.dof_indices (elem, dof_indices);
772 
773  // Compute the element-specific data for the current
774  // element. This involves computing the location of the
775  // quadrature points (q_point) and the shape functions
776  // (phi, dphi) for the current element.
777  fe->reinit (elem);
778 
779  const unsigned int n_dofs =
780  cast_int<unsigned int>(dof_indices.size());
781 
782  // Zero the element matrix and right-hand side before
783  // summing them. We use the resize member here because
784  // the number of degrees of freedom might have changed from
785  // the last element. Note that this will be the case if the
786  // element type is different (i.e. the last element was a
787  // triangle, now we are on a quadrilateral).
788  Ke.resize (n_dofs, n_dofs);
789 
790  Fe.resize (n_dofs);
791 
792  // Stop logging the shape function initialization.
793  // If you forget to stop logging an event the PerfLog
794  // object will probably catch the error and abort.
795  perf_log.pop("elem init");
796 
797  // Now we will build the element matrix. This involves
798  // a quadruple loop to integrate the test functions (i) against
799  // the trial functions (j) for each variable (v) at each
800  // quadrature point (qp).
801  //
802  // Now start logging the element matrix computation
803  perf_log.push ("Ke");
804 
805  std::vector<dof_id_type> dof_indices_u;
806  dof_map.dof_indices (elem, dof_indices_u, 0);
807  const unsigned int n_u_dofs = dof_indices_u.size();
808  libmesh_assert_equal_to (n_u_dofs, phi.size());
809  libmesh_assert_equal_to (n_u_dofs, dphi.size());
810 
811  for (unsigned int v=0; v != n_vars; ++v)
812  {
813  DenseSubMatrix<Number> Kuu(Ke);
814  Kuu.reposition (v*n_u_dofs, v*n_u_dofs, n_u_dofs, n_u_dofs);
815 
816  for (unsigned int qp=0; qp<qrule->n_points(); qp++)
817  for (unsigned int i=0; i != n_u_dofs; i++)
818  for (unsigned int j=0; j != n_u_dofs; j++)
819  Kuu(i,j) += JxW[qp]*(dphi[i][qp]*dphi[j][qp]);
820 
821  // We need a forcing function to make the 1D case interesting
822  if (mesh_dim == 1)
823  {
824  DenseSubVector<Number> Fu(Fe);
825  Fu.reposition (v*n_u_dofs, n_u_dofs);
826 
827  for (unsigned int qp=0; qp<qrule->n_points(); qp++)
828  {
829  Real x = q_point[qp](0);
830  Real f = singularity ? sqrt(3.)/9.*pow(-x, -4./3.) :
831  cos(x);
832  for (unsigned int i=0; i != n_u_dofs; ++i)
833  Fu(i) += JxW[qp]*phi[i][qp]*f;
834  }
835  }
836  }
837 
838  // Stop logging the matrix computation
839  perf_log.pop ("Ke");
840 
841  // The element matrix and right-hand-side are now built
842  // for this element. Add them to the global matrix and
843  // right-hand-side vector. The SparseMatrix::add_matrix()
844  // and NumericVector::add_vector() members do this for us.
845  // Start logging the insertion of the local (element)
846  // matrix and vector into the global matrix and vector
847  LOG_SCOPE_WITH("matrix insertion", "", perf_log);
848 
849  // Use heterogenously here to handle Dirichlet as well as AMR
850  // constraints.
851  dof_map.heterogenously_constrain_element_matrix_and_vector(Ke, Fe, dof_indices);
852  system.matrix->add_matrix (Ke, dof_indices);
853  system.rhs->add_vector (Fe, dof_indices);
854  }
855 
856  // That's it. We don't need to do anything else to the
857  // PerfLog. When it goes out of scope (at this function return)
858  // it will print its log to the screen. Pretty easy, huh?
859 #endif // #ifdef LIBMESH_ENABLE_AMR
860 }
libMesh::ErrorVector::plot_error
void plot_error(const std::string &filename, const MeshBase &mesh) const
Plots a data file, of a type determined by looking at the file extension in filename,...
Definition: error_vector.C:210
libMesh::DofMap::add_algebraic_ghosting_functor
void add_algebraic_ghosting_functor(GhostingFunctor &evaluable_functor, bool to_mesh=true)
Adds a functor which can specify algebraic ghosting requirements for use with distributed vectors.
Definition: dof_map.C:1862
libMesh::ExactSolution
This class handles the computation of the L2 and/or H1 error for the Systems in the EquationSystems o...
Definition: exact_solution.h:73
libMesh::Number
Real Number
Definition: libmesh_common.h:195
exact_grad
Gradient exact_grad(const Point &, const Parameters &, const std::string &, const std::string &)
Definition: mysystems.h:25
libMesh::pi
const Real pi
.
Definition: libmesh.h:237
libMesh::MeshRefinement::refine_and_coarsen_elements
bool refine_and_coarsen_elements()
Refines and coarsens user-requested elements.
Definition: mesh_refinement.C:476
libMesh::Mesh
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
Definition: mesh.h:50
main
int main(int argc, char **argv)
Definition: adaptivity_ex3.C:122
libMesh::EquationSystems::get_mesh
const MeshBase & get_mesh() const
Definition: equation_systems.h:637
libMesh::MeshBase::read
virtual void read(const std::string &name, void *mesh_data=nullptr, bool skip_renumber_nodes_and_elements=false, bool skip_find_neighbors=false)=0
Interfaces for reading/writing a mesh to/from a file.
libMesh::ExplicitSystem::rhs
NumericVector< Number > * rhs
The system matrix.
Definition: explicit_system.h:114
libMesh::PatchRecoveryErrorEstimator
This class implements the Patch Recovery error indicator.
Definition: patch_recovery_error_estimator.h:55
n_vars
unsigned int n_vars
Definition: adaptivity_ex3.C:116
libMesh::MeshRefinement::uniformly_p_refine
void uniformly_p_refine(unsigned int n=1)
Uniformly p refines the mesh n times.
Definition: mesh_refinement.C:1649
libMesh::MeshBase::all_second_order
virtual void all_second_order(const bool full_ordered=true)=0
Converts a (conforming, non-refined) mesh with linear elements into a mesh with second-order elements...
libMesh::DofMap::add_dirichlet_boundary
void add_dirichlet_boundary(const DirichletBoundary &dirichlet_boundary)
Adds a copy of the specified Dirichlet boundary to the system.
Definition: dof_map_constraints.C:4390
libMesh::JumpErrorEstimator::estimate_error
virtual void estimate_error(const System &system, ErrorVector &error_per_cell, const NumericVector< Number > *solution_vector=nullptr, bool estimate_parent_error=false) override
This function uses the derived class's jump error estimate formula to estimate the error on each cell...
Definition: jump_error_estimator.C:53
libMesh::MeshBase::active_local_element_ptr_range
virtual SimpleRange< element_iterator > active_local_element_ptr_range()=0
libMesh::DenseSubMatrix
Defines a dense submatrix for use in Finite Element-type computations.
Definition: dense_submatrix.h:45
libMesh
The libMesh namespace provides an interface to certain functionality in the library.
Definition: factoryfunction.C:55
libMesh::ExactErrorEstimator::attach_exact_deriv
void attach_exact_deriv(unsigned int sys_num, FunctionBase< Gradient > *g)
Clone and attach an arbitrary functor which computes the exact gradient of the system sys_num solutio...
Definition: exact_error_estimator.C:126
libMesh::HPSingularity
This class uses a user-provided list of singularity locations to choose between h refining and p elev...
Definition: hp_singular.h:49
libMesh::EquationSystems::get_system
const T_sys & get_system(const std::string &name) const
Definition: equation_systems.h:757
libMesh::ExactSolution::h1_error
Real h1_error(const std::string &sys_name, const std::string &unknown_name)
Definition: exact_solution.C:393
std::sqrt
MetaPhysicL::DualNumber< T, D > sqrt(const MetaPhysicL::DualNumber< T, D > &in)
libMesh::TOLERANCE
static const Real TOLERANCE
Definition: libmesh_common.h:128
libMesh::DenseMatrix< Number >
exact_derivative
Gradient exact_derivative(const Point &p, const Parameters &, const std::string &, const std::string &)
Definition: adaptivity_ex3.C:604
libMesh::LinearImplicitSystem::solve
virtual void solve() override
Assembles & solves the linear system A*x=b.
Definition: linear_implicit_system.C:108
libMesh::default_solver_package
SolverPackage default_solver_package()
Definition: libmesh.C:993
mesh
MeshBase & mesh
Definition: mesh_communication.C:1257
libMesh::MeshBase::mesh_dimension
unsigned int mesh_dimension() const
Definition: mesh_base.C:135
libMesh::ExodusII_IO
The ExodusII_IO class implements reading meshes in the ExodusII file format from Sandia National Labs...
Definition: exodusII_io.h:51
dim
unsigned int dim
Definition: adaptivity_ex3.C:113
libMesh::DenseMatrix::resize
void resize(const unsigned int new_m, const unsigned int new_n)
Resize the matrix.
Definition: dense_matrix.h:822
libMesh::VectorValue
This class defines a vector in LIBMESH_DIM dimensional Real or Complex space.
Definition: exact_solution.h:54
libMesh::TriangleWrapper::init
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
libMesh::MeshRefinement
Implements (adaptive) mesh refinement algorithms for a MeshBase.
Definition: mesh_refinement.h:61
libMesh::ExactErrorEstimator::estimate_error
virtual void estimate_error(const System &system, ErrorVector &error_per_cell, const NumericVector< Number > *solution_vector=nullptr, bool estimate_parent_error=false) override
This function uses the exact solution function to estimate the error on each cell.
Definition: exact_error_estimator.C:188
libMesh::libmesh_assert
libmesh_assert(ctx)
libMesh::KellyErrorEstimator
This class implements the Kelly error indicator which is based on the flux jumps between elements.
Definition: kelly_error_estimator.h:59
libMesh::ExactSolution::attach_exact_value
void attach_exact_value(unsigned int sys_num, FunctionBase< Number > *f)
Clone and attach an arbitrary functor which computes the exact value of the system sys_num solution a...
Definition: exact_solution.C:123
libMesh::System::attach_assemble_function
void attach_assemble_function(void fptr(EquationSystems &es, const std::string &name))
Register a user function to use in assembling the system matrix and RHS.
Definition: system.C:1755
libMesh::NumericVector::add_vector
virtual void add_vector(const T *v, const std::vector< numeric_index_type > &dof_indices)
Computes , where v is a pointer and each dof_indices[i] specifies where to add value v[i].
Definition: numeric_vector.C:363
libMesh::MeshBase
This is the MeshBase class.
Definition: mesh_base.h:78
libMesh::ExactSolution::extra_quadrature_order
void extra_quadrature_order(const int extraorder)
Increases or decreases the order of the quadrature rule used for numerical integration.
Definition: exact_solution.h:190
libMesh::WrappedFunction
Wrap a libMesh-style function pointer into a FunctionBase object.
Definition: wrapped_function.h:51
libMesh::PerfLog::pop
void pop(const char *label, const char *header="")
Pop the event label off the stack, resuming any lower event.
Definition: perf_log.C:163
libMesh::INVALID_SOLVER_PACKAGE
Definition: enum_solver_package.h:43
libMesh::libmesh_ignore
void libmesh_ignore(const Args &...)
Definition: libmesh_common.h:526
libMesh::FEGenericBase::build
static std::unique_ptr< FEGenericBase > build(const unsigned int dim, const FEType &type)
Builds a specific finite element type.
libMesh::System::add_variable
unsigned int add_variable(const std::string &var, const FEType &type, const std::set< subdomain_id_type > *const active_subdomains=nullptr)
Adds the variable var to the list of variables for this system.
Definition: system.C:1069
libMesh::MeshTools::Generation::build_line
void build_line(UnstructuredMesh &mesh, const unsigned int nx, const Real xmin=0., const Real xmax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
A specialized build_cube() for 1D meshes.
Definition: mesh_generation.C:1480
libMesh::PerfLog
The PerfLog class allows monitoring of specific events.
Definition: perf_log.h:125
libMesh::Point
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:38
singularity
bool singularity
Definition: adaptivity_ex3.C:119
libMesh::ImplicitSystem::matrix
SparseMatrix< Number > * matrix
The system matrix.
Definition: implicit_system.h:393
libMesh::ErrorVector
The ErrorVector is a specialization of the StatisticsVector for error data computed on a finite eleme...
Definition: error_vector.h:50
std::pow
double pow(double a, int b)
Definition: libmesh_augment_std_namespace.h:58
libMesh::PatchRecoveryErrorEstimator::estimate_error
virtual void estimate_error(const System &system, ErrorVector &error_per_cell, const NumericVector< Number > *solution_vector=nullptr, bool estimate_parent_error=false) override
This function uses the Patch Recovery error estimate to estimate the error on each cell.
Definition: patch_recovery_error_estimator.C:153
libMesh::FEType::default_quadrature_rule
std::unique_ptr< QBase > default_quadrature_rule(const unsigned int dim, const int extraorder=0) const
Definition: fe_type.C:31
libMesh::LibMeshInit
The LibMeshInit class, when constructed, initializes the dependent libraries (e.g.
Definition: libmesh.h:83
libMesh::SiblingCoupling
This class adds coupling (for use in send_list construction) between active elements and all descenda...
Definition: sibling_coupling.h:39
libMesh::UniformRefinementEstimator
This class implements a `‘brute force’' error estimator which integrates differences between the curr...
Definition: uniform_refinement_estimator.h:45
libMesh::MeshRefinement::switch_h_to_p_refinement
void switch_h_to_p_refinement()
Takes a mesh whose elements are flagged for h refinement and coarsening, and switches those flags to ...
Definition: mesh_refinement_flagging.C:655
libMesh::ExactSolution::l2_error
Real l2_error(const std::string &sys_name, const std::string &unknown_name)
Definition: exact_solution.C:333
libMesh::MeshRefinement::max_h_level
unsigned int & max_h_level()
The max_h_level is the greatest refinement level an element should reach.
Definition: mesh_refinement.h:891
libMesh::ExactSolution::compute_error
void compute_error(const std::string &sys_name, const std::string &unknown_name)
Computes and stores the error in the solution value e = u-u_h, the gradient grad(e) = grad(u) - grad(...
Definition: exact_solution.C:227
libMesh::EquationSystems
This is the EquationSystems class.
Definition: equation_systems.h:74
libMesh::LinearImplicitSystem::n_linear_iterations
unsigned int n_linear_iterations() const
Definition: linear_implicit_system.h:164
libMesh::DenseSubVector< Number >
libMesh::MeshOutput::write_equation_systems
virtual void write_equation_systems(const std::string &, const EquationSystems &, const std::set< std::string > *system_names=nullptr)
This method implements writing a mesh with data to a specified file where the data is taken from the ...
Definition: mesh_output.C:31
libMesh::DenseVector::resize
void resize(const unsigned int n)
Resize the vector.
Definition: dense_vector.h:355
libMesh::MeshTools::Modification::all_tri
void all_tri(MeshBase &mesh)
Converts the 2D quadrilateral elements of a Mesh into triangular elements.
Definition: mesh_modification.C:280
libMesh::MeshRefinement::coarsen_fraction
Real & coarsen_fraction()
The coarsen_fraction sets either a desired target or a desired maximum number of elements to flag for...
Definition: mesh_refinement.h:885
libMesh::SparseMatrix::add_matrix
virtual void add_matrix(const DenseMatrix< T > &dm, const std::vector< numeric_index_type > &rows, const std::vector< numeric_index_type > &cols)=0
Add the full matrix dm to the SparseMatrix.
libMesh::MeshRefinement::refine_fraction
Real & refine_fraction()
The refine_fraction sets either a desired target or a desired maximum number of elements to flag for ...
Definition: mesh_refinement.h:879
libMesh::FEType
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Definition: fe_type.h:178
libMesh::DofMap
This class handles the numbering of degrees of freedom on a mesh.
Definition: dof_map.h:176
libMesh::ErrorVector::mean
virtual Real mean() const override
Definition: error_vector.C:69
libMesh::ExactErrorEstimator::attach_exact_value
void attach_exact_value(unsigned int sys_num, FunctionBase< Number > *f)
Clone and attach an arbitrary functor which computes the exact value of the system sys_num solution a...
Definition: exact_error_estimator.C:91
libMesh::DirichletBoundary
This class allows one to associate Dirichlet boundary values with a given set of mesh boundary ids an...
Definition: dirichlet_boundaries.h:88
libMesh::ExactErrorEstimator
This class implements an "error estimator" based on the difference between the approximate and exact ...
Definition: exact_error_estimator.h:57
exact_solution
Number exact_solution(const Point &p, const Parameters &, const std::string &, const std::string &)
Definition: adaptivity_ex3.C:564
libMesh::JumpErrorEstimator::use_unweighted_quadrature_rules
bool use_unweighted_quadrature_rules
This boolean flag allows you to use "unweighted" quadrature rules (sized to exactly integrate unweigh...
Definition: jump_error_estimator.h:113
libMesh::HPSingularity::singular_points
std::list< Point > singular_points
This list, to be filled by the user, should include all singular points in the solution.
Definition: hp_singular.h:83
libMesh::PerfLog::push
void push(const char *label, const char *header="")
Push the event label onto the stack, pausing any active event.
Definition: perf_log.C:133
libMesh::DenseSubVector::reposition
void reposition(const unsigned int ioff, const unsigned int n)
Changes the location of the subvector in the parent vector.
Definition: dense_subvector.h:174
libMesh::LinearImplicitSystem::final_linear_residual
Real final_linear_residual() const
Definition: linear_implicit_system.h:169
libMesh::System::get_dof_map
const DofMap & get_dof_map() const
Definition: system.h:2099
libMesh::DiscontinuityMeasure
This class measures discontinuities between elements for debugging purposes.
Definition: discontinuity_measure.h:49
libMesh::HPCoarsenTest
This class uses the error estimate given by different types of derefinement (h coarsening or p reduct...
Definition: hp_coarsentest.h:67
libMesh::Real
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Definition: libmesh_common.h:121
libMesh::LinearImplicitSystem
Manages consistently variables, degrees of freedom, coefficient vectors, matrices and linear solvers ...
Definition: linear_implicit_system.h:55
assemble_laplace
void assemble_laplace(EquationSystems &es, const std::string &system_name)
Definition: adaptivity_ex3.C:670
libMesh::MeshRefinement::flag_elements_by_error_fraction
void flag_elements_by_error_fraction(const ErrorVector &error_per_cell, const Real refine_fraction=0.3, const Real coarsen_fraction=0.0, const unsigned int max_level=libMesh::invalid_uint)
Flags elements for coarsening and refinement based on the computed error passed in error_per_cell.
Definition: mesh_refinement_flagging.C:44
libMesh::HPSingularity::select_refinement
virtual void select_refinement(System &system)
This pure virtual function must be redefined in derived classes to take a mesh flagged for h refineme...
Definition: hp_singular.C:36
libMesh::HPCoarsenTest::select_refinement
virtual void select_refinement(System &system) override
This pure virtual function must be redefined in derived classes to take a mesh flagged for h refineme...
Definition: hp_coarsentest.C:137
libMesh::UniformRefinementEstimator::estimate_error
virtual void estimate_error(const System &system, ErrorVector &error_per_cell, const NumericVector< Number > *solution_vector=nullptr, bool estimate_parent_error=false) override
This function does uniform refinements and a solve to get an improved solution on each cell,...
Definition: uniform_refinement_estimator.C:69
libMesh::out
OStreamProxy out
libMesh::ExactSolution::attach_exact_deriv
void attach_exact_deriv(unsigned int sys_num, FunctionBase< Gradient > *g)
Clone and attach an arbitrary functor which computes the exact gradient of the system sys_num solutio...
Definition: exact_solution.C:164
libMesh::MeshRefinement::uniformly_refine
void uniformly_refine(unsigned int n=1)
Uniformly refines the mesh n times.
Definition: mesh_refinement.C:1678
libMesh::Parameters
This class provides the ability to map between arbitrary, user-defined strings and several data types...
Definition: parameters.h:59
libMesh::DenseVector< Number >
libMesh::DenseSubMatrix::reposition
void reposition(const unsigned int ioff, const unsigned int joff, const unsigned int new_m, const unsigned int new_n)
Changes the location of the submatrix in the parent matrix.
Definition: dense_submatrix.h:173
libMesh::MeshRefinement::add_p_to_h_refinement
void add_p_to_h_refinement()
Takes a mesh whose elements are flagged for h refinement and coarsening, and adds flags to request p ...
Definition: mesh_refinement_flagging.C:674