fourth_error_estimators.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2018 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 #include "libmesh/libmesh_config.h"
20 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
21 
22 
23 // C++ includes
24 #include <algorithm> // for std::fill
25 #include <cstdlib> // *must* precede <cmath> for proper std:abs() on PGI, Sun Studio CC
26 #include <cmath> // for sqrt
27 
28 
29 // Local Includes
30 #include "libmesh/libmesh_common.h"
32 #include "libmesh/error_vector.h"
33 #include "libmesh/fe_base.h"
35 #include "libmesh/elem.h"
36 #include "libmesh/system.h"
37 #include "libmesh/dense_vector.h"
38 #include "libmesh/tensor_tools.h"
40 #include "libmesh/enum_norm_type.h"
41 
42 namespace libMesh
43 {
44 
45 
48 {
50 }
51 
52 
53 
56 {
57  return LAPLACIAN;
58 }
59 
60 
61 
62 void
64 {
65  const unsigned int n_vars = c.n_vars();
66  for (unsigned int v=0; v<n_vars; v++)
67  {
68  // Possibly skip this variable
69  if (error_norm.weight(v) == 0.0) continue;
70 
71  // FIXME: Need to generalize this to vector-valued elements. [PB]
72  FEBase * side_fe = nullptr;
73 
74  const std::set<unsigned char> & elem_dims =
75  c.elem_dimensions();
76 
77  for (const auto & dim : elem_dims)
78  {
79  fine_context->get_side_fe( v, side_fe, dim );
80 
81  // We'll need hessians on both sides for flux jump computation
82  side_fe->get_d2phi();
83  }
84  }
85 }
86 
87 
88 
89 void
91 {
92  const Elem & coarse_elem = coarse_context->get_elem();
93  const Elem & fine_elem = fine_context->get_elem();
94 
95  const DenseVector<Number> & Ucoarse = coarse_context->get_elem_solution();
96  const DenseVector<Number> & Ufine = fine_context->get_elem_solution();
97 
98  unsigned short dim = fine_elem.dim();
99 
100  FEBase * fe_fine = nullptr;
101  fine_context->get_side_fe( var, fe_fine, dim );
102 
103  FEBase * fe_coarse = nullptr;
104  coarse_context->get_side_fe( var, fe_coarse, dim );
105 
106  Real error = 1.e-30;
107  unsigned int n_qp = fe_fine->n_quadrature_points();
108 
109  std::vector<std::vector<RealTensor>> d2phi_coarse = fe_coarse->get_d2phi();
110  std::vector<std::vector<RealTensor>> d2phi_fine = fe_fine->get_d2phi();
111  std::vector<Real> JxW_face = fe_fine->get_JxW();
112 
113  for (unsigned int qp=0; qp != n_qp; ++qp)
114  {
115  // Calculate solution gradients on fine and coarse elements
116  // at this quadrature point
117  Number laplacian_fine = 0., laplacian_coarse = 0.;
118 
119  const unsigned int n_coarse_dofs = Ucoarse.size();
120  for (unsigned int i=0; i != n_coarse_dofs; ++i)
121  {
122  laplacian_coarse += d2phi_coarse[i][qp](0,0) * Ucoarse(i);
123  if (dim > 1)
124  laplacian_coarse += d2phi_coarse[i][qp](1,1) * Ucoarse(i);
125  if (dim > 2)
126  laplacian_coarse += d2phi_coarse[i][qp](2,2) * Ucoarse(i);
127  }
128 
129  const unsigned int n_fine_dofs = Ufine.size();
130  for (unsigned int i=0; i != n_fine_dofs; ++i)
131  {
132  laplacian_fine += d2phi_fine[i][qp](0,0) * Ufine(i);
133  if (dim > 1)
134  laplacian_fine += d2phi_fine[i][qp](1,1) * Ufine(i);
135  if (dim > 2)
136  laplacian_fine += d2phi_fine[i][qp](2,2) * Ufine(i);
137  }
138 
139 
140  // Find the jump in the Laplacian
141  // at this quadrature point
142  const Number jump = laplacian_fine - laplacian_coarse;
143  const Real jump2 = TensorTools::norm_sq(jump);
144 
145  // Accumulate the jump integral
146  error += JxW_face[qp] * jump2;
147  }
148 
149  // Add the h-weighted jump integral to each error term
150  fine_error =
151  error * fine_elem.hmax() * error_norm.weight(var);
152  coarse_error =
153  error * coarse_elem.hmax() * error_norm.weight(var);
154 }
155 
156 } // namespace libMesh
157 
158 #else // defined (LIBMESH_ENABLE_SECOND_DERIVATIVES)
159 
161 
162 namespace libMesh
163 {
164 
165 void
167 {
168  libmesh_error_msg("Error: LaplacianErrorEstimator requires second " \
169  << "derivative support; try configuring libmesh with " \
170  << "--enable-second");
171 }
172 
173 
174 void
176 {
177  libmesh_error_msg("Error: LaplacianErrorEstimator requires second " \
178  << "derivative support; try configuring libmesh with " \
179  << "--enable-second");
180 }
181 
182 } // namespace libMesh
183 
184 #endif // defined (LIBMESH_ENABLE_SECOND_DERIVATIVES)
virtual unsigned int size() const override
Definition: dense_vector.h:92
virtual void internal_side_integration() override
std::unique_ptr< FEMContext > fine_context
The base class for all geometric element types.
Definition: elem.h:100
virtual unsigned int n_quadrature_points() const =0
const unsigned int n_vars
Definition: tecplot_io.C:69
virtual Real hmax() const
Definition: elem.C:373
const std::vector< Real > & get_JxW() const
Definition: fe_abstract.h:245
const std::vector< std::vector< OutputTensor > > & get_d2phi() const
Definition: fe_base.h:289
std::unique_ptr< FEMContext > coarse_context
virtual void init_context(FEMContext &c) override
Real weight(unsigned int var) const
Definition: system_norm.C:132
virtual ErrorEstimatorType type() const override
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual unsigned short dim() const =0
unsigned int n_vars() const
Definition: diff_context.h:99
const std::set< unsigned char > & elem_dimensions() const
Definition: fem_context.h:913