libMesh
Loading...
Searching...
No Matches
Functions | Variables
adaptivity_ex4.C File Reference

Go to the source code of this file.

Functions

void assemble_biharmonic (EquationSystems &es, const std::string &system_name)
 
Number exact_1D_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 &)
 
Number exact_3D_solution (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_2D_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 &)
 
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 &)
 
Tensor exact_3D_hessian (const Point &p, const Parameters &, const std::string &, const std::string &)
 
Number forcing_function_1D (const Point &p)
 
Number forcing_function_2D (const Point &p)
 
Number forcing_function_3D (const Point &p)
 
int main (int argc, char **argv)
 

Variables

bool penalty_dirichlet = true
 
Number(* exact_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 &)
 
Tensor(* exact_hessian )(const Point &p, const Parameters &, const std::string &, const std::string &)
 
Number(* forcing_function )(const Point &p)
 

Function Documentation

◆ assemble_biharmonic()

void assemble_biharmonic ( EquationSystems es,
const std::string &  system_name 
)

Definition at line 705 of file adaptivity_ex4.C.

707{
708 // Ignore unused parameter warnings when libmesh is configured without certain options.
709 libmesh_ignore(es, system_name);
710
711#ifdef LIBMESH_ENABLE_AMR
712#ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
713
714 // It is a good idea to make sure we are assembling
715 // the proper system.
716 libmesh_assert_equal_to (system_name, "Biharmonic");
717
718 // Declare a performance log. Give it a descriptive
719 // string to identify what part of the code we are
720 // logging, since there may be many PerfLogs in an
721 // application.
722 PerfLog perf_log ("Matrix Assembly", false);
723
724 // Get a constant reference to the mesh object.
725 const MeshBase & mesh = es.get_mesh();
726
727 // The dimension that we are running
728 const unsigned int dim = mesh.mesh_dimension();
729
730 // Get a reference to the LinearImplicitSystem we are solving
731 LinearImplicitSystem & system = es.get_system<LinearImplicitSystem>("Biharmonic");
732
733 // A reference to the DofMap object for this system. The DofMap
734 // object handles the index translation from node and element numbers
735 // to degree of freedom numbers. We will talk more about the DofMap
736 // in future examples.
737 const DofMap & dof_map = system.get_dof_map();
738
739 // Get a constant reference to the Finite Element type
740 // for the first (and only) variable in the system.
741 FEType fe_type = dof_map.variable_type(0);
742
743 // Build a Finite Element object of the specified type. Since the
744 // FEBase::build() member dynamically creates memory we will
745 // store the object as a std::unique_ptr<FEBase>. This can be thought
746 // of as a pointer that will clean up after itself.
747 std::unique_ptr<FEBase> fe (FEBase::build(dim, fe_type));
748
749 // Quadrature rule for numerical integration.
750 // With 2D triangles, the Clough quadrature rule puts a Gaussian
751 // quadrature rule on each of the 3 subelements
752 std::unique_ptr<QBase> qrule(fe_type.default_quadrature_rule(dim));
753
754 // Tell the finite element object to use our quadrature rule.
755 fe->attach_quadrature_rule (qrule.get());
756
757 // Declare a special finite element object for
758 // boundary integration.
759 std::unique_ptr<FEBase> fe_face (FEBase::build(dim, fe_type));
760
761 // Boundary integration requires another quadrature rule,
762 // with dimensionality one less than the dimensionality
763 // of the element.
764 // In 1D, the Clough and Gauss quadrature rules are identical.
765 std::unique_ptr<QBase> qface(fe_type.default_quadrature_rule(dim-1));
766
767 // Tell the finite element object to use our
768 // quadrature rule.
769 fe_face->attach_quadrature_rule (qface.get());
770
771 // Here we define some references to cell-specific data that
772 // will be used to assemble the linear system.
773 // We begin with the element Jacobian * quadrature weight at each
774 // integration point.
775 const std::vector<Real> & JxW = fe->get_JxW();
776
777 // The physical XY locations of the quadrature points on the element.
778 // These might be useful for evaluating spatially varying material
779 // properties at the quadrature points.
780 const std::vector<Point> & q_point = fe->get_xyz();
781
782 // The element shape functions evaluated at the quadrature points.
783 const std::vector<std::vector<Real>> & phi = fe->get_phi();
784
785 // The element shape function second derivatives evaluated at the
786 // quadrature points. Note that for the simple biharmonic, shape
787 // function first derivatives are unnecessary.
788 const std::vector<std::vector<RealTensor>> & d2phi = fe->get_d2phi();
789
790 // For efficiency we will compute shape function laplacians n times,
791 // not n^2
792 std::vector<Real> shape_laplacian;
793
794 // Define data structures to contain the element matrix
795 // and right-hand-side vector contribution. Following
796 // basic finite element terminology we will denote these
797 // "Ke" and "Fe". More detail is in example 3.
800
801 // This vector will hold the degree of freedom indices for
802 // the element. These define where in the global system
803 // the element degrees of freedom get mapped.
804 std::vector<dof_id_type> dof_indices;
805
806 // The global system matrix
807 SparseMatrix<Number> & matrix = system.get_system_matrix();
808
809 // Now we will loop over all the elements in the mesh. We will
810 // compute the element matrix and right-hand-side contribution. See
811 // example 3 for a discussion of the element iterators.
812 for (const auto & elem : mesh.active_local_element_ptr_range())
813 {
814 // Start logging the shape function initialization.
815 // This is done through a simple function call with
816 // the name of the event to log.
817 perf_log.push("elem init");
818
819 // Get the degree of freedom indices for the
820 // current element. These define where in the global
821 // matrix and right-hand-side this element will
822 // contribute to.
823 dof_map.dof_indices (elem, dof_indices);
824
825 // Compute the element-specific data for the current
826 // element. This involves computing the location of the
827 // quadrature points (q_point) and the shape functions
828 // (phi, dphi) for the current element.
829 fe->reinit (elem);
830
831 const unsigned int n_dofs =
832 cast_int<unsigned int>(dof_indices.size());
833 libmesh_assert_equal_to (n_dofs, phi.size());
834
835 // Zero the element matrix and right-hand side before
836 // summing them.
837 Ke.resize (n_dofs, n_dofs);
838
839 Fe.resize (n_dofs);
840
841 // Make sure there is enough room in this cache
842 shape_laplacian.resize(n_dofs);
843
844 // Stop logging the shape function initialization.
845 // If you forget to stop logging an event the PerfLog
846 // object will probably catch the error and abort.
847 perf_log.pop("elem init");
848
849 // Now we will build the element matrix. This involves
850 // a double loop to integrate laplacians of the test functions
851 // (i) against laplacians of the trial functions (j).
852 //
853 // This step is why we need the Clough-Tocher elements -
854 // these C1 differentiable elements have square-integrable
855 // second derivatives.
856 //
857 // Now start logging the element matrix computation
858 perf_log.push ("Ke");
859
860 for (unsigned int qp=0; qp<qrule->n_points(); qp++)
861 {
862 for (unsigned int i=0; i != n_dofs; i++)
863 {
864 shape_laplacian[i] = d2phi[i][qp](0,0);
865 if (dim > 1)
866 shape_laplacian[i] += d2phi[i][qp](1,1);
867 if (dim == 3)
868 shape_laplacian[i] += d2phi[i][qp](2,2);
869 }
870 for (unsigned int i=0; i != n_dofs; i++)
871 for (unsigned int j=0; j != n_dofs; j++)
872 Ke(i,j) += JxW[qp]*
873 shape_laplacian[i]*shape_laplacian[j];
874 }
875
876 // Stop logging the matrix computation
877 perf_log.pop ("Ke");
878
879
880 // At this point the interior element integration has
881 // been completed. However, we may have not yet addressed
882 // boundary conditions, if we didn't add a DirichletBoundary to
883 // our system earlier. In that case, we will demonstrate the
884 // imposition of simple Dirichlet boundary conditions imposed
885 // via the penalty method. Note that this is a fourth-order
886 // problem: Dirichlet boundary conditions include *both*
887 // boundary values and boundary normal fluxes.
889 {
890 // Start logging the boundary condition computation. We use a
891 // macro to log everything in this scope.
892 LOG_SCOPE_WITH("BCs", "", perf_log);
893
894 // The penalty values, for solution boundary trace and flux.
895 const Real penalty = 1e10;
896 const Real penalty2 = 1e10;
897
898 // The following loops over the sides of the element.
899 // If the element has no neighbor on a side then that
900 // side MUST live on a boundary of the domain.
901 for (auto s : elem->side_index_range())
902 if (elem->neighbor_ptr(s) == nullptr)
903 {
904 // The value of the shape functions at the quadrature
905 // points.
906 const std::vector<std::vector<Real>> & phi_face =
907 fe_face->get_phi();
908
909 // The value of the shape function derivatives at the
910 // quadrature points.
911 const std::vector<std::vector<RealGradient>> & dphi_face =
912 fe_face->get_dphi();
913
914 // The Jacobian * Quadrature Weight at the quadrature
915 // points on the face.
916 const std::vector<Real> & JxW_face = fe_face->get_JxW();
917
918 // The XYZ locations (in physical space) of the
919 // quadrature points on the face. This is where
920 // we will interpolate the boundary value function.
921 const std::vector<Point> & qface_point = fe_face->get_xyz();
922 const std::vector<Point> & face_normals = fe_face->get_normals();
923
924 // Compute the shape function values on the element
925 // face.
926 fe_face->reinit(elem, s);
927
928 libmesh_assert_equal_to (n_dofs, phi_face.size());
929
930 // Loop over the face quadrature points for integration.
931 for (unsigned int qp=0; qp<qface->n_points(); qp++)
932 {
933 // The boundary value.
934 Number value = exact_solution(qface_point[qp],
935 es.parameters, "null",
936 "void");
937 Gradient flux = exact_2D_derivative(qface_point[qp],
938 es.parameters,
939 "null", "void");
940
941 // Matrix contribution of the L2 projection.
942 // Note that the basis function values are
943 // integrated against test function values while
944 // basis fluxes are integrated against test function
945 // fluxes.
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] *
952 face_normals[qp]) *
953 (dphi_face[j][qp] *
954 face_normals[qp]));
955
956 // Right-hand-side contribution of the L2
957 // projection.
958 for (unsigned int i=0; i != n_dofs; i++)
959 Fe(i) += JxW_face[qp] *
960 (penalty * value * phi_face[i][qp]
961 + penalty2 *
962 (flux * face_normals[qp])
963 * (dphi_face[i][qp]
964 * face_normals[qp]));
965
966 }
967 }
968 }
969
970 for (unsigned int qp=0; qp<qrule->n_points(); qp++)
971 for (unsigned int i=0; i != n_dofs; i++)
972 Fe(i) += JxW[qp]*phi[i][qp]*forcing_function(q_point[qp]);
973
974 // The element matrix and right-hand-side are now built
975 // for this element. Add them to the global matrix and
976 // right-hand-side vector. The SparseMatrix::add_matrix()
977 // and NumericVector::add_vector() members do this for us.
978 // Start logging the insertion of the local (element)
979 // matrix and vector into the global matrix and vector
980 LOG_SCOPE_WITH("matrix insertion", "", perf_log);
981
982 dof_map.constrain_element_matrix_and_vector(Ke, Fe, dof_indices);
983 matrix.add_matrix (Ke, dof_indices);
984 system.rhs->add_vector (Fe, dof_indices);
985 }
986
987 // That's it. We don't need to do anything else to the
988 // PerfLog. When it goes out of scope (at this function return)
989 // it will print its log to the screen. Pretty easy, huh?
990
991#else
992
993#endif // #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
994#endif // #ifdef LIBMESH_ENABLE_AMR
995}
unsigned int dim
Number(* forcing_function)(const Point &p)
bool penalty_dirichlet
Number(* exact_solution)(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 &)
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 handles the numbering of degrees of freedom on a mesh.
Definition dof_map.h:181
const MeshBase & get_mesh() const
Parameters parameters
Data structure holding arbitrary parameters.
const T_sys & get_system(std::string_view name) const
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...
Definition fe_type.h:197
std::unique_ptr< QBase > default_quadrature_rule(const unsigned int dim, const int extraorder=0) const
Definition fe_type.C:34
const SparseMatrix< Number > & get_system_matrix() const
Manages consistently variables, degrees of freedom, coefficient vectors, matrices and linear solvers ...
This is the MeshBase class.
Definition mesh_base.h:81
unsigned int mesh_dimension() const
Definition mesh_base.C:430
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].
The PerfLog class allows monitoring of specific events.
Definition perf_log.h:154
Generic sparse 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.
const DofMap & get_dof_map() const
Definition system.h:2417
This class defines a vector in LIBMESH_DIM dimensional Real or Complex space.
MeshBase & mesh
void libmesh_ignore(const Args &...)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static const bool value
Definition xdr_io.C:55

References libMesh::SparseMatrix< T >::add_matrix(), libMesh::NumericVector< T >::add_vector(), libMesh::FEGenericBase< OutputType >::build(), libMesh::FEType::default_quadrature_rule(), dim, exact_2D_derivative(), exact_solution, forcing_function, libMesh::System::get_dof_map(), libMesh::EquationSystems::get_mesh(), libMesh::EquationSystems::get_system(), libMesh::ImplicitSystem::get_system_matrix(), libMesh::libmesh_ignore(), mesh, libMesh::MeshBase::mesh_dimension(), libMesh::EquationSystems::parameters, penalty_dirichlet, libMesh::PerfLog::pop(), libMesh::PerfLog::push(), libMesh::Real, libMesh::DenseVector< T >::resize(), libMesh::DenseMatrix< T >::resize(), libMesh::ExplicitSystem::rhs, and value.

Referenced by main().

◆ exact_1D_derivative()

Gradient exact_1D_derivative ( const Point p,
const Parameters ,
const std::string &  ,
const std::string &   
)

Definition at line 501 of file adaptivity_ex4.C.

505{
506 // x coordinate in space
507 const Real x = p(0);
508
509 // First derivatives to be returned.
510 Gradient gradu;
511
512 gradu(0) = 256.*2.*(x-x*x)*(1-2*x);
513
514 return gradu;
515}

References libMesh::Real.

Referenced by main().

◆ exact_1D_hessian()

Tensor exact_1D_hessian ( const Point p,
const Parameters ,
const std::string &  ,
const std::string &   
)

Definition at line 519 of file adaptivity_ex4.C.

523{
524 // Second derivatives to be returned.
525 Tensor hessu;
526
527 // x coordinate in space
528 const Real x = p(0);
529
530 hessu(0,0) = 256.*2.*(1-6.*x+6.*x*x);
531
532 return hessu;
533}
This class defines a tensor in LIBMESH_DIM dimensional Real or Complex space.

References libMesh::Real.

Referenced by main().

◆ exact_1D_solution()

Number exact_1D_solution ( const Point p,
const Parameters ,
const std::string &  ,
const std::string &   
)

Definition at line 487 of file adaptivity_ex4.C.

491{
492 // x coordinate in space
493 const Real x = p(0);
494
495 // analytic solution value
496 return 256.*(x-x*x)*(x-x*x);
497}

References libMesh::Real.

Referenced by main().

◆ exact_2D_derivative()

Gradient exact_2D_derivative ( const Point p,
const Parameters ,
const std::string &  ,
const std::string &   
)

Definition at line 559 of file adaptivity_ex4.C.

563{
564 // x and y coordinates in space
565 const Real x = p(0);
566 const Real y = p(1);
567
568 // First derivatives to be returned.
569 Gradient gradu;
570
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);
573
574 return gradu;
575}

References libMesh::Real.

Referenced by assemble_biharmonic(), and main().

◆ exact_2D_hessian()

Tensor exact_2D_hessian ( const Point p,
const Parameters ,
const std::string &  ,
const std::string &   
)

Definition at line 579 of file adaptivity_ex4.C.

583{
584 // Second derivatives to be returned.
585 Tensor hessu;
586
587 // x and y coordinates in space
588 const Real x = p(0);
589 const Real y = p(1);
590
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);
594
595 // Hessians are always symmetric
596 hessu(1,0) = hessu(0,1);
597 return hessu;
598}

References libMesh::Real.

Referenced by main().

◆ exact_2D_solution()

Number exact_2D_solution ( const Point p,
const Parameters ,
const std::string &  ,
const std::string &   
)

Definition at line 544 of file adaptivity_ex4.C.

548{
549 // x and y coordinates in space
550 const Real x = p(0);
551 const Real y = p(1);
552
553 // analytic solution value
554 return 256.*(x-x*x)*(x-x*x)*(y-y*y)*(y-y*y);
555}

References libMesh::Real.

Referenced by main().

◆ exact_3D_derivative()

Gradient exact_3D_derivative ( const Point p,
const Parameters ,
const std::string &  ,
const std::string &   
)

Definition at line 630 of file adaptivity_ex4.C.

634{
635 // First derivatives to be returned.
636 Gradient gradu;
637
638 // xyz coordinates in space
639 const Real x = p(0);
640 const Real y = p(1);
641 const Real z = p(2);
642
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);
646
647 return gradu;
648}

References libMesh::Real.

Referenced by main().

◆ exact_3D_hessian()

Tensor exact_3D_hessian ( const Point p,
const Parameters ,
const std::string &  ,
const std::string &   
)

Definition at line 652 of file adaptivity_ex4.C.

656{
657 // Second derivatives to be returned.
658 Tensor hessu;
659
660 // xyz coordinates in space
661 const Real x = p(0);
662 const Real y = p(1);
663 const Real z = p(2);
664
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);
671
672 // Hessians are always symmetric
673 hessu(1,0) = hessu(0,1);
674 hessu(2,0) = hessu(0,2);
675 hessu(2,1) = hessu(1,2);
676
677 return hessu;
678}

References libMesh::Real.

Referenced by main().

◆ exact_3D_solution()

Number exact_3D_solution ( const Point p,
const Parameters ,
const std::string &  ,
const std::string &   
)

Definition at line 615 of file adaptivity_ex4.C.

619{
620 // xyz coordinates in space
621 const Real x = p(0);
622 const Real y = p(1);
623 const Real z = p(2);
624
625 // analytic solution value
626 return 4096.*(x-x*x)*(x-x*x)*(y-y*y)*(y-y*y)*(z-z*z)*(z-z*z);
627}

References libMesh::Real.

Referenced by main().

◆ forcing_function_1D()

Number forcing_function_1D ( const Point p)

Definition at line 537 of file adaptivity_ex4.C.

538{
539 // Equals laplacian(laplacian(u)), u'''' in 1D
540 return 256. * 2. * 12.;
541}

Referenced by main().

◆ forcing_function_2D()

Number forcing_function_2D ( const Point p)

Definition at line 602 of file adaptivity_ex4.C.

603{
604 // x and y coordinates in space
605 const Real x = p(0);
606 const Real y = p(1);
607
608 // Equals laplacian(laplacian(u))
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));
611}

References libMesh::Real.

Referenced by main().

◆ forcing_function_3D()

Number forcing_function_3D ( const Point p)

Definition at line 682 of file adaptivity_ex4.C.

683{
684 // xyz coordinates in space
685 const Real x = p(0);
686 const Real y = p(1);
687 const Real z = p(2);
688
689 // Equals laplacian(laplacian(u))
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));
696}

References libMesh::Real.

Referenced by main().

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 156 of file adaptivity_ex4.C.

157{
158 // Initialize libMesh.
159 LibMeshInit init (argc, argv);
160
161 // This example requires a linear solver package.
162 libmesh_example_requires(libMesh::default_solver_package() != INVALID_SOLVER_PACKAGE,
163 "--enable-petsc, --enable-trilinos, or --enable-eigen");
164
165 // Adaptive constraint calculations for fine Hermite elements seems
166 // to require half-decent precision
167#ifdef LIBMESH_DEFAULT_SINGLE_PRECISION
168 libmesh_example_requires(false, "double precision");
169#endif
170
171 // This example requires Adaptive Mesh Refinement support
172#ifndef LIBMESH_ENABLE_AMR
173 libmesh_example_requires(false, "--enable-amr");
174#else
175
176 // This example requires second derivative calculation support
177#ifndef LIBMESH_ENABLE_SECOND_DERIVATIVES
178 libmesh_example_requires(false, "--enable-second");
179#else
180
181 // Parse the input file
182 GetPot input_file("adaptivity_ex4.in");
183
184 // But allow the command line to override it.
185 input_file.parse_command_line(argc, argv);
186
187 // Read in parameters from the input file
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);
197 penalty_dirichlet = input_file("penalty_dirichlet", penalty_dirichlet);
198
199 // Skip higher-dimensional examples on a lower-dimensional libMesh build
200 libmesh_example_requires(dim <= LIBMESH_DIM, "2D/3D support");
201
202 // Currently only the Hermite cubics give a 1D or 3D C^1 basis
203 libmesh_assert (dim == 2 || approx_type == "HERMITE");
204
205 // Create a mesh, with dimension to be overridden later, on the
206 // default MPI communicator.
207 Mesh mesh(init.comm());
208
209 // Output file for plotting the error
210 std::string output_file = "";
211
212 if (dim == 1)
213 output_file += "1D_";
214 else if (dim == 2)
215 output_file += "2D_";
216 else if (dim == 3)
217 output_file += "3D_";
218
219 if (approx_type == "HERMITE")
220 output_file += "hermite_";
221 else if (approx_type == "SECOND")
222 output_file += "reducedclough_";
223 else
224 output_file += "clough_";
225
226 output_file += approx_order_string;
227
228 if (uniform_refine == 0)
229 output_file += "_adaptive";
230 else
231 output_file += "_uniform";
232
233#ifdef LIBMESH_HAVE_EXODUS_API
234 // If we have Exodus, use the same base output filename
235 std::string exodus_file = output_file;
236 exodus_file += ".e";
237#endif // #ifdef LIBMESH_HAVE_EXODUS_API
238
239 output_file += ".m";
240
241 std::ofstream out (output_file.c_str());
242 out << "% dofs L2-error H1-error H2-error\n"
243 << "e = [\n";
244
245 // Set up the dimension-dependent coarse mesh and solution
246 if (dim == 1)
247 {
253 }
254
255 if (dim == 2)
256 {
262 }
263 else if (dim == 3)
264 {
270 }
271
272 // Convert the mesh to second order: necessary for computing with
273 // Clough-Tocher elements, useful for getting slightly less
274 // broken visualization output with Hermite elements
276
277 // Convert it to triangles if necessary
278 if (approx_type != "HERMITE")
280
281 // Mesh Refinement object
282 MeshRefinement mesh_refinement(mesh);
283 mesh_refinement.refine_fraction() = refine_percentage;
284 mesh_refinement.coarsen_fraction() = coarsen_percentage;
285 mesh_refinement.max_h_level() = max_r_level;
286
287 // Create an equation systems object.
288 EquationSystems equation_systems (mesh);
289
290 // Declare the system and its variables.
291 // Create a system named "Biharmonic"
292 LinearImplicitSystem & system =
293 equation_systems.add_system<LinearImplicitSystem> ("Biharmonic");
294
295 Order approx_order = approx_type == "SECOND" ? SECOND :
296 Utility::string_to_enum<Order>(approx_order_string);
297
298 // Adds the variable "u" to "Biharmonic". "u" will be approximated
299 // using Hermite tensor product squares or Clough-Tocher triangles
300
301 if (approx_type == "HERMITE")
302 system.add_variable("u", approx_order, HERMITE);
303 else if (approx_type == "SECOND")
304 system.add_variable("u", SECOND, CLOUGH);
305 else if (approx_type == "CLOUGH")
306 system.add_variable("u", approx_order, CLOUGH);
307 else
308 libmesh_error_msg("Invalid approx_type = " << approx_type);
309
310 // Give the system a pointer to the matrix assembly
311 // function.
313
314 // Give the system Dirichlet boundary conditions, if we want to
315 // enforce those strongly.
317 {
318 const std::vector<unsigned int>
319 all_vars(1, system.variable_number("u"));
320 std::set<boundary_id_type> all_bdys;
321 for (unsigned int i=0; i != dim; ++i)
322 {
323 all_bdys.insert(2*i);
324 all_bdys.insert(2*i+1);
325 }
326
327 WrappedFunction<Number> exact_val(system, exact_solution);
329 DirichletBoundary exact_bc(all_bdys, all_vars, exact_val,
330 exact_grad);
331 system.get_dof_map().add_dirichlet_boundary(exact_bc);
332 }
333
334 // Initialize the data structures for the equation system.
335 equation_systems.init();
336
337 // Set linear solver max iterations
338 equation_systems.parameters.set<unsigned int>
339 ("linear solver maximum iterations") = max_linear_iterations;
340
341 // Linear solver tolerance.
342 equation_systems.parameters.set<Real>
343 ("linear solver tolerance") = TOLERANCE * TOLERANCE;
344
345 // Prints information about the system to the screen.
346 equation_systems.print_info();
347
348 // Construct ExactSolution object and attach function to compute exact solution
349 ExactSolution exact_sol(equation_systems);
350 exact_sol.attach_exact_value(exact_solution);
351 exact_sol.attach_exact_deriv(exact_derivative);
352 exact_sol.attach_exact_hessian(exact_hessian);
353
354 // Construct zero solution object, useful for computing solution norms
355 // Attaching "zero_solution" functions is unnecessary
356 ExactSolution zero_sol(equation_systems);
357
358 // A refinement loop.
359 for (unsigned int r_step=0; r_step<max_r_steps; r_step++)
360 {
362 equation_systems.print_info();
363
364 libMesh::out << "Beginning Solve " << r_step << std::endl;
365
366 // Solve the system "Biharmonic", just like example 2.
367 system.solve();
368
369 libMesh::out << "Linear solver converged at step: "
370 << system.n_linear_iterations()
371 << ", final residual: "
372 << system.final_linear_residual()
373 << std::endl;
374
375 // Compute the error.
376 exact_sol.compute_error("Biharmonic", "u");
377 // Compute the norm.
378 zero_sol.compute_error("Biharmonic", "u");
379
380 // Print out the error values
381 libMesh::out << "L2-Norm is: "
382 << zero_sol.l2_error("Biharmonic", "u")
383 << std::endl;
384 libMesh::out << "H1-Norm is: "
385 << zero_sol.h1_error("Biharmonic", "u")
386 << std::endl;
387 libMesh::out << "H2-Norm is: "
388 << zero_sol.h2_error("Biharmonic", "u")
389 << std::endl
390 << std::endl;
391 libMesh::out << "L2-Error is: "
392 << exact_sol.l2_error("Biharmonic", "u")
393 << std::endl;
394 libMesh::out << "H1-Error is: "
395 << exact_sol.h1_error("Biharmonic", "u")
396 << std::endl;
397 libMesh::out << "H2-Error is: "
398 << exact_sol.h2_error("Biharmonic", "u")
399 << std::endl
400 << std::endl;
401
402 // Print to output file
403 out << equation_systems.n_active_dofs() << " "
404 << exact_sol.l2_error("Biharmonic", "u") << " "
405 << exact_sol.h1_error("Biharmonic", "u") << " "
406 << exact_sol.h2_error("Biharmonic", "u") << std::endl;
407
408 // Assert that we're not outright diverging here, for regression
409 // testing. These bounds just come from eyeballing some graphs
410 // and tacking on a huge tolerance.
411 const dof_id_type n_dofs = system.n_dofs();
412
413 if (exact_sol.l2_error("Biharmonic", "u") > 200*std::pow(n_dofs,-4./3.))
414 libmesh_error_msg("Unacceptably high L2-error!");
415
416 if (exact_sol.h1_error("Biharmonic", "u") > 200./n_dofs)
417 libmesh_error_msg("Unacceptably high H1-error!");
418
419 if (exact_sol.h2_error("Biharmonic", "u") > 400*std::pow(n_dofs,-2./3.))
420 libmesh_error_msg("Unacceptably high H2-error!");
421
422 // Possibly refine the mesh
423 if (r_step+1 != max_r_steps)
424 {
425 libMesh::out << " Refining the mesh..." << std::endl;
426
427 if (uniform_refine == 0)
428 {
429 ErrorVector error;
430 LaplacianErrorEstimator error_estimator;
431
432 // This is another subclass of JumpErrorEstimator, based
433 // on measuring discontinuities across sides between
434 // elements, and we can tell it to use a cheaper
435 // "unweighted" quadrature rule when numerically
436 // integrating those discontinuities.
437 error_estimator.use_unweighted_quadrature_rules = true;
438
439 error_estimator.estimate_error(system, error);
440 mesh_refinement.flag_elements_by_elem_fraction (error);
441
442 libMesh::out << "Mean Error: " << error.mean() << std::endl;
443 libMesh::out << "Error Variance: " << error.variance() << std::endl;
444
445 mesh_refinement.refine_and_coarsen_elements();
446 }
447 else
448 {
449 mesh_refinement.uniformly_refine(1);
450 }
451
452 // This call reinitializes the EquationSystems object for
453 // the newly refined mesh. One of the steps in the
454 // reinitialization is projecting the solution,
455 // old_solution, etc... vectors from the old mesh to
456 // the current one.
457 equation_systems.reinit ();
458 }
459 }
460
461#ifdef LIBMESH_HAVE_EXODUS_API
462 // After solving the system write the solution
463 // to a ExodusII-formatted plot file.
465 equation_systems);
466#endif // #ifdef LIBMESH_HAVE_EXODUS_API
467
468 // Close up the output file.
469 out << "];\n"
470 << "hold on\n"
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";
478
479 // All done.
480 return 0;
481#endif // #ifndef LIBMESH_ENABLE_SECOND_DERIVATIVES
482#endif // #ifndef LIBMESH_ENABLE_AMR
483}
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_3D(const Point &p)
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_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 &)
This class allows one to associate Dirichlet boundary values with a given set of mesh boundary ids an...
void add_dirichlet_boundary(const DirichletBoundary &dirichlet_boundary)
Adds a copy of the specified Dirichlet boundary to the system.
This is the EquationSystems class.
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...
The ExodusII_IO class implements reading meshes in the ExodusII file format from Sandia National Labs...
Definition exodusII_io.h:53
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.
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.
Definition libmesh.h:92
virtual void solve() override
Assembles & solves the linear system A*x=b.
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.
Definition mesh_base.C:1803
void print_info(std::ostream &os=libMesh::out, const unsigned int verbosity=0, const bool global=true) const
Prints relevant information about the mesh.
Definition mesh_base.C:1755
Implements (adaptive) mesh refinement algorithms for a MeshBase.
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
Definition mesh.h:51
dof_id_type n_dofs() const
Definition system.C:118
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:1959
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.
Definition system.C:1344
unsigned int variable_number(std::string_view var) const
Definition system.C:1398
Wrap a libMesh-style function pointer into a FunctionBase object.
Gradient exact_grad(const Point &, const Parameters &, const std::string &, const std::string &)
Definition mysystems.h:25
void build_square(UnstructuredMesh &mesh, const unsigned int nx, const unsigned int ny, const Real xmin=0., const Real xmax=1., const Real ymin=0., const Real ymax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
A specialized build_cube() for 2D meshes.
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.
void build_cube(UnstructuredMesh &mesh, const unsigned int nx=0, const unsigned int ny=0, const unsigned int nz=0, const Real xmin=0., const Real xmax=1., const Real ymin=0., const Real ymax=1., const Real zmin=0., const Real zmax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
Builds a (elements) cube.
void all_tri(MeshBase &mesh)
Subdivides any non-simplex elements in a Mesh to produce simplex (triangular in 2D,...
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
SolverPackage default_solver_package()
Definition libmesh.C:1064
libmesh_assert(ctx)
OStreamProxy out
static constexpr Real TOLERANCE
uint8_t dof_id_type
Definition id_types.h:67

References libMesh::DofMap::add_dirichlet_boundary(), libMesh::EquationSystems::add_system(), libMesh::System::add_variable(), libMesh::MeshBase::all_second_order(), libMesh::MeshTools::Modification::all_tri(), assemble_biharmonic(), libMesh::System::attach_assemble_function(), libMesh::ExactSolution::attach_exact_deriv(), libMesh::ExactSolution::attach_exact_hessian(), libMesh::ExactSolution::attach_exact_value(), libMesh::MeshTools::Generation::build_cube(), libMesh::MeshTools::Generation::build_line(), libMesh::MeshTools::Generation::build_square(), libMesh::CLOUGH, libMesh::MeshRefinement::coarsen_fraction(), libMesh::ExactSolution::compute_error(), libMesh::default_solver_package(), dim, libMesh::JumpErrorEstimator::estimate_error(), exact_1D_derivative(), exact_1D_hessian(), exact_1D_solution(), exact_2D_derivative(), exact_2D_hessian(), exact_2D_solution(), exact_3D_derivative(), exact_3D_hessian(), exact_3D_solution(), exact_derivative, exact_grad(), exact_hessian, exact_solution, libMesh::LinearImplicitSystem::final_linear_residual(), libMesh::MeshRefinement::flag_elements_by_elem_fraction(), forcing_function, forcing_function_1D(), forcing_function_2D(), forcing_function_3D(), libMesh::System::get_dof_map(), libMesh::ExactSolution::h1_error(), libMesh::ExactSolution::h2_error(), libMesh::HERMITE, libMesh::EquationSystems::init(), libMesh::INVALID_SOLVER_PACKAGE, libMesh::ExactSolution::l2_error(), libMesh::libmesh_assert(), main(), libMesh::MeshRefinement::max_h_level(), libMesh::ErrorVector::mean(), mesh, libMesh::EquationSystems::n_active_dofs(), libMesh::System::n_dofs(), libMesh::LinearImplicitSystem::n_linear_iterations(), libMesh::out, libMesh::EquationSystems::parameters, penalty_dirichlet, libMesh::EquationSystems::print_info(), libMesh::MeshBase::print_info(), libMesh::Real, libMesh::MeshRefinement::refine_and_coarsen_elements(), libMesh::MeshRefinement::refine_fraction(), libMesh::EquationSystems::reinit(), libMesh::SECOND, libMesh::Parameters::set(), libMesh::LinearImplicitSystem::solve(), libMesh::TOLERANCE, libMesh::MeshRefinement::uniformly_refine(), libMesh::JumpErrorEstimator::use_unweighted_quadrature_rules, libMesh::System::variable_number(), libMesh::ErrorVector::variance(), and libMesh::ExodusII_IO::write_equation_systems().

Variable Documentation

◆ exact_derivative

Gradient exact_derivative ( const Point p,
const Parameters ,
const std::string &  ,
const std::string &   
)

Definition at line 142 of file adaptivity_ex4.C.

Referenced by main().

◆ exact_hessian

Tensor(* exact_hessian) (const Point &p, const Parameters &, const std::string &, const std::string &) ( const Point p,
const Parameters ,
const std::string &  ,
const std::string &   
)

Definition at line 147 of file adaptivity_ex4.C.

Referenced by main().

◆ exact_solution

Number exact_solution ( const Point p,
const Parameters ,
const std::string &  ,
const std::string &   
)

◆ forcing_function

Number(* forcing_function) (const Point &p) ( const Point p)

Definition at line 152 of file adaptivity_ex4.C.

Referenced by assemble_biharmonic(), compute_residual(), and main().

◆ penalty_dirichlet

bool penalty_dirichlet = true

Definition at line 77 of file adaptivity_ex4.C.

Referenced by assemble_biharmonic(), and main().