38#include "libmesh/mesh.h"
39#include "libmesh/equation_systems.h"
40#include "libmesh/linear_implicit_system.h"
41#include "libmesh/exodusII_io.h"
42#include "libmesh/fe.h"
43#include "libmesh/quadrature.h"
44#include "libmesh/dense_matrix.h"
45#include "libmesh/dense_vector.h"
46#include "libmesh/sparse_matrix.h"
47#include "libmesh/mesh_generation.h"
48#include "libmesh/mesh_modification.h"
49#include "libmesh/mesh_refinement.h"
50#include "libmesh/error_vector.h"
51#include "libmesh/fourth_error_estimators.h"
52#include "libmesh/getpot.h"
53#include "libmesh/exact_solution.h"
54#include "libmesh/dof_map.h"
55#include "libmesh/numeric_vector.h"
56#include "libmesh/elem.h"
57#include "libmesh/tensor_value.h"
58#include "libmesh/perf_log.h"
59#include "libmesh/string_to_enum.h"
60#include "libmesh/enum_solver_package.h"
61#include "libmesh/dirichlet_boundaries.h"
62#include "libmesh/wrapped_function.h"
74 const std::string & system_name);
103 const std::string &);
108 const std::string &);
113 const std::string &);
118 const std::string &);
123 const std::string &);
128 const std::string &);
140 const std::string &);
145 const std::string &);
150 const std::string &);
156int main(
int argc,
char ** argv)
163 "--enable-petsc, --enable-trilinos, or --enable-eigen");
167#ifdef LIBMESH_DEFAULT_SINGLE_PRECISION
168 libmesh_example_requires(
false,
"double precision");
172#ifndef LIBMESH_ENABLE_AMR
173 libmesh_example_requires(
false,
"--enable-amr");
177#ifndef LIBMESH_ENABLE_SECOND_DERIVATIVES
178 libmesh_example_requires(
false,
"--enable-second");
182 GetPot input_file(
"adaptivity_ex4.in");
185 input_file.parse_command_line(argc, argv);
188 const unsigned int max_r_level = input_file(
"max_r_level", 10);
189 const unsigned int max_r_steps = input_file(
"max_r_steps", 4);
190 const std::string approx_type = input_file(
"approx_type",
"HERMITE");
191 const std::string approx_order_string = input_file(
"approx_order",
"THIRD");
192 const unsigned int uniform_refine = input_file(
"uniform_refine", 0);
193 const Real refine_percentage = input_file(
"refine_percentage", 0.5);
194 const Real coarsen_percentage = input_file(
"coarsen_percentage", 0.5);
195 const unsigned int dim = input_file(
"dimension", 2);
196 const unsigned int max_linear_iterations = input_file(
"max_linear_iterations", 10000);
200 libmesh_example_requires(
dim <= LIBMESH_DIM,
"2D/3D support");
210 std::string output_file =
"";
213 output_file +=
"1D_";
215 output_file +=
"2D_";
217 output_file +=
"3D_";
219 if (approx_type ==
"HERMITE")
220 output_file +=
"hermite_";
221 else if (approx_type ==
"SECOND")
222 output_file +=
"reducedclough_";
224 output_file +=
"clough_";
226 output_file += approx_order_string;
228 if (uniform_refine == 0)
229 output_file +=
"_adaptive";
231 output_file +=
"_uniform";
233#ifdef LIBMESH_HAVE_EXODUS_API
235 std::string exodus_file = output_file;
241 std::ofstream
out (output_file.c_str());
242 out <<
"% dofs L2-error H1-error H2-error\n"
278 if (approx_type !=
"HERMITE")
295 Order approx_order = approx_type ==
"SECOND" ?
SECOND :
296 Utility::string_to_enum<Order>(approx_order_string);
301 if (approx_type ==
"HERMITE")
303 else if (approx_type ==
"SECOND")
305 else if (approx_type ==
"CLOUGH")
308 libmesh_error_msg(
"Invalid approx_type = " << approx_type);
318 const std::vector<unsigned int>
320 std::set<boundary_id_type> all_bdys;
321 for (
unsigned int i=0; i !=
dim; ++i)
323 all_bdys.insert(2*i);
324 all_bdys.insert(2*i+1);
335 equation_systems.
init();
339 (
"linear solver maximum iterations") = max_linear_iterations;
359 for (
unsigned int r_step=0; r_step<max_r_steps; r_step++)
364 libMesh::out <<
"Beginning Solve " << r_step << std::endl;
371 <<
", final residual: "
382 << zero_sol.
l2_error(
"Biharmonic",
"u")
385 << zero_sol.
h1_error(
"Biharmonic",
"u")
388 << zero_sol.
h2_error(
"Biharmonic",
"u")
392 << exact_sol.
l2_error(
"Biharmonic",
"u")
395 << exact_sol.
h1_error(
"Biharmonic",
"u")
398 << exact_sol.
h2_error(
"Biharmonic",
"u")
404 << exact_sol.
l2_error(
"Biharmonic",
"u") <<
" "
405 << exact_sol.
h1_error(
"Biharmonic",
"u") <<
" "
406 << exact_sol.
h2_error(
"Biharmonic",
"u") << std::endl;
413 if (exact_sol.
l2_error(
"Biharmonic",
"u") > 200*std::pow(n_dofs,-4./3.))
414 libmesh_error_msg(
"Unacceptably high L2-error!");
416 if (exact_sol.
h1_error(
"Biharmonic",
"u") > 200./n_dofs)
417 libmesh_error_msg(
"Unacceptably high H1-error!");
419 if (exact_sol.
h2_error(
"Biharmonic",
"u") > 400*std::pow(n_dofs,-2./3.))
420 libmesh_error_msg(
"Unacceptably high H2-error!");
423 if (r_step+1 != max_r_steps)
427 if (uniform_refine == 0)
457 equation_systems.
reinit ();
461#ifdef LIBMESH_HAVE_EXODUS_API
471 <<
"loglog(e(:,1), e(:,2), 'bo-');\n"
472 <<
"loglog(e(:,1), e(:,3), 'ro-');\n"
473 <<
"loglog(e(:,1), e(:,4), 'go-');\n"
474 <<
"xlabel('log(dofs)');\n"
475 <<
"ylabel('log(error)');\n"
476 <<
"title('C1 " << approx_type <<
" elements');\n"
477 <<
"legend('L2-error', 'H1-error', 'H2-error');\n";
496 return 256.*(x-x*x)*(x-x*x);
512 gradu(0) = 256.*2.*(x-x*x)*(1-2*x);
530 hessu(0,0) = 256.*2.*(1-6.*x+6.*x*x);
540 return 256. * 2. * 12.;
554 return 256.*(x-x*x)*(x-x*x)*(y-y*y)*(y-y*y);
571 gradu(0) = 256.*2.*(x-x*x)*(1-2*x)*(y-y*y)*(y-y*y);
572 gradu(1) = 256.*2.*(x-x*x)*(x-x*x)*(y-y*y)*(1-2*y);
591 hessu(0,0) = 256.*2.*(1-6.*x+6.*x*x)*(y-y*y)*(y-y*y);
592 hessu(0,1) = 256.*4.*(x-x*x)*(1.-2.*x)*(y-y*y)*(1.-2.*y);
593 hessu(1,1) = 256.*2.*(x-x*x)*(x-x*x)*(1.-6.*y+6.*y*y);
596 hessu(1,0) = hessu(0,1);
609 return 256. * 8. * (3.*((y-y*y)*(y-y*y)+(x-x*x)*(x-x*x))
610 + (1.-6.*x+6.*x*x)*(1.-6.*y+6.*y*y));
626 return 4096.*(x-x*x)*(x-x*x)*(y-y*y)*(y-y*y)*(z-z*z)*(z-z*z);
643 gradu(0) = 4096.*2.*(x-x*x)*(1.-2.*x)*(y-y*y)*(y-y*y)*(z-z*z)*(z-z*z);
644 gradu(1) = 4096.*2.*(x-x*x)*(x-x*x)*(y-y*y)*(1.-2.*y)*(z-z*z)*(z-z*z);
645 gradu(2) = 4096.*2.*(x-x*x)*(x-x*x)*(y-y*y)*(y-y*y)*(z-z*z)*(1.-2.*z);
665 hessu(0,0) = 4096.*(2.-12.*x+12.*x*x)*(y-y*y)*(y-y*y)*(z-z*z)*(z-z*z);
666 hessu(0,1) = 4096.*4.*(x-x*x)*(1.-2.*x)*(y-y*y)*(1.-2.*y)*(z-z*z)*(z-z*z);
667 hessu(0,2) = 4096.*4.*(x-x*x)*(1.-2.*x)*(y-y*y)*(y-y*y)*(z-z*z)*(1.-2.*z);
668 hessu(1,1) = 4096.*(x-x*x)*(x-x*x)*(2.-12.*y+12.*y*y)*(z-z*z)*(z-z*z);
669 hessu(1,2) = 4096.*4.*(x-x*x)*(x-x*x)*(y-y*y)*(1.-2.*y)*(z-z*z)*(1.-2.*z);
670 hessu(2,2) = 4096.*(x-x*x)*(x-x*x)*(y-y*y)*(y-y*y)*(2.-12.*z+12.*z*z);
673 hessu(1,0) = hessu(0,1);
674 hessu(2,0) = hessu(0,2);
675 hessu(2,1) = hessu(1,2);
690 return 4096. * 8. * (3.*((y-y*y)*(y-y*y)*(x-x*x)*(x-x*x) +
691 (z-z*z)*(z-z*z)*(x-x*x)*(x-x*x) +
692 (z-z*z)*(z-z*z)*(y-y*y)*(y-y*y)) +
693 (1.-6.*x+6.*x*x)*(1.-6.*y+6.*y*y)*(z-z*z)*(z-z*z) +
694 (1.-6.*x+6.*x*x)*(1.-6.*z+6.*z*z)*(y-y*y)*(y-y*y) +
695 (1.-6.*y+6.*y*y)*(1.-6.*z+6.*z*z)*(x-x*x)*(x-x*x));
706 const std::string & system_name)
711#ifdef LIBMESH_ENABLE_AMR
712#ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
716 libmesh_assert_equal_to (system_name,
"Biharmonic");
722 PerfLog perf_log (
"Matrix Assembly",
false);
741 FEType fe_type = dof_map.variable_type(0);
755 fe->attach_quadrature_rule (qrule.get());
769 fe_face->attach_quadrature_rule (qface.get());
775 const std::vector<Real> & JxW = fe->get_JxW();
780 const std::vector<Point> & q_point = fe->get_xyz();
783 const std::vector<std::vector<Real>> & phi = fe->get_phi();
788 const std::vector<std::vector<RealTensor>> & d2phi = fe->get_d2phi();
792 std::vector<Real> shape_laplacian;
804 std::vector<dof_id_type> dof_indices;
812 for (
const auto & elem :
mesh.active_local_element_ptr_range())
817 perf_log.
push(
"elem init");
823 dof_map.dof_indices (elem, dof_indices);
831 const unsigned int n_dofs =
832 cast_int<unsigned int>(dof_indices.size());
833 libmesh_assert_equal_to (n_dofs, phi.size());
837 Ke.
resize (n_dofs, n_dofs);
842 shape_laplacian.resize(n_dofs);
847 perf_log.
pop(
"elem init");
858 perf_log.
push (
"Ke");
860 for (
unsigned int qp=0; qp<qrule->n_points(); qp++)
862 for (
unsigned int i=0; i != n_dofs; i++)
864 shape_laplacian[i] = d2phi[i][qp](0,0);
866 shape_laplacian[i] += d2phi[i][qp](1,1);
868 shape_laplacian[i] += d2phi[i][qp](2,2);
870 for (
unsigned int i=0; i != n_dofs; i++)
871 for (
unsigned int j=0; j != n_dofs; j++)
873 shape_laplacian[i]*shape_laplacian[j];
892 LOG_SCOPE_WITH(
"BCs",
"", perf_log);
895 const Real penalty = 1e10;
896 const Real penalty2 = 1e10;
901 for (
auto s : elem->side_index_range())
902 if (elem->neighbor_ptr(s) ==
nullptr)
906 const std::vector<std::vector<Real>> & phi_face =
911 const std::vector<std::vector<RealGradient>> & dphi_face =
916 const std::vector<Real> & JxW_face = fe_face->get_JxW();
921 const std::vector<Point> & qface_point = fe_face->get_xyz();
922 const std::vector<Point> & face_normals = fe_face->get_normals();
926 fe_face->reinit(elem, s);
928 libmesh_assert_equal_to (n_dofs, phi_face.size());
931 for (
unsigned int qp=0; qp<qface->n_points(); qp++)
946 for (
unsigned int i=0; i != n_dofs; i++)
947 for (
unsigned int j=0; j != n_dofs; j++)
948 Ke(i,j) += JxW_face[qp] *
949 (penalty * phi_face[i][qp] *
950 phi_face[j][qp] + penalty2
951 * (dphi_face[i][qp] *
958 for (
unsigned int i=0; i != n_dofs; i++)
959 Fe(i) += JxW_face[qp] *
960 (penalty *
value * phi_face[i][qp]
962 (flux * face_normals[qp])
964 * face_normals[qp]));
970 for (
unsigned int qp=0; qp<qrule->n_points(); qp++)
971 for (
unsigned int i=0; i != n_dofs; i++)
980 LOG_SCOPE_WITH(
"matrix insertion",
"", perf_log);
982 dof_map.constrain_element_matrix_and_vector(Ke, Fe, dof_indices);
Number forcing_function_2D(const Point &p)
Number exact_1D_solution(const Point &p, const Parameters &, const std::string &, const std::string &)
Gradient(* exact_derivative)(const Point &p, const Parameters &, const std::string &, const std::string &)
Number exact_3D_solution(const Point &p, const Parameters &, const std::string &, const std::string &)
Number(* forcing_function)(const Point &p)
Number forcing_function_3D(const Point &p)
Number(* exact_solution)(const Point &p, const Parameters &, const std::string &, const std::string &)
Number exact_2D_solution(const Point &p, const Parameters &, const std::string &, const std::string &)
Tensor exact_3D_hessian(const Point &p, const Parameters &, const std::string &, const std::string &)
void assemble_biharmonic(EquationSystems &es, const std::string &system_name)
Tensor exact_1D_hessian(const Point &p, const Parameters &, const std::string &, const std::string &)
Tensor exact_2D_hessian(const Point &p, const Parameters &, const std::string &, const std::string &)
Gradient exact_2D_derivative(const Point &p, const Parameters &, const std::string &, const std::string &)
Gradient exact_1D_derivative(const Point &p, const Parameters &, const std::string &, const std::string &)
Gradient exact_3D_derivative(const Point &p, const Parameters &, const std::string &, const std::string &)
Number forcing_function_1D(const Point &p)
Tensor(* exact_hessian)(const Point &p, const Parameters &, const std::string &, const std::string &)
Defines a dense matrix for use in Finite Element-type computations.
void resize(const unsigned int new_m, const unsigned int new_n)
Resizes the matrix to the specified size and calls zero().
Defines a dense vector for use in Finite Element-type computations.
void resize(const unsigned int n)
Resize the vector.
This class allows one to associate Dirichlet boundary values with a given set of mesh boundary ids an...
This class handles the numbering of degrees of freedom on a mesh.
void add_dirichlet_boundary(const DirichletBoundary &dirichlet_boundary)
Adds a copy of the specified Dirichlet boundary to the system.
This is the EquationSystems class.
virtual void reinit()
Handle any mesh changes and reinitialize all the systems on the updated mesh.
void print_info(std::ostream &os=libMesh::out) const
Prints information about the equation systems, by default to libMesh::out.
std::size_t n_active_dofs() const
const MeshBase & get_mesh() const
Parameters parameters
Data structure holding arbitrary parameters.
virtual void init()
Initialize all the systems.
virtual System & add_system(std::string_view system_type, std::string_view name)
Add the system of type system_type named name to the systems array.
const T_sys & get_system(std::string_view name) const
The ErrorVector is a specialization of the StatisticsVector for error data computed on a finite eleme...
virtual Real variance() const override
virtual Real mean() const override
This class handles the computation of the L2 and/or H1 error for the Systems in the EquationSystems o...
Real l2_error(std::string_view sys_name, std::string_view unknown_name)
Real h1_error(std::string_view sys_name, std::string_view unknown_name)
Real h2_error(std::string_view sys_name, std::string_view unknown_name)
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...
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...
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...
void compute_error(std::string_view sys_name, std::string_view unknown_name)
Computes and stores the error in the solution value e = u-u_h, the gradient grad(e) = grad(u) - grad(...
The ExodusII_IO class implements reading meshes in the ExodusII file format from Sandia National Labs...
virtual void write_equation_systems(const std::string &fname, const EquationSystems &es, const std::set< std::string > *system_names=nullptr) override
Writes out the solution for no specific time or timestep.
NumericVector< Number > * rhs
The system matrix.
static std::unique_ptr< FEGenericBase > build(const unsigned int dim, const FEType &type)
Builds a specific finite element type.
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
std::unique_ptr< QBase > default_quadrature_rule(const unsigned int dim, const int extraorder=0) const
const SparseMatrix< Number > & get_system_matrix() const
bool use_unweighted_quadrature_rules
This boolean flag allows you to use "unweighted" quadrature rules (sized to exactly integrate unweigh...
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...
This class is an error indicator based on laplacian jumps between elements.
The LibMeshInit class, when constructed, initializes the dependent libraries (e.g.
Manages consistently variables, degrees of freedom, coefficient vectors, matrices and linear solvers ...
Real final_linear_residual() const
virtual void solve() override
Assembles & solves the linear system A*x=b.
unsigned int n_linear_iterations() const
This is the MeshBase class.
unsigned int mesh_dimension() const
void all_second_order(const bool full_ordered=true)
Calls the range-based version of this function with a range consisting of all elements in the mesh.
void print_info(std::ostream &os=libMesh::out, const unsigned int verbosity=0, const bool global=true) const
Prints relevant information about the mesh.
Implements (adaptive) mesh refinement algorithms for a MeshBase.
void uniformly_refine(unsigned int n=1)
Uniformly refines the mesh n times.
void flag_elements_by_elem_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.
unsigned int & max_h_level()
The max_h_level is the greatest refinement level an element should reach.
bool refine_and_coarsen_elements()
Refines and coarsens user-requested elements.
Real & refine_fraction()
The refine_fraction sets either a desired target or a desired maximum number of elements to flag for ...
Real & coarsen_fraction()
The coarsen_fraction sets either a desired target or a desired maximum number of elements to flag for...
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
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].
This class provides the ability to map between arbitrary, user-defined strings and several data types...
T & set(const std::string &)
The PerfLog class allows monitoring of specific events.
void pop(const char *label, const char *header="")
Pop the event label off the stack, resuming any lower event.
void push(const char *label, const char *header="")
Push the event label onto the stack, pausing any active event.
A Point defines a location in LIBMESH_DIM dimensional Real space.
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.
dof_id_type n_dofs() const
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.
unsigned int add_variable(std::string_view 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.
unsigned int variable_number(std::string_view var) const
const DofMap & get_dof_map() const
This class defines a tensor in LIBMESH_DIM dimensional Real or Complex space.
This class defines a vector in LIBMESH_DIM dimensional Real or Complex space.
Wrap a libMesh-style function pointer into a FunctionBase object.
Gradient exact_grad(const Point &, const Parameters &, const std::string &, const std::string &)
The libMesh namespace provides an interface to certain functionality in the library.
void libmesh_ignore(const Args &...)
SolverPackage default_solver_package()
NumberVectorValue Gradient
static constexpr Real TOLERANCE
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real