libMesh
Functions
adaptivity_ex1.C File Reference

Go to the source code of this file.

Functions

void assemble_1D (EquationSystems &es, const std::string &system_name)
 
int main (int argc, char **argv)
 

Function Documentation

◆ assemble_1D()

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

Definition at line 185 of file adaptivity_ex1.C.

187 {
188  // Ignore unused parameter warnings when !LIBMESH_ENABLE_AMR.
189  libmesh_ignore(es, system_name);
190 
191 #ifdef LIBMESH_ENABLE_AMR
192 
193  // It is a good idea to check we are solving the correct system
194  libmesh_assert_equal_to (system_name, "1D");
195 
196  // Get a reference to the mesh object
197  const MeshBase & mesh = es.get_mesh();
198 
199  // The dimension we are using, i.e. dim==1
200  const unsigned int dim = mesh.mesh_dimension();
201 
202  // Get a reference to the system we are solving
204 
205  // Get a reference to the DofMap object for this system. The DofMap object
206  // handles the index translation from node and element numbers to degree of
207  // freedom numbers. DofMap's are discussed in more detail in future examples.
208  const DofMap & dof_map = system.get_dof_map();
209 
210  // Get a constant reference to the Finite Element type for the first
211  // (and only) variable in the system.
212  FEType fe_type = dof_map.variable_type(0);
213 
214  // Build a finite element object of the specified type. The build
215  // function dynamically allocates memory so we use a std::unique_ptr in this case.
216  // A std::unique_ptr is a pointer that cleans up after itself. See examples 3 and 4
217  // for more details on std::unique_ptr.
218  std::unique_ptr<FEBase> fe(FEBase::build(dim, fe_type));
219 
220  // Tell the finite element object to use fifth order Gaussian quadrature
221  QGauss qrule(dim, FIFTH);
222  fe->attach_quadrature_rule(&qrule);
223 
224  // Here we define some references to cell-specific data that will be used to
225  // assemble the linear system.
226 
227  // The element Jacobian * quadrature weight at each integration point.
228  const std::vector<Real> & JxW = fe->get_JxW();
229 
230  // The element shape functions evaluated at the quadrature points.
231  const std::vector<std::vector<Real>> & phi = fe->get_phi();
232 
233  // The element shape function gradients evaluated at the quadrature points.
234  const std::vector<std::vector<RealGradient>> & dphi = fe->get_dphi();
235 
236  // Declare a dense matrix and dense vector to hold the element matrix
237  // and right-hand-side contribution
240 
241  // This vector will hold the degree of freedom indices for the element.
242  // These define where in the global system the element degrees of freedom
243  // get mapped.
244  std::vector<dof_id_type> dof_indices;
245 
246  // We now loop over all the active elements in the mesh in order to calculate
247  // the matrix and right-hand-side contribution from each element. Use a
248  // const_element_iterator to loop over the elements. We make
249  // el_end const as it is used only for the stopping condition of the loop.
250  for (const auto & elem : mesh.active_local_element_ptr_range())
251  {
252  // Get the degree of freedom indices for the current element.
253  // These define where in the global matrix and right-hand-side this
254  // element will contribute to.
255  dof_map.dof_indices(elem, dof_indices);
256 
257  // Compute the element-specific data for the current element. This
258  // involves computing the location of the quadrature points (q_point)
259  // and the shape functions (phi, dphi) for the current element.
260  fe->reinit(elem);
261 
262  // Store the number of local degrees of freedom contained in this element
263  const unsigned int n_dofs =
264  cast_int<unsigned int>(dof_indices.size());
265  libmesh_assert_equal_to (n_dofs, phi.size());
266 
267  // We resize and zero out Ke and Fe (resize() also clears the matrix and
268  // vector). In this example, all elements in the mesh are EDGE3's, so
269  // Ke will always be 3x3, and Fe will always be 3x1. If the mesh contained
270  // different element types, then the size of Ke and Fe would change.
271  Ke.resize(n_dofs, n_dofs);
272  Fe.resize(n_dofs);
273 
274 
275  // Now loop over quadrature points to handle numerical integration
276  for (unsigned int qp=0; qp<qrule.n_points(); qp++)
277  {
278  // Now build the element matrix and right-hand-side using loops to
279  // integrate the test functions (i) against the trial functions (j).
280  for (unsigned int i=0; i != n_dofs; i++)
281  {
282  Fe(i) += JxW[qp]*phi[i][qp];
283 
284  for (unsigned int j=0; j != n_dofs; j++)
285  {
286  Ke(i,j) += JxW[qp]*(1.e-3*dphi[i][qp]*dphi[j][qp] +
287  phi[i][qp]*phi[j][qp]);
288  }
289  }
290  }
291 
292 
293  // At this point we have completed the matrix and RHS summation. The
294  // final step is to apply boundary conditions, which in this case are
295  // simple Dirichlet conditions with u(0) = u(1) = 0.
296 
297  // Define the penalty parameter used to enforce the BC's
298  double penalty = 1.e10;
299 
300  // Loop over the sides of this element. For a 1D element, the "sides"
301  // are defined as the nodes on each edge of the element, i.e. 1D elements
302  // have 2 sides.
303  for (auto s : elem->side_index_range())
304  {
305  // If this element has a nullptr neighbor, then it is on the edge of the
306  // mesh and we need to enforce a boundary condition using the penalty
307  // method.
308  if (elem->neighbor_ptr(s) == nullptr)
309  {
310  Ke(s,s) += penalty;
311  Fe(s) += 0*penalty;
312  }
313  }
314 
315  // This is a function call that is necessary when using adaptive
316  // mesh refinement. See Adaptivity Example 2 for more details.
317  dof_map.constrain_element_matrix_and_vector (Ke, Fe, dof_indices);
318 
319  // Add Ke and Fe to the global matrix and right-hand-side.
320  system.matrix->add_matrix(Ke, dof_indices);
321  system.rhs->add_vector(Fe, dof_indices);
322  }
323 #endif // #ifdef LIBMESH_ENABLE_AMR
324 }

References libMesh::MeshBase::active_local_element_ptr_range(), libMesh::SparseMatrix< T >::add_matrix(), libMesh::NumericVector< T >::add_vector(), libMesh::FEGenericBase< OutputType >::build(), dim, libMesh::FIFTH, libMesh::System::get_dof_map(), libMesh::EquationSystems::get_mesh(), libMesh::EquationSystems::get_system(), libMesh::libmesh_ignore(), libMesh::ImplicitSystem::matrix, mesh, libMesh::MeshBase::mesh_dimension(), libMesh::QBase::n_points(), libMesh::DenseVector< T >::resize(), libMesh::DenseMatrix< T >::resize(), and libMesh::ExplicitSystem::rhs.

Referenced by main().

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 60 of file adaptivity_ex1.C.

61 {
62  // Initialize the library. This is necessary because the library
63  // may depend on a number of other libraries (i.e. MPI and PETSc)
64  // that require initialization before use. When the LibMeshInit
65  // object goes out of scope, other libraries and resources are
66  // finalized.
67  LibMeshInit init (argc, argv);
68 
69  // This example requires a linear solver package.
70  libmesh_example_requires(libMesh::default_solver_package() != INVALID_SOLVER_PACKAGE,
71  "--enable-petsc, --enable-trilinos, or --enable-eigen");
72 
73  // Skip adaptive examples on a non-adaptive libMesh build
74 #ifndef LIBMESH_ENABLE_AMR
75  libmesh_example_requires(false, "--enable-amr");
76 #else
77 
78  // Create a mesh, with dimension to be overridden later, on the
79  // default MPI communicator.
80  Mesh mesh(init.comm());
81 
82  GetPot command_line (argc, argv);
83 
84  int n = 4;
85  if (command_line.search(1, "-n"))
86  n = command_line.next(n);
87 
88  // Build a 1D mesh with 4 elements from x=0 to x=1, using
89  // EDGE3 (i.e. quadratic) 1D elements. They are called EDGE3 elements
90  // because a quadratic element contains 3 nodes.
92 
93  // Define the equation systems object and the system we are going
94  // to solve. See Introduction Example 2 for more details.
95  EquationSystems equation_systems(mesh);
96  LinearImplicitSystem & system = equation_systems.add_system
97  <LinearImplicitSystem>("1D");
98 
99  // Add a variable "u" to the system, using second-order approximation
100  system.add_variable("u", SECOND);
101 
102  // Give the system a pointer to the matrix assembly function. This
103  // will be called when needed by the library.
105 
106  // Define the mesh refinement object that takes care of adaptively
107  // refining the mesh.
108  MeshRefinement mesh_refinement(mesh);
109 
110  // These parameters determine the proportion of elements that will
111  // be refined and coarsened. Any element within 30% of the maximum
112  // error on any element will be refined, and any element within 30%
113  // of the minimum error on any element might be coarsened
114  mesh_refinement.refine_fraction() = 0.7;
115  mesh_refinement.coarsen_fraction() = 0.3;
116  // We won't refine any element more than 5 times in total
117  mesh_refinement.max_h_level() = 5;
118 
119  // Initialize the data structures for the equation system.
120  equation_systems.init();
121 
122  // Refinement parameters
123  const unsigned int max_r_steps = 5; // Refine the mesh 5 times
124 
125  // Define the refinement loop
126  for (unsigned int r_step=0; r_step<=max_r_steps; r_step++)
127  {
128  // Solve the equation system
129  equation_systems.get_system("1D").solve();
130 
131  // We need to ensure that the mesh is not refined on the last iteration
132  // of this loop, since we do not want to refine the mesh unless we are
133  // going to solve the equation system for that refined mesh.
134  if (r_step != max_r_steps)
135  {
136  // Error estimation objects, see Adaptivity Example 2 for details
137  ErrorVector error;
138  KellyErrorEstimator error_estimator;
139  error_estimator.use_unweighted_quadrature_rules = true;
140 
141  // Compute the error for each active element
142  error_estimator.estimate_error(system, error);
143 
144  // Output error estimate magnitude
145  libMesh::out << "Error estimate\nl2 norm = "
146  << error.l2_norm()
147  << "\nmaximum = "
148  << error.maximum()
149  << std::endl;
150 
151  // Flag elements to be refined and coarsened
152  mesh_refinement.flag_elements_by_error_fraction (error);
153 
154  // Perform refinement and coarsening
155  mesh_refinement.refine_and_coarsen_elements();
156 
157  // Reinitialize the equation_systems object for the newly refined
158  // mesh. One of the steps in this is project the solution onto the
159  // new mesh
160  equation_systems.reinit();
161  }
162  }
163 
164  // Construct gnuplot plotting object, pass in mesh, title of plot
165  // and boolean to indicate use of grid in plot. The grid is used to
166  // show the edges of each element in the mesh.
167  GnuPlotIO plot(mesh, "Adaptivity Example 1", GnuPlotIO::GRID_ON);
168 
169  // Write out script to be called from within gnuplot:
170  // Load gnuplot, then type "call 'gnuplot_script'" from gnuplot prompt
171  plot.write_equation_systems("gnuplot_script", equation_systems);
172 #endif // #ifndef LIBMESH_ENABLE_AMR
173 
174  // All done. libMesh objects are destroyed here. Because the
175  // LibMeshInit object was created first, its destruction occurs
176  // last, and it's destructor finalizes any external libraries and
177  // checks for leaked memory.
178  return 0;
179 }

References libMesh::EquationSystems::add_system(), libMesh::System::add_variable(), assemble_1D(), libMesh::System::attach_assemble_function(), libMesh::MeshTools::Generation::build_line(), libMesh::MeshRefinement::coarsen_fraction(), libMesh::default_solver_package(), libMesh::EDGE3, libMesh::JumpErrorEstimator::estimate_error(), libMesh::MeshRefinement::flag_elements_by_error_fraction(), libMesh::EquationSystems::get_system(), libMesh::GnuPlotIO::GRID_ON, libMesh::TriangleWrapper::init(), libMesh::EquationSystems::init(), libMesh::INVALID_SOLVER_PACKAGE, libMesh::StatisticsVector< T >::l2_norm(), libMesh::MeshRefinement::max_h_level(), libMesh::StatisticsVector< T >::maximum(), mesh, libMesh::out, libMesh::MeshRefinement::refine_and_coarsen_elements(), libMesh::MeshRefinement::refine_fraction(), libMesh::EquationSystems::reinit(), libMesh::SECOND, libMesh::JumpErrorEstimator::use_unweighted_quadrature_rules, and libMesh::MeshOutput< MT >::write_equation_systems().

libMesh::Mesh
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
Definition: mesh.h:50
libMesh::EquationSystems::get_mesh
const MeshBase & get_mesh() const
Definition: equation_systems.h:637
libMesh::ExplicitSystem::rhs
NumericVector< Number > * rhs
The system matrix.
Definition: explicit_system.h:114
libMesh::QGauss
This class implements specific orders of Gauss quadrature.
Definition: quadrature_gauss.h:39
libMesh::JumpErrorEstimator::estimate_error
virtual void estimate_error(const System &system, ErrorVector &error_per_cell, const NumericVector< Number > *solution_vector=nullptr, bool estimate_parent_error=false) override
This function uses the derived class's jump error estimate formula to estimate the error on each cell...
Definition: jump_error_estimator.C:53
libMesh::StatisticsVector::l2_norm
virtual Real l2_norm() const
Definition: statistics.C:37
libMesh::MeshBase::active_local_element_ptr_range
virtual SimpleRange< element_iterator > active_local_element_ptr_range()=0
libMesh::EquationSystems::get_system
const T_sys & get_system(const std::string &name) const
Definition: equation_systems.h:757
libMesh::DenseMatrix< Number >
libMesh::default_solver_package
SolverPackage default_solver_package()
Definition: libmesh.C:993
mesh
MeshBase & mesh
Definition: mesh_communication.C:1257
libMesh::MeshBase::mesh_dimension
unsigned int mesh_dimension() const
Definition: mesh_base.C:135
libMesh::FIFTH
Definition: enum_order.h:46
libMesh::SECOND
Definition: enum_order.h:43
dim
unsigned int dim
Definition: adaptivity_ex3.C:113
libMesh::DenseMatrix::resize
void resize(const unsigned int new_m, const unsigned int new_n)
Resize the matrix.
Definition: dense_matrix.h:822
libMesh::TriangleWrapper::init
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
libMesh::MeshRefinement
Implements (adaptive) mesh refinement algorithms for a MeshBase.
Definition: mesh_refinement.h:61
libMesh::KellyErrorEstimator
This class implements the Kelly error indicator which is based on the flux jumps between elements.
Definition: kelly_error_estimator.h:59
libMesh::System::attach_assemble_function
void attach_assemble_function(void fptr(EquationSystems &es, const std::string &name))
Register a user function to use in assembling the system matrix and RHS.
Definition: system.C:1755
libMesh::NumericVector::add_vector
virtual void add_vector(const T *v, const std::vector< numeric_index_type > &dof_indices)
Computes , where v is a pointer and each dof_indices[i] specifies where to add value v[i].
Definition: numeric_vector.C:363
libMesh::MeshBase
This is the MeshBase class.
Definition: mesh_base.h:78
libMesh::INVALID_SOLVER_PACKAGE
Definition: enum_solver_package.h:43
libMesh::libmesh_ignore
void libmesh_ignore(const Args &...)
Definition: libmesh_common.h:526
libMesh::System::add_variable
unsigned int add_variable(const std::string &var, const FEType &type, const std::set< subdomain_id_type > *const active_subdomains=nullptr)
Adds the variable var to the list of variables for this system.
Definition: system.C:1069
libMesh::MeshTools::Generation::build_line
void build_line(UnstructuredMesh &mesh, const unsigned int nx, const Real xmin=0., const Real xmax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
A specialized build_cube() for 1D meshes.
Definition: mesh_generation.C:1480
libMesh::ImplicitSystem::matrix
SparseMatrix< Number > * matrix
The system matrix.
Definition: implicit_system.h:393
libMesh::ErrorVector
The ErrorVector is a specialization of the StatisticsVector for error data computed on a finite eleme...
Definition: error_vector.h:50
libMesh::LibMeshInit
The LibMeshInit class, when constructed, initializes the dependent libraries (e.g.
Definition: libmesh.h:83
libMesh::EquationSystems
This is the EquationSystems class.
Definition: equation_systems.h:74
libMesh::DenseVector::resize
void resize(const unsigned int n)
Resize the vector.
Definition: dense_vector.h:355
libMesh::SparseMatrix::add_matrix
virtual void add_matrix(const DenseMatrix< T > &dm, const std::vector< numeric_index_type > &rows, const std::vector< numeric_index_type > &cols)=0
Add the full matrix dm to the SparseMatrix.
libMesh::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::EDGE3
Definition: enum_elem_type.h:36
libMesh::JumpErrorEstimator::use_unweighted_quadrature_rules
bool use_unweighted_quadrature_rules
This boolean flag allows you to use "unweighted" quadrature rules (sized to exactly integrate unweigh...
Definition: jump_error_estimator.h:113
libMesh::System::get_dof_map
const DofMap & get_dof_map() const
Definition: system.h:2099
libMesh::GnuPlotIO
This class implements writing meshes using GNUplot, designed for use only with 1D meshes.
Definition: gnuplot_io.h:43
libMesh::LinearImplicitSystem
Manages consistently variables, degrees of freedom, coefficient vectors, matrices and linear solvers ...
Definition: linear_implicit_system.h:55
libMesh::out
OStreamProxy out
libMesh::DenseVector< Number >
libMesh::StatisticsVector::maximum
virtual T maximum() const
Definition: statistics.C:62
assemble_1D
void assemble_1D(EquationSystems &es, const std::string &system_name)
Definition: adaptivity_ex1.C:185