libMesh
exact_solution.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 // Local includes
19 #include "libmesh/dof_map.h"
20 #include "libmesh/elem.h"
21 #include "libmesh/exact_solution.h"
22 #include "libmesh/equation_systems.h"
23 #include "libmesh/fe_base.h"
24 #include "libmesh/function_base.h"
25 #include "libmesh/mesh_base.h"
26 #include "libmesh/mesh_function.h"
27 #include "libmesh/numeric_vector.h"
28 #include "libmesh/parallel.h"
29 #include "libmesh/quadrature.h"
30 #include "libmesh/wrapped_function.h"
31 #include "libmesh/fe_interface.h"
32 #include "libmesh/raw_accessor.h"
33 #include "libmesh/tensor_tools.h"
34 #include "libmesh/enum_norm_type.h"
35 #include "libmesh/utility.h"
36 #include "libmesh/auto_ptr.h" // libmesh_make_unique
37 
38 namespace libMesh
39 {
40 
42  _equation_systems(es),
43  _equation_systems_fine(nullptr),
44  _extra_order(0)
45 {
46  // Initialize the _errors data structure which holds all
47  // the eventual values of the error.
49  {
50  // Reference to the system
51  const System & system = _equation_systems.get_system(sys);
52 
53  // The name of the system
54  const std::string & sys_name = system.name();
55 
56  // The SystemErrorMap to be inserted
58 
59  for (auto var : IntRange<unsigned int>(0, system.n_vars()))
60  {
61  // The name of this variable
62  const std::string & var_name = system.variable_name(var);
63  sem[var_name] = std::vector<Real>(5, 0.);
64  }
65 
66  _errors[sys_name] = sem;
67  }
68 }
69 
70 
73 
74 
75 void ExactSolution::
76 set_excluded_subdomains(const std::set<subdomain_id_type> & excluded)
77 {
78  _excluded_subdomains = excluded;
79 }
80 
82 {
83  libmesh_assert(es_fine);
84  _equation_systems_fine = es_fine;
85 
86  // If we're using a fine grid solution, we're not using exact values
87  _exact_values.clear();
88  _exact_derivs.clear();
89  _exact_hessians.clear();
90 }
91 
92 
93 void ExactSolution::attach_exact_value (ValueFunctionPointer fptr)
94 {
96 
97  // Clear out any previous _exact_values entries, then add a new
98  // entry for each system.
99  _exact_values.clear();
100 
101  for (auto sys : IntRange<unsigned int>(0, _equation_systems.n_systems()))
102  {
103  const System & system = _equation_systems.get_system(sys);
104  _exact_values.emplace_back(libmesh_make_unique<WrappedFunction<Number>>(system, fptr, &_equation_systems.parameters));
105  }
106 
107  // If we're using exact values, we're not using a fine grid solution
108  _equation_systems_fine = nullptr;
109 }
110 
111 
113 {
114  // Automatically delete any previous _exact_values entries, then add a new
115  // entry for each system.
116  _exact_values.clear();
117 
118  for (auto ptr : f)
119  _exact_values.emplace_back(ptr ? ptr->clone() : nullptr);
120 }
121 
122 
123 void ExactSolution::attach_exact_value (unsigned int sys_num,
125 {
126  if (_exact_values.size() <= sys_num)
127  _exact_values.resize(sys_num+1);
128 
129  if (f)
130  _exact_values[sys_num] = f->clone();
131 }
132 
133 
134 void ExactSolution::attach_exact_deriv (GradientFunctionPointer gptr)
135 {
137 
138  // Clear out any previous _exact_derivs entries, then add a new
139  // entry for each system.
140  _exact_derivs.clear();
141 
142  for (auto sys : IntRange<unsigned int>(0, _equation_systems.n_systems()))
143  {
144  const System & system = _equation_systems.get_system(sys);
145  _exact_derivs.emplace_back(libmesh_make_unique<WrappedFunction<Gradient>>(system, gptr, &_equation_systems.parameters));
146  }
147 
148  // If we're using exact values, we're not using a fine grid solution
149  _equation_systems_fine = nullptr;
150 }
151 
152 
154 {
155  // Automatically delete any previous _exact_derivs entries, then add a new
156  // entry for each system.
157  _exact_derivs.clear();
158 
159  for (auto ptr : g)
160  _exact_derivs.emplace_back(ptr ? ptr->clone() : nullptr);
161 }
162 
163 
164 void ExactSolution::attach_exact_deriv (unsigned int sys_num,
166 {
167  if (_exact_derivs.size() <= sys_num)
168  _exact_derivs.resize(sys_num+1);
169 
170  if (g)
171  _exact_derivs[sys_num] = g->clone();
172 }
173 
174 
175 void ExactSolution::attach_exact_hessian (HessianFunctionPointer hptr)
176 {
177  libmesh_assert(hptr);
178 
179  // Clear out any previous _exact_hessians entries, then add a new
180  // entry for each system.
181  _exact_hessians.clear();
182 
183  for (auto sys : IntRange<unsigned int>(0, _equation_systems.n_systems()))
184  {
185  const System & system = _equation_systems.get_system(sys);
186  _exact_hessians.emplace_back(libmesh_make_unique<WrappedFunction<Tensor>>(system, hptr, &_equation_systems.parameters));
187  }
188 
189  // If we're using exact values, we're not using a fine grid solution
190  _equation_systems_fine = nullptr;
191 }
192 
193 
195 {
196  // Automatically delete any previous _exact_hessians entries, then add a new
197  // entry for each system.
198  _exact_hessians.clear();
199 
200  for (auto ptr : h)
201  _exact_hessians.emplace_back(ptr ? ptr->clone() : nullptr);
202 }
203 
204 
205 void ExactSolution::attach_exact_hessian (unsigned int sys_num,
207 {
208  if (_exact_hessians.size() <= sys_num)
209  _exact_hessians.resize(sys_num+1);
210 
211  if (h)
212  _exact_hessians[sys_num] = h->clone();
213 }
214 
215 
216 std::vector<Real> & ExactSolution::_check_inputs(const std::string & sys_name,
217  const std::string & unknown_name)
218 {
219  // Return a reference to the proper error entry, or throw an error
220  // if it doesn't exist.
221  auto & system_error_map = libmesh_map_find(_errors, sys_name);
222  return libmesh_map_find(system_error_map, unknown_name);
223 }
224 
225 
226 
227 void ExactSolution::compute_error(const std::string & sys_name,
228  const std::string & unknown_name)
229 {
230  // Check the inputs for validity, and get a reference
231  // to the proper location to store the error
232  std::vector<Real> & error_vals = this->_check_inputs(sys_name,
233  unknown_name);
234 
236  const System & sys = _equation_systems.get_system<System>( sys_name );
237 
238  libmesh_assert( sys.has_variable( unknown_name ) );
239  switch( FEInterface::field_type(sys.variable_type( unknown_name )) )
240  {
241  case TYPE_SCALAR:
242  {
243  this->_compute_error<Real>(sys_name,
244  unknown_name,
245  error_vals);
246  break;
247  }
248  case TYPE_VECTOR:
249  {
250  this->_compute_error<RealGradient>(sys_name,
251  unknown_name,
252  error_vals);
253  break;
254  }
255  default:
256  libmesh_error_msg("Invalid variable type!");
257  }
258 }
259 
260 
261 
262 
263 
264 Real ExactSolution::error_norm(const std::string & sys_name,
265  const std::string & unknown_name,
266  const FEMNormType & norm)
267 {
268  // Check the inputs for validity, and get a reference
269  // to the proper location to store the error
270  std::vector<Real> & error_vals = this->_check_inputs(sys_name,
271  unknown_name);
272 
274  libmesh_assert(_equation_systems.get_system(sys_name).has_variable( unknown_name ));
275  const FEType & fe_type = _equation_systems.get_system(sys_name).variable_type(unknown_name);
276 
277  switch (norm)
278  {
279  case L2:
280  return std::sqrt(error_vals[0]);
281  case H1:
282  return std::sqrt(error_vals[0] + error_vals[1]);
283  case H2:
284  return std::sqrt(error_vals[0] + error_vals[1] + error_vals[2]);
285  case HCURL:
286  {
287  if (FEInterface::field_type(fe_type) == TYPE_SCALAR)
288  libmesh_error_msg("Cannot compute HCurl error norm of scalar-valued variables!");
289  else
290  return std::sqrt(error_vals[0] + error_vals[5]);
291  }
292  case HDIV:
293  {
294  if (FEInterface::field_type(fe_type) == TYPE_SCALAR)
295  libmesh_error_msg("Cannot compute HDiv error norm of scalar-valued variables!");
296  else
297  return std::sqrt(error_vals[0] + error_vals[6]);
298  }
299  case H1_SEMINORM:
300  return std::sqrt(error_vals[1]);
301  case H2_SEMINORM:
302  return std::sqrt(error_vals[2]);
303  case HCURL_SEMINORM:
304  {
305  if (FEInterface::field_type(fe_type) == TYPE_SCALAR)
306  libmesh_error_msg("Cannot compute HCurl error seminorm of scalar-valued variables!");
307  else
308  return std::sqrt(error_vals[5]);
309  }
310  case HDIV_SEMINORM:
311  {
312  if (FEInterface::field_type(fe_type) == TYPE_SCALAR)
313  libmesh_error_msg("Cannot compute HDiv error seminorm of scalar-valued variables!");
314  else
315  return std::sqrt(error_vals[6]);
316  }
317  case L1:
318  return error_vals[3];
319  case L_INF:
320  return error_vals[4];
321 
322  default:
323  libmesh_error_msg("Currently only Sobolev norms/seminorms are supported!");
324  }
325 }
326 
327 
328 
329 
330 
331 
332 
333 Real ExactSolution::l2_error(const std::string & sys_name,
334  const std::string & unknown_name)
335 {
336 
337  // Check the inputs for validity, and get a reference
338  // to the proper location to store the error
339  std::vector<Real> & error_vals = this->_check_inputs(sys_name,
340  unknown_name);
341 
342  // Return the square root of the first component of the
343  // computed error.
344  return std::sqrt(error_vals[0]);
345 }
346 
347 
348 
349 
350 
351 
352 
353 Real ExactSolution::l1_error(const std::string & sys_name,
354  const std::string & unknown_name)
355 {
356 
357  // Check the inputs for validity, and get a reference
358  // to the proper location to store the error
359  std::vector<Real> & error_vals = this->_check_inputs(sys_name,
360  unknown_name);
361 
362  // Return the square root of the first component of the
363  // computed error.
364  return error_vals[3];
365 }
366 
367 
368 
369 
370 
371 
372 
373 Real ExactSolution::l_inf_error(const std::string & sys_name,
374  const std::string & unknown_name)
375 {
376 
377  // Check the inputs for validity, and get a reference
378  // to the proper location to store the error
379  std::vector<Real> & error_vals = this->_check_inputs(sys_name,
380  unknown_name);
381 
382  // Return the square root of the first component of the
383  // computed error.
384  return error_vals[4];
385 }
386 
387 
388 
389 
390 
391 
392 
393 Real ExactSolution::h1_error(const std::string & sys_name,
394  const std::string & unknown_name)
395 {
396  // If the user has supplied no exact derivative function, we
397  // just integrate the H1 norm of the solution; i.e. its
398  // difference from an "exact solution" of zero.
399 
400  // Check the inputs for validity, and get a reference
401  // to the proper location to store the error
402  std::vector<Real> & error_vals = this->_check_inputs(sys_name,
403  unknown_name);
404 
405  // Return the square root of the sum of the computed errors.
406  return std::sqrt(error_vals[0] + error_vals[1]);
407 }
408 
409 
410 Real ExactSolution::hcurl_error(const std::string & sys_name,
411  const std::string & unknown_name)
412 {
413  return this->error_norm(sys_name,unknown_name,HCURL);
414 }
415 
416 
417 Real ExactSolution::hdiv_error(const std::string & sys_name,
418  const std::string & unknown_name)
419 {
420  return this->error_norm(sys_name,unknown_name,HDIV);
421 }
422 
423 
424 
425 Real ExactSolution::h2_error(const std::string & sys_name,
426  const std::string & unknown_name)
427 {
428  // If the user has supplied no exact derivative functions, we
429  // just integrate the H2 norm of the solution; i.e. its
430  // difference from an "exact solution" of zero.
431 
432  // Check the inputs for validity, and get a reference
433  // to the proper location to store the error
434  std::vector<Real> & error_vals = this->_check_inputs(sys_name,
435  unknown_name);
436 
437  // Return the square root of the sum of the computed errors.
438  return std::sqrt(error_vals[0] + error_vals[1] + error_vals[2]);
439 }
440 
441 
442 
443 
444 
445 
446 
447 template<typename OutputShape>
448 void ExactSolution::_compute_error(const std::string & sys_name,
449  const std::string & unknown_name,
450  std::vector<Real> & error_vals)
451 {
452  // Make sure we aren't "overconfigured"
454 
455  // We need a communicator.
456  const Parallel::Communicator & communicator(_equation_systems.comm());
457 
458  // This function must be run on all processors at once
459  libmesh_parallel_only(communicator);
460 
461  // Get a reference to the system whose error is being computed.
462  // If we have a fine grid, however, we'll integrate on that instead
463  // for more accuracy.
464  const System & computed_system = _equation_systems_fine ?
466  _equation_systems.get_system (sys_name);
467 
468  const Real time = _equation_systems.get_system(sys_name).time;
469 
470  const unsigned int sys_num = computed_system.number();
471  const unsigned int var = computed_system.variable_number(unknown_name);
472  const unsigned int var_component =
473  computed_system.variable_scalar_number(var, 0);
474 
475  // Prepare a global solution and a MeshFunction of the coarse system if we need one
476  std::unique_ptr<MeshFunction> coarse_values;
477  std::unique_ptr<NumericVector<Number>> comparison_soln = NumericVector<Number>::build(_equation_systems.comm());
479  {
480  const System & comparison_system
481  = _equation_systems.get_system(sys_name);
482 
483  std::vector<Number> global_soln;
484  comparison_system.update_global_solution(global_soln);
485  comparison_soln->init(comparison_system.solution->size(), true, SERIAL);
486  (*comparison_soln) = global_soln;
487 
488  coarse_values = libmesh_make_unique<MeshFunction>
490  *comparison_soln,
491  comparison_system.get_dof_map(),
492  comparison_system.variable_number(unknown_name));
493  coarse_values->init();
494  }
495 
496  // Initialize any functors we're going to use
497  for (auto & ev : _exact_values)
498  if (ev)
499  ev->init();
500 
501  for (auto & ed : _exact_derivs)
502  if (ed)
503  ed->init();
504 
505  for (auto & eh : _exact_hessians)
506  if (eh)
507  eh->init();
508 
509  // Get a reference to the dofmap and mesh for that system
510  const DofMap & computed_dof_map = computed_system.get_dof_map();
511 
512  const MeshBase & mesh = computed_system.get_mesh();
513 
514  // Grab which element dimensions are present in the mesh
515  const std::set<unsigned char> & elem_dims = mesh.elem_dimensions();
516 
517  // Zero the error before summation
518  // 0 - sum of square of function error (L2)
519  // 1 - sum of square of gradient error (H1 semi)
520  // 2 - sum of square of Hessian error (H2 semi)
521  // 3 - sum of sqrt(square of function error) (L1)
522  // 4 - max of sqrt(square of function error) (Linfty)
523  // 5 - sum of square of curl error (HCurl semi)
524  // 6 - sum of square of div error (HDiv semi)
525  error_vals = std::vector<Real>(7, 0.);
526 
527  // Construct Quadrature rule based on default quadrature order
528  const FEType & fe_type = computed_dof_map.variable_type(var);
529 
530  unsigned int n_vec_dim = FEInterface::n_vec_dim( mesh, fe_type );
531 
532  // FIXME: MeshFunction needs to be updated to support vector-valued
533  // elements before we can use a reference solution.
534  if ((n_vec_dim > 1) && _equation_systems_fine)
535  {
536  libMesh::err << "Error calculation using reference solution not yet\n"
537  << "supported for vector-valued elements."
538  << std::endl;
539  libmesh_not_implemented();
540  }
541 
542 
543  // Allow space for dims 0-3, even if we don't use them all
544  std::vector<std::unique_ptr<FEGenericBase<OutputShape>>> fe_ptrs(4);
545  std::vector<std::unique_ptr<QBase>> q_rules(4);
546 
547  // Prepare finite elements for each dimension present in the mesh
548  for (const auto dim : elem_dims)
549  {
550  // Build a quadrature rule.
551  q_rules[dim] = fe_type.default_quadrature_rule (dim, _extra_order);
552 
553  // Construct finite element object
554  fe_ptrs[dim] = FEGenericBase<OutputShape>::build(dim, fe_type);
555 
556  // Attach quadrature rule to FE object
557  fe_ptrs[dim]->attach_quadrature_rule (q_rules[dim].get());
558  }
559 
560  // The global degree of freedom indices associated
561  // with the local degrees of freedom.
562  std::vector<dof_id_type> dof_indices;
563 
564 
565  //
566  // Begin the loop over the elements
567  //
568  // TODO: this ought to be threaded (and using subordinate
569  // MeshFunction objects in each thread rather than a single
570  // master)
571  for (const auto & elem : mesh.active_local_element_ptr_range())
572  {
573  // Skip this element if it is in a subdomain excluded by the user.
574  const subdomain_id_type elem_subid = elem->subdomain_id();
575  if (_excluded_subdomains.count(elem_subid))
576  continue;
577 
578  // The spatial dimension of the current Elem. FEs and other data
579  // are indexed on dim.
580  const unsigned int dim = elem->dim();
581 
582  // If the variable is not active on this subdomain, don't bother
583  if (!computed_system.variable(var).active_on_subdomain(elem_subid))
584  continue;
585 
586  /* If the variable is active, then we're going to restrict the
587  MeshFunction evaluations to the current element subdomain.
588  This is for cases such as mixed dimension meshes where we want
589  to restrict the calculation to one particular domain. */
590  std::set<subdomain_id_type> subdomain_id;
591  subdomain_id.insert(elem_subid);
592 
593  FEGenericBase<OutputShape> * fe = fe_ptrs[dim].get();
594  QBase * qrule = q_rules[dim].get();
595  libmesh_assert(fe);
596  libmesh_assert(qrule);
597 
598  // The Jacobian*weight at the quadrature points.
599  const std::vector<Real> & JxW = fe->get_JxW();
600 
601  // The value of the shape functions at the quadrature points
602  // i.e. phi(i) = phi_values[i][qp]
603  const std::vector<std::vector<OutputShape>> & phi_values = fe->get_phi();
604 
605  // The value of the shape function gradients at the quadrature points
606  const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputGradient>> &
607  dphi_values = fe->get_dphi();
608 
609  // The value of the shape function curls at the quadrature points
610  // Only computed for vector-valued elements
611  const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputShape>> * curl_values = nullptr;
612 
613  // The value of the shape function divergences at the quadrature points
614  // Only computed for vector-valued elements
615  const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputDivergence>> * div_values = nullptr;
616 
617  if (FEInterface::field_type(fe_type) == TYPE_VECTOR)
618  {
619  curl_values = &fe->get_curl_phi();
620  div_values = &fe->get_div_phi();
621  }
622 
623 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
624  // The value of the shape function second derivatives at the quadrature points
625  const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputTensor>> &
626  d2phi_values = fe->get_d2phi();
627 #endif
628 
629  // The XYZ locations (in physical space) of the quadrature points
630  const std::vector<Point> & q_point = fe->get_xyz();
631 
632  // reinitialize the element-specific data
633  // for the current element
634  fe->reinit (elem);
635 
636  // Get the local to global degree of freedom maps
637  computed_dof_map.dof_indices (elem, dof_indices, var);
638 
639  // The number of quadrature points
640  const unsigned int n_qp = qrule->n_points();
641 
642  // The number of shape functions
643  const unsigned int n_sf =
644  cast_int<unsigned int>(dof_indices.size());
645 
646  //
647  // Begin the loop over the Quadrature points.
648  //
649  for (unsigned int qp=0; qp<n_qp; qp++)
650  {
651  // Real u_h = 0.;
652  // RealGradient grad_u_h;
653 
655 
657 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
659 #endif
660  typename FEGenericBase<OutputShape>::OutputNumber curl_u_h(0.0);
662 
663  // Compute solution values at the current
664  // quadrature point. This requires a sum
665  // over all the shape functions evaluated
666  // at the quadrature point.
667  for (unsigned int i=0; i<n_sf; i++)
668  {
669  // Values from current solution.
670  u_h += phi_values[i][qp]*computed_system.current_solution (dof_indices[i]);
671  grad_u_h += dphi_values[i][qp]*computed_system.current_solution (dof_indices[i]);
672 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
673  grad2_u_h += d2phi_values[i][qp]*computed_system.current_solution (dof_indices[i]);
674 #endif
675  if (FEInterface::field_type(fe_type) == TYPE_VECTOR)
676  {
677  curl_u_h += (*curl_values)[i][qp]*computed_system.current_solution (dof_indices[i]);
678  div_u_h += (*div_values)[i][qp]*computed_system.current_solution (dof_indices[i]);
679  }
680  }
681 
682  // Compute the value of the error at this quadrature point
683  typename FEGenericBase<OutputShape>::OutputNumber exact_val(0);
684  RawAccessor<typename FEGenericBase<OutputShape>::OutputNumber> exact_val_accessor( exact_val, dim );
685  if (_exact_values.size() > sys_num && _exact_values[sys_num])
686  {
687  for (unsigned int c = 0; c < n_vec_dim; c++)
688  exact_val_accessor(c) =
689  _exact_values[sys_num]->
690  component(var_component+c, q_point[qp], time);
691  }
692  else if (_equation_systems_fine)
693  {
694  // FIXME: Needs to be updated for vector-valued elements
695  DenseVector<Number> output(1);
696  (*coarse_values)(q_point[qp],time,output,&subdomain_id);
697  exact_val = output(0);
698  }
699  const typename FEGenericBase<OutputShape>::OutputNumber val_error = u_h - exact_val;
700 
701  // Add the squares of the error to each contribution
702  Real error_sq = TensorTools::norm_sq(val_error);
703  error_vals[0] += JxW[qp]*error_sq;
704 
705  Real norm = sqrt(error_sq);
706  error_vals[3] += JxW[qp]*norm;
707 
708  if (error_vals[4]<norm) { error_vals[4] = norm; }
709 
710  // Compute the value of the error in the gradient at this
711  // quadrature point
714  if (_exact_derivs.size() > sys_num && _exact_derivs[sys_num])
715  {
716  for (unsigned int c = 0; c < n_vec_dim; c++)
717  for (unsigned int d = 0; d < LIBMESH_DIM; d++)
718  exact_grad_accessor(d + c*LIBMESH_DIM) =
719  _exact_derivs[sys_num]->
720  component(var_component+c, q_point[qp], time)(d);
721  }
722  else if (_equation_systems_fine)
723  {
724  // FIXME: Needs to be updated for vector-valued elements
725  std::vector<Gradient> output(1);
726  coarse_values->gradient(q_point[qp],time,output,&subdomain_id);
727  exact_grad = output[0];
728  }
729 
730  const typename FEGenericBase<OutputShape>::OutputNumberGradient grad_error = grad_u_h - exact_grad;
731 
732  error_vals[1] += JxW[qp]*grad_error.norm_sq();
733 
734 
735  if (FEInterface::field_type(fe_type) == TYPE_VECTOR)
736  {
737  // Compute the value of the error in the curl at this
738  // quadrature point
739  typename FEGenericBase<OutputShape>::OutputNumber exact_curl(0.0);
740  if (_exact_derivs.size() > sys_num && _exact_derivs[sys_num])
741  {
742  exact_curl = TensorTools::curl_from_grad( exact_grad );
743  }
744  else if (_equation_systems_fine)
745  {
746  // FIXME: Need to implement curl for MeshFunction and support reference
747  // solution for vector-valued elements
748  }
749 
750  const typename FEGenericBase<OutputShape>::OutputNumber curl_error = curl_u_h - exact_curl;
751 
752  error_vals[5] += JxW[qp]*TensorTools::norm_sq(curl_error);
753 
754  // Compute the value of the error in the divergence at this
755  // quadrature point
757  if (_exact_derivs.size() > sys_num && _exact_derivs[sys_num])
758  {
759  exact_div = TensorTools::div_from_grad( exact_grad );
760  }
761  else if (_equation_systems_fine)
762  {
763  // FIXME: Need to implement div for MeshFunction and support reference
764  // solution for vector-valued elements
765  }
766 
767  const typename FEGenericBase<OutputShape>::OutputNumberDivergence div_error = div_u_h - exact_div;
768 
769  error_vals[6] += JxW[qp]*TensorTools::norm_sq(div_error);
770  }
771 
772 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
773  // Compute the value of the error in the hessian at this
774  // quadrature point
777  if (_exact_hessians.size() > sys_num && _exact_hessians[sys_num])
778  {
779  //FIXME: This needs to be implemented to support rank 3 tensors
780  // which can't happen until type_n_tensor is fully implemented
781  // and a RawAccessor<TypeNTensor> is fully implemented
782  if (FEInterface::field_type(fe_type) == TYPE_VECTOR)
783  libmesh_not_implemented();
784 
785  for (unsigned int c = 0; c < n_vec_dim; c++)
786  for (unsigned int d = 0; d < dim; d++)
787  for (unsigned int e =0; e < dim; e++)
788  exact_hess_accessor(d + e*dim + c*dim*dim) =
789  _exact_hessians[sys_num]->
790  component(var_component+c, q_point[qp], time)(d,e);
791  }
792  else if (_equation_systems_fine)
793  {
794  // FIXME: Needs to be updated for vector-valued elements
795  std::vector<Tensor> output(1);
796  coarse_values->hessian(q_point[qp],time,output,&subdomain_id);
797  exact_hess = output[0];
798  }
799 
800  const typename FEGenericBase<OutputShape>::OutputNumberTensor grad2_error = grad2_u_h - exact_hess;
801 
802  // FIXME: PB: Is this what we want for rank 3 tensors?
803  error_vals[2] += JxW[qp]*grad2_error.norm_sq();
804 #endif
805 
806  } // end qp loop
807  } // end element loop
808 
809  // Add up the error values on all processors, except for the L-infty
810  // norm, for which the maximum is computed.
811  Real l_infty_norm = error_vals[4];
812  communicator.max(l_infty_norm);
813  communicator.sum(error_vals);
814  error_vals[4] = l_infty_norm;
815 }
816 
817 // Explicit instantiations of templated member functions
818 template void ExactSolution::_compute_error<Real>(const std::string &, const std::string &, std::vector<Real> &);
819 template void ExactSolution::_compute_error<RealGradient>(const std::string &, const std::string &, std::vector<Real> &);
820 
821 } // namespace libMesh
libMesh::QBase
The QBase class provides the basic functionality from which various quadrature rules can be derived.
Definition: quadrature.h:61
libMesh::System
Manages consistently variables, degrees of freedom, and coefficient vectors.
Definition: system.h:100
libMesh::ExactSolution::_extra_order
int _extra_order
Extra order to use for quadrature rule.
Definition: exact_solution.h:370
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::RawAccessor
This class provides single index access to FieldType (i.e.
Definition: raw_accessor.h:93
libMesh::System::n_vars
unsigned int n_vars() const
Definition: system.h:2155
exact_grad
Gradient exact_grad(const Point &, const Parameters &, const std::string &, const std::string &)
Definition: mysystems.h:25
libMesh::ExactSolution::ExactSolution
ExactSolution(const EquationSystems &es)
Constructor.
Definition: exact_solution.C:41
libMesh::FunctionBase< Number >
libMesh::ExactSolution::attach_exact_derivs
void attach_exact_derivs(const std::vector< FunctionBase< Gradient > * > &g)
Clone and attach arbitrary functors which compute the exact gradients of the EquationSystems' solutio...
Definition: exact_solution.C:153
libMesh::TensorTools::curl_from_grad
Number curl_from_grad(const VectorValue< Number > &)
Definition: tensor_tools.C:28
libMesh::ExactSolution::_excluded_subdomains
std::set< subdomain_id_type > _excluded_subdomains
Elements in a subdomain from this set are skipped during the error computation.
Definition: exact_solution.h:376
libMesh::FEAbstract::get_xyz
const std::vector< Point > & get_xyz() const
Definition: fe_abstract.h:237
libMesh::FEInterface::n_vec_dim
static unsigned int n_vec_dim(const MeshBase &mesh, const FEType &fe_type)
Definition: fe_interface.C:1701
libMesh::ExactSolution::set_excluded_subdomains
void set_excluded_subdomains(const std::set< subdomain_id_type > &excluded)
The user can indicate that elements in certain subdomains should be excluded from the error calculati...
Definition: exact_solution.C:76
libMesh::DofMap::dof_indices
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
Fills the vector di with the global degree of freedom indices for the element.
Definition: dof_map.C:1967
libMesh::L_INF
Definition: enum_norm_type.h:42
libMesh::ExactSolution::l1_error
Real l1_error(const std::string &sys_name, const std::string &unknown_name)
Definition: exact_solution.C:353
libMesh::FunctionBase::clone
virtual std::unique_ptr< FunctionBase< Output > > clone() const =0
libMesh::TYPE_SCALAR
Definition: enum_fe_family.h:93
libMesh::QBase::n_points
unsigned int n_points() const
Definition: quadrature.h:126
libMesh::System::variable_name
const std::string & variable_name(const unsigned int i) const
Definition: system.h:2203
libMesh::SERIAL
Definition: enum_parallel_type.h:35
libMesh
The libMesh namespace provides an interface to certain functionality in the library.
Definition: factoryfunction.C:55
libMesh::ExactSolution::_exact_hessians
std::vector< std::unique_ptr< FunctionBase< Tensor > > > _exact_hessians
User-provided functors which compute the exact hessians of the solution for each system.
Definition: exact_solution.h:335
libMesh::L1
Definition: enum_norm_type.h:41
libMesh::FEGenericBase
This class forms the foundation from which generic finite elements may be derived.
Definition: exact_error_estimator.h:39
libMesh::H1_SEMINORM
Definition: enum_norm_type.h:43
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
libMesh::FEAbstract::get_JxW
const std::vector< Real > & get_JxW() const
Definition: fe_abstract.h:244
std::sqrt
MetaPhysicL::DualNumber< T, D > sqrt(const MetaPhysicL::DualNumber< T, D > &in)
libMesh::ParallelObject::comm
const Parallel::Communicator & comm() const
Definition: parallel_object.h:94
libMesh::FEGenericBase::get_d2phi
const std::vector< std::vector< OutputTensor > > & get_d2phi() const
Definition: fe_base.h:288
libMesh::System::number
unsigned int number() const
Definition: system.h:2075
libMesh::TensorTools::div_from_grad
Number div_from_grad(const VectorValue< Number > &grad)
Dummy. Divergence of a scalar not defined, but is needed for ExactSolution to compile.
Definition: tensor_tools.C:54
libMesh::H2
Definition: enum_norm_type.h:38
mesh
MeshBase & mesh
Definition: mesh_communication.C:1257
libMesh::ExactSolution::h2_error
Real h2_error(const std::string &sys_name, const std::string &unknown_name)
Definition: exact_solution.C:425
libMesh::FEGenericBase::get_dphi
const std::vector< std::vector< OutputGradient > > & get_dphi() const
Definition: fe_base.h:214
libMesh::FEGenericBase::get_div_phi
const std::vector< std::vector< OutputDivergence > > & get_div_phi() const
Definition: fe_base.h:230
libMesh::System::variable
const Variable & variable(unsigned int var) const
Return a constant reference to Variable var.
Definition: system.h:2183
libMesh::ExactSolution::hcurl_error
Real hcurl_error(const std::string &sys_name, const std::string &unknown_name)
Definition: exact_solution.C:410
libMesh::EquationSystems::has_system
bool has_system(const std::string &name) const
Definition: equation_systems.h:694
dim
unsigned int dim
Definition: adaptivity_ex3.C:113
libMesh::NumericVector::build
static std::unique_ptr< NumericVector< T > > build(const Parallel::Communicator &comm, const SolverPackage solver_package=libMesh::default_solver_package())
Builds a NumericVector on the processors in communicator comm using the linear solver package specifi...
Definition: numeric_vector.C:49
libMesh::VectorValue
This class defines a vector in LIBMESH_DIM dimensional Real or Complex space.
Definition: exact_solution.h:54
libMesh::System::current_solution
Number current_solution(const dof_id_type global_dof_number) const
Definition: system.C:194
libMesh::libmesh_assert
libmesh_assert(ctx)
libMesh::ExactSolution::_errors
std::map< std::string, SystemErrorMap > _errors
A map of SystemErrorMaps, which contains entries for each system in the EquationSystems object.
Definition: exact_solution.h:353
libMesh::IntRange
The IntRange templated class is intended to make it easy to loop over integers which are indices of a...
Definition: int_range.h:53
libMesh::FEMNormType
FEMNormType
Definition: enum_norm_type.h:34
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::ExactSolution::_exact_values
std::vector< std::unique_ptr< FunctionBase< Number > > > _exact_values
User-provided functors which compute the exact value of the solution for each system.
Definition: exact_solution.h:323
libMesh::MeshBase
This is the MeshBase class.
Definition: mesh_base.h:78
libMesh::ExactSolution::attach_reference_solution
void attach_reference_solution(const EquationSystems *es_fine)
Attach function similar to system.h which allows the user to attach a second EquationSystems object w...
Definition: exact_solution.C:81
libMesh::TypeVector::norm_sq
auto norm_sq() const -> decltype(std::norm(T()))
Definition: type_vector.h:986
libMesh::WrappedFunction
Wrap a libMesh-style function pointer into a FunctionBase object.
Definition: wrapped_function.h:51
libMesh::System::variable_scalar_number
unsigned int variable_scalar_number(const std::string &var, unsigned int component) const
Definition: system.h:2214
libMesh::ExactSolution::attach_exact_hessian
void attach_exact_hessian(unsigned int sys_num, FunctionBase< Tensor > *h)
Clone and attach an arbitrary functor which computes the exact second derivatives of the system sys_n...
Definition: exact_solution.C:205
libMesh::ExactSolution::hdiv_error
Real hdiv_error(const std::string &sys_name, const std::string &unknown_name)
Definition: exact_solution.C:417
libMesh::System::get_mesh
const MeshBase & get_mesh() const
Definition: system.h:2083
libMesh::System::update_global_solution
void update_global_solution(std::vector< Number > &global_soln) const
Fill the input vector global_soln so that it contains the global solution on all processors.
Definition: system.C:642
libMesh::FEGenericBase::build
static std::unique_ptr< FEGenericBase > build(const unsigned int dim, const FEType &type)
Builds a specific finite element type.
libMesh::ExactSolution::error_norm
Real error_norm(const std::string &sys_name, const std::string &unknown_name, const FEMNormType &norm)
Definition: exact_solution.C:264
libMesh::ExactSolution::_exact_derivs
std::vector< std::unique_ptr< FunctionBase< Gradient > > > _exact_derivs
User-provided functors which compute the exact derivative of the solution for each system.
Definition: exact_solution.h:329
libMesh::ExactSolution::attach_exact_hessians
void attach_exact_hessians(std::vector< FunctionBase< Tensor > * > h)
Clone and attach arbitrary functors which compute the exact second derivatives of the EquationSystems...
Definition: exact_solution.C:194
libMesh::ExactSolution::~ExactSolution
~ExactSolution()
libMesh::DofMap::variable_type
const FEType & variable_type(const unsigned int c) const
Definition: dof_map.h:1924
libMesh::ExactSolution::_equation_systems
const EquationSystems & _equation_systems
Constant reference to the EquationSystems object used for the simulation.
Definition: exact_solution.h:359
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
gptr
Gradient gptr(const Point &p, const Parameters &, const std::string &libmesh_dbg_var(sys_name), const std::string &unknown_name)
Definition: projection.C:95
libMesh::EquationSystems::n_systems
unsigned int n_systems() const
Definition: equation_systems.h:652
libMesh::FEGenericBase::OutputNumber
TensorTools::MakeNumber< OutputShape >::type OutputNumber
Definition: fe_base.h:122
libMesh::H2_SEMINORM
Definition: enum_norm_type.h:44
libMesh::ExactSolution::l2_error
Real l2_error(const std::string &sys_name, const std::string &unknown_name)
Definition: exact_solution.C:333
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::HCURL
Definition: enum_norm_type.h:39
libMesh::ExactSolution::attach_exact_values
void attach_exact_values(const std::vector< FunctionBase< Number > * > &f)
Clone and attach arbitrary functors which compute the exact values of the EquationSystems' solutions ...
Definition: exact_solution.C:112
libMesh::HDIV_SEMINORM
Definition: enum_norm_type.h:47
libMesh::FEGenericBase::OutputNumberDivergence
TensorTools::DecrementRank< OutputNumber >::type OutputNumberDivergence
Definition: fe_base.h:125
libMesh::System::solution
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
Definition: system.h:1539
libMesh::ReferenceElem::get
const Elem & get(const ElemType type_in)
Definition: reference_elem.C:237
libMesh::HCURL_SEMINORM
Definition: enum_norm_type.h:46
libMesh::TensorTools::norm_sq
T norm_sq(std::complex< T > a)
Definition: tensor_tools.h:85
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::System::name
const std::string & name() const
Definition: system.h:2067
libMesh::FEInterface::field_type
static FEFieldType field_type(const FEType &fe_type)
Definition: fe_interface.C:1683
libMesh::FEGenericBase::get_curl_phi
const std::vector< std::vector< OutputShape > > & get_curl_phi() const
Definition: fe_base.h:222
libMesh::TYPE_VECTOR
Definition: enum_fe_family.h:94
libMesh::ExactSolution::_compute_error
void _compute_error(const std::string &sys_name, const std::string &unknown_name, std::vector< Real > &error_vals)
This function computes the error (in the solution and its first derivative) for a single unknown in a...
Definition: exact_solution.C:448
libMesh::L2
Definition: enum_norm_type.h:36
libMesh::System::variable_number
unsigned short int variable_number(const std::string &var) const
Definition: system.C:1232
std::norm
MetaPhysicL::DualNumber< T, D > norm(const MetaPhysicL::DualNumber< T, D > &in)
libMesh::ExactSolution::_check_inputs
std::vector< Real > & _check_inputs(const std::string &sys_name, const std::string &unknown_name)
This function is responsible for checking the validity of the sys_name and unknown_name inputs.
Definition: exact_solution.C:216
libMesh::System::get_dof_map
const DofMap & get_dof_map() const
Definition: system.h:2099
libMesh::err
OStreamProxy err
libMesh::FEGenericBase::get_phi
const std::vector< std::vector< OutputShape > > & get_phi() const
Definition: fe_base.h:206
libMesh::TestClass
Definition: id_types.h:33
libMesh::ExactSolution::l_inf_error
Real l_inf_error(const std::string &sys_name, const std::string &unknown_name)
Definition: exact_solution.C:373
libMesh::H1
Definition: enum_norm_type.h:37
libMesh::Real
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Definition: libmesh_common.h:121
libMesh::Variable::active_on_subdomain
bool active_on_subdomain(subdomain_id_type sid) const
Definition: variable.h:136
libMesh::FEAbstract::reinit
virtual void reinit(const Elem *elem, const std::vector< Point > *const pts=nullptr, const std::vector< Real > *const weights=nullptr)=0
This is at the core of this class.
fptr
Number fptr(const Point &p, const Parameters &, const std::string &libmesh_dbg_var(sys_name), const std::string &unknown_name)
Definition: projection.C:80
libMesh::ExactSolution::SystemErrorMap
std::map< std::string, std::vector< Real > > SystemErrorMap
Data structure which stores the errors: ||e|| = ||u - u_h|| ||grad(e)|| = ||grad(u) - grad(u_h)|| for...
Definition: exact_solution.h:345
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::ExactSolution::_equation_systems_fine
const EquationSystems * _equation_systems_fine
Constant pointer to the EquationSystems object containing the fine grid solution.
Definition: exact_solution.h:365
libMesh::HDIV
Definition: enum_norm_type.h:40
libMesh::DenseVector< Number >
libMesh::EquationSystems::parameters
Parameters parameters
Data structure holding arbitrary parameters.
Definition: equation_systems.h:557