libMesh
Loading...
Searching...
No Matches
miscellaneous_ex5.C
Go to the documentation of this file.
1// The libMesh Finite Element Library.
2// Copyright (C) 2002-2026 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
20// <h1>Miscellaneous Example 5 - Interior Penalty Discontinuous Galerkin</h1>
21// \author Lorenzo Botti
22// \date 2010
23//
24// This example is based on Adaptivity Example 3, but uses an
25// Interior Penalty Discontinuous Galerkin formulation.
26
27#include <iostream>
28
29// LibMesh include files.
30#include "libmesh/libmesh.h"
31#include "libmesh/mesh.h"
32#include "libmesh/equation_systems.h"
33#include "libmesh/mesh_generation.h"
34#include "libmesh/mesh_modification.h"
35#include "libmesh/elem.h"
36#include "libmesh/transient_system.h"
37#include "libmesh/fe.h"
38#include "libmesh/quadrature_gauss.h"
39#include "libmesh/dof_map.h"
40#include "libmesh/sparse_matrix.h"
41#include "libmesh/dense_matrix.h"
42#include "libmesh/dense_vector.h"
43#include "libmesh/dense_submatrix.h"
44#include "libmesh/dense_subvector.h"
45#include "libmesh/numeric_vector.h"
46#include "libmesh/linear_implicit_system.h"
47#include "libmesh/exodusII_io.h"
48#include "libmesh/fe_interface.h"
49#include "libmesh/getpot.h"
50#include "libmesh/mesh_refinement.h"
51#include "libmesh/error_vector.h"
52#include "libmesh/kelly_error_estimator.h"
53#include "libmesh/discontinuity_measure.h"
54#include "libmesh/string_to_enum.h"
55#include "libmesh/exact_solution.h"
56#include "libmesh/enum_solver_package.h"
57#include "libmesh/elem_side_builder.h"
58//#define QORDER TWENTYSIXTH
59
60// Bring in everything from the libMesh namespace
61using namespace libMesh;
62
64 const Parameters & parameters,
65 const std::string &,
66 const std::string &)
67{
68 const Real x = p(0);
69 const Real y = p(1);
70 const Real z = p(2);
71
72 if (parameters.get<bool>("singularity"))
73 {
74 Real theta = atan2(y, x);
75
76 if (theta < 0)
77 theta += 2. * libMesh::pi;
78
79 return pow(x*x + y*y, 1./3.)*sin(2./3.*theta) + z;
80 }
81 else
82 {
83 return cos(x) * exp(y) * (1. - z);
84 }
85}
86
87// We now define the gradient of the exact solution, again being careful
88// to obtain an angle from atan2 in the correct
89// quadrant.
91 const Parameters & parameters, // es parameters
92 const std::string &, // sys_name, not needed
93 const std::string &) // unk_name, not needed
94{
95 // Gradient value to be returned.
96 Gradient gradu;
97
98 // x and y coordinates in space
99 const Real x = p(0);
100 const Real y = p(1);
101 const Real z = p(2);
102
103 if (parameters.get<bool>("singularity"))
104 {
105 libmesh_assert_not_equal_to (x, 0.);
106
107 // For convenience...
108 const Real tt = 2./3.;
109 const Real ot = 1./3.;
110
111 // The value of the radius, squared
112 const Real r2 = x*x + y*y;
113
114 // The boundary value, given by the exact solution,
115 // u_exact = r^(2/3)*sin(2*theta/3).
116 Real theta = atan2(y, x);
117
118 // Make sure 0 <= theta <= 2*pi
119 if (theta < 0)
120 theta += 2. * libMesh::pi;
121
122 // du/dx
123 gradu(0) = tt*x*pow(r2,-tt)*sin(tt*theta) - pow(r2,ot)*cos(tt*theta)*tt/(1.+y*y/x/x)*y/x/x;
124 gradu(1) = tt*y*pow(r2,-tt)*sin(tt*theta) + pow(r2,ot)*cos(tt*theta)*tt/(1.+y*y/x/x)*1./x;
125 gradu(2) = 1.;
126 }
127 else
128 {
129 gradu(0) = -sin(x) * exp(y) * (1. - z);
130 gradu(1) = cos(x) * exp(y) * (1. - z);
131 gradu(2) = -cos(x) * exp(y);
132 }
133 return gradu;
134}
135
136// We now define the matrix assembly function for the
137// Laplace system. We need to first compute element volume
138// matrices, and then take into account the boundary
139// conditions and the flux integrals, which will be handled
140// via an interior penalty method.
142 const std::string & libmesh_dbg_var(system_name))
143{
144 libMesh::out << " assembling elliptic dg system... ";
146
147 // It is a good idea to make sure we are assembling
148 // the proper system.
149 libmesh_assert_equal_to (system_name, "EllipticDG");
150
151 // Get a constant reference to the mesh object.
152 const MeshBase & mesh = es.get_mesh();
153 // The dimension that we are running
154 const unsigned int dim = mesh.mesh_dimension();
155
156 // Get a reference to the LinearImplicitSystem we are solving
157 LinearImplicitSystem & ellipticdg_system = es.get_system<LinearImplicitSystem> ("EllipticDG");
158 // Get some parameters that we need during assembly
159 const Real penalty = es.parameters.get<Real> ("penalty");
160 std::string refinement_type = es.parameters.get<std::string> ("refinement");
161
162 // A reference to the DofMap object for this system. The DofMap
163 // object handles the index translation from node and element numbers
164 // to degree of freedom numbers. We will talk more about the DofMap
165 const DofMap & dof_map = ellipticdg_system.get_dof_map();
166
167 // Get a constant reference to the Finite Element type
168 // for the first (and only) variable in the system.
169 FEType fe_type = ellipticdg_system.variable_type(0);
170
171 // Build a Finite Element object of the specified type. Since the
172 // FEBase::build() member dynamically creates memory we will
173 // store the object as a std::unique_ptr<FEBase>. This can be thought
174 // of as a pointer that will clean up after itself.
175 std::unique_ptr<FEBase> fe (FEBase::build(dim, fe_type));
176 std::unique_ptr<FEBase> fe_elem_face(FEBase::build(dim, fe_type));
177 std::unique_ptr<FEBase> fe_neighbor_face(FEBase::build(dim, fe_type));
178
179 // Quadrature rules for numerical integration.
180#ifdef QORDER
181 QGauss qrule (dim, QORDER);
182#else
183 QGauss qrule (dim, fe_type.default_quadrature_order());
184#endif
185 fe->attach_quadrature_rule (&qrule);
186
187#ifdef QORDER
188 QGauss qface(dim-1, QORDER);
189#else
190 QGauss qface(dim-1, fe_type.default_quadrature_order());
191#endif
192
193 // Tell the finite element object to use our quadrature rule.
194 fe_elem_face->attach_quadrature_rule(&qface);
195 fe_neighbor_face->attach_quadrature_rule(&qface);
196
197 // Here we define some references to cell-specific data that
198 // will be used to assemble the linear system.
199 // Data for interior volume integrals
200 const std::vector<Real> & JxW = fe->get_JxW();
201 const std::vector<std::vector<RealGradient>> & dphi = fe->get_dphi();
202
203 // Data for surface integrals on the element boundary
204 const std::vector<std::vector<Real>> & phi_face = fe_elem_face->get_phi();
205 const std::vector<std::vector<RealGradient>> & dphi_face = fe_elem_face->get_dphi();
206 const std::vector<Real> & JxW_face = fe_elem_face->get_JxW();
207 const std::vector<Point> & qface_normals = fe_elem_face->get_normals();
208 const std::vector<Point> & qface_points = fe_elem_face->get_xyz();
209
210 // Data for surface integrals on the neighbor boundary
211 const std::vector<std::vector<Real>> & phi_neighbor_face = fe_neighbor_face->get_phi();
212 const std::vector<std::vector<RealGradient>> & dphi_neighbor_face = fe_neighbor_face->get_dphi();
213
214 // Define data structures to contain the element interior matrix
215 // and right-hand-side vector contribution. Following
216 // basic finite element terminology we will denote these
217 // "Ke" and "Fe".
220
221 // Data structures to contain the element and neighbor boundary matrix
222 // contribution. This matrices will do the coupling between the dofs of
223 // the element and those of his neighbors.
224 // Ken: matrix coupling elem and neighbor dofs
229
230 // This vector will hold the degree of freedom indices for
231 // the element. These define where in the global system
232 // the element degrees of freedom get mapped.
233 std::vector<dof_id_type> dof_indices;
234
235 // The global system matrix
236 SparseMatrix<Number> & matrix = ellipticdg_system.get_system_matrix();
237
238 // We need to compute element side volumes, which requires obtaining
239 // a side element. Instead of constructing a new side every time,
240 // we leverage the ElemSideBuilder which can produce element sides
241 // and only allocates memory for each unique element side type.
242 ElemSideBuilder side_builder;
243
244 // Now we will loop over all the elements in the mesh. We will
245 // compute first the element interior matrix and right-hand-side contribution
246 // and then the element and neighbors boundary matrix contributions.
247 for (const auto & elem : mesh.active_local_element_ptr_range())
248 {
249 // Get the degree of freedom indices for the
250 // current element. These define where in the global
251 // matrix and right-hand-side this element will
252 // contribute to.
253 dof_map.dof_indices (elem, dof_indices);
254 const unsigned int n_dofs =
255 cast_int<unsigned int>(dof_indices.size());
256
257 // Compute the element-specific data for the current
258 // element. This involves computing the location of the
259 // quadrature points (q_point) and the shape functions
260 // (phi, dphi) for the current element.
261 fe->reinit (elem);
262
263 // Zero the element matrix and right-hand side before
264 // summing them. We use the resize member here because
265 // the number of degrees of freedom might have changed from
266 // the last element.
267 Ke.resize (n_dofs, n_dofs);
268 Fe.resize (n_dofs);
269
270 // Now we will build the element interior matrix. This involves
271 // a double loop to integrate the test functions (i) against
272 // the trial functions (j).
273 for (unsigned int qp=0; qp<qrule.n_points(); qp++)
274 for (unsigned int i=0; i<n_dofs; i++)
275 for (unsigned int j=0; j<n_dofs; j++)
276 Ke(i,j) += JxW[qp]*(dphi[i][qp]*dphi[j][qp]);
277
278 // Now we address boundary conditions.
279 // We consider Dirichlet bc imposed via the interior penalty method
280 // The following loops over the sides of the element.
281 // If the element has no neighbor on a side then that
282 // side MUST live on a boundary of the domain.
283 for (auto side : elem->side_index_range())
284 {
285 if (elem->neighbor_ptr(side) == nullptr)
286 {
287 // Reinit the side
288 fe_elem_face->reinit(elem, side);
289
290 // h element dimension to compute the interior penalty penalty parameter
291 const auto side_volume = side_builder(*elem, side).volume();
292 const unsigned int elem_b_order = static_cast<unsigned int> (fe_elem_face->get_order());
293 const Real h_elem = elem->volume()/side_volume * 1./pow(elem_b_order, 2.);
294
295 for (unsigned int qp=0; qp<qface.n_points(); qp++)
296 {
297 Number bc_value = exact_solution(qface_points[qp], es.parameters, "null", "void");
298 for (unsigned int i=0; i<n_dofs; i++)
299 {
300 // Matrix contribution
301 for (unsigned int j=0; j<n_dofs; j++)
302 {
303 // stability
304 Ke(i,j) += JxW_face[qp] * penalty/h_elem * phi_face[i][qp] * phi_face[j][qp];
305
306 // consistency
307 Ke(i,j) -=
308 JxW_face[qp] *
309 (phi_face[i][qp] * (dphi_face[j][qp]*qface_normals[qp]) +
310 phi_face[j][qp] * (dphi_face[i][qp]*qface_normals[qp]));
311 }
312
313 // RHS contributions
314
315 // stability
316 Fe(i) += JxW_face[qp] * bc_value * penalty/h_elem * phi_face[i][qp];
317
318 // consistency
319 Fe(i) -= JxW_face[qp] * dphi_face[i][qp] * (bc_value*qface_normals[qp]);
320 }
321 }
322 }
323
324 // If the element is not on a boundary of the domain
325 // we loop over his neighbors to compute the element
326 // and neighbor boundary matrix contributions
327 else
328 {
329 // Store a pointer to the neighbor we are currently
330 // working on.
331 const Elem * neighbor = elem->neighbor_ptr(side);
332
333 // Get the global id of the element and the neighbor
334 const unsigned int elem_id = elem->id();
335 const unsigned int neighbor_id = neighbor->id();
336
337 // If the neighbor has the same h level and is active
338 // perform integration only if our global id is bigger than our neighbor id.
339 // We don't want to compute twice the same contributions.
340 // If the neighbor has a different h level perform integration
341 // only if the neighbor is at a lower level.
342 if ((neighbor->active() &&
343 (neighbor->level() == elem->level()) &&
344 (elem_id < neighbor_id)) ||
345 (neighbor->level() < elem->level()))
346 {
347 const Elem & elem_side = side_builder(*elem, side);
348
349 // h dimension to compute the interior penalty penalty parameter
350 const unsigned int elem_b_order = static_cast<unsigned int>(fe_elem_face->get_order());
351 const unsigned int neighbor_b_order = static_cast<unsigned int>(fe_neighbor_face->get_order());
352 const double side_order = (elem_b_order + neighbor_b_order)/2.;
353 const Real h_elem = (elem->volume()/elem_side.volume()) * 1./pow(side_order,2.);
354
355 // The quadrature point locations on the neighbor side
356 std::vector<Point> qface_neighbor_point;
357
358 // The quadrature point locations on the element side
359 std::vector<Point > qface_point;
360
361 // Reinitialize shape functions on the element side
362 fe_elem_face->reinit(elem, side);
363
364 // Get the physical locations of the element quadrature points
365 qface_point = fe_elem_face->get_xyz();
366
367 // Find their locations on the neighbor
368 unsigned int side_neighbor = neighbor->which_neighbor_am_i(elem);
369 if (refinement_type == "p")
370 fe_neighbor_face->side_map (neighbor,
371 &elem_side,
372 side_neighbor,
373 qface.get_points(),
374 qface_neighbor_point);
375 else
376 FEMap::inverse_map (elem->dim(), neighbor,
377 qface_point,
378 qface_neighbor_point);
379
380 // Calculate the neighbor element shape functions at those locations
381 fe_neighbor_face->reinit(neighbor, &qface_neighbor_point);
382
383 // Get the degree of freedom indices for the
384 // neighbor. These define where in the global
385 // matrix this neighbor will contribute to.
386 std::vector<dof_id_type> neighbor_dof_indices;
387 dof_map.dof_indices (neighbor, neighbor_dof_indices);
388 const unsigned int n_neighbor_dofs =
389 cast_int<unsigned int>(neighbor_dof_indices.size());
390
391 // Zero the element and neighbor side matrix before
392 // summing them. We use the resize member here because
393 // the number of degrees of freedom might have changed from
394 // the last element or neighbor.
395 // Note that Kne and Ken are not square matrices if neighbor
396 // and element have a different p level
397 Kne.resize (n_neighbor_dofs, n_dofs);
398 Ken.resize (n_dofs, n_neighbor_dofs);
399 Kee.resize (n_dofs, n_dofs);
400 Knn.resize (n_neighbor_dofs, n_neighbor_dofs);
401
402 // Now we will build the element and neighbor
403 // boundary matrices. This involves
404 // a double loop to integrate the test functions
405 // (i) against the trial functions (j).
406 for (unsigned int qp=0; qp<qface.n_points(); qp++)
407 {
408 // Kee Matrix. Integrate the element test function i
409 // against the element test function j
410 for (unsigned int i=0; i<n_dofs; i++)
411 {
412 for (unsigned int j=0; j<n_dofs; j++)
413 {
414 // consistency
415 Kee(i,j) -=
416 0.5 * JxW_face[qp] *
417 (phi_face[j][qp]*(qface_normals[qp]*dphi_face[i][qp]) +
418 phi_face[i][qp]*(qface_normals[qp]*dphi_face[j][qp]));
419
420 // stability
421 Kee(i,j) += JxW_face[qp] * penalty/h_elem * phi_face[j][qp]*phi_face[i][qp];
422 }
423 }
424
425 // Knn Matrix. Integrate the neighbor test function i
426 // against the neighbor test function j
427 for (unsigned int i=0; i<n_neighbor_dofs; i++)
428 {
429 for (unsigned int j=0; j<n_neighbor_dofs; j++)
430 {
431 // consistency
432 Knn(i,j) +=
433 0.5 * JxW_face[qp] *
434 (phi_neighbor_face[j][qp]*(qface_normals[qp]*dphi_neighbor_face[i][qp]) +
435 phi_neighbor_face[i][qp]*(qface_normals[qp]*dphi_neighbor_face[j][qp]));
436
437 // stability
438 Knn(i,j) +=
439 JxW_face[qp] * penalty/h_elem * phi_neighbor_face[j][qp]*phi_neighbor_face[i][qp];
440 }
441 }
442
443 // Kne Matrix. Integrate the neighbor test function i
444 // against the element test function j
445 for (unsigned int i=0; i<n_neighbor_dofs; i++)
446 {
447 for (unsigned int j=0; j<n_dofs; j++)
448 {
449 // consistency
450 Kne(i,j) +=
451 0.5 * JxW_face[qp] *
452 (phi_neighbor_face[i][qp]*(qface_normals[qp]*dphi_face[j][qp]) -
453 phi_face[j][qp]*(qface_normals[qp]*dphi_neighbor_face[i][qp]));
454
455 // stability
456 Kne(i,j) -= JxW_face[qp] * penalty/h_elem * phi_face[j][qp]*phi_neighbor_face[i][qp];
457 }
458 }
459
460 // Ken Matrix. Integrate the element test function i
461 // against the neighbor test function j
462 for (unsigned int i=0; i<n_dofs; i++)
463 {
464 for (unsigned int j=0; j<n_neighbor_dofs; j++)
465 {
466 // consistency
467 Ken(i,j) +=
468 0.5 * JxW_face[qp] *
469 (phi_neighbor_face[j][qp]*(qface_normals[qp]*dphi_face[i][qp]) -
470 phi_face[i][qp]*(qface_normals[qp]*dphi_neighbor_face[j][qp]));
471
472 // stability
473 Ken(i,j) -= JxW_face[qp] * penalty/h_elem * phi_face[i][qp]*phi_neighbor_face[j][qp];
474 }
475 }
476 }
477
478 // The element and neighbor boundary matrix are now built
479 // for this side. Add them to the global matrix
480 // The SparseMatrix::add_matrix() members do this for us.
481 matrix.add_matrix(Kne, neighbor_dof_indices, dof_indices);
482 matrix.add_matrix(Ken, dof_indices, neighbor_dof_indices);
483 matrix.add_matrix(Kee, dof_indices);
484 matrix.add_matrix(Knn, neighbor_dof_indices);
485 }
486 }
487 }
488 // The element interior matrix and right-hand-side are now built
489 // for this element. Add them to the global matrix and
490 // right-hand-side vector. The SparseMatrix::add_matrix()
491 // and NumericVector::add_vector() members do this for us.
492 matrix.add_matrix(Ke, dof_indices);
493 ellipticdg_system.rhs->add_vector(Fe, dof_indices);
494 }
495
496 libMesh::out << "done" << std::endl;
497}
498
499
500
501int main (int argc, char** argv)
502{
503 LibMeshInit init(argc, argv);
504
505 // This example requires a linear solver package.
506 libmesh_example_requires(libMesh::default_solver_package() != INVALID_SOLVER_PACKAGE,
507 "--enable-petsc, --enable-trilinos, or --enable-eigen");
508
509 // Skip adaptive examples on a non-adaptive libMesh build
510#ifndef LIBMESH_ENABLE_AMR
511 libmesh_example_requires(false, "--enable-amr");
512#else
513
514 //Parse the input file
515 GetPot input_file("miscellaneous_ex5.in");
516
517 // But allow the command line to override it.
518 input_file.parse_command_line(argc, argv);
519
520 //Read in parameters from the input file
521 const unsigned int adaptive_refinement_steps = input_file("max_adaptive_r_steps", 3);
522 const unsigned int uniform_refinement_steps = input_file("uniform_h_r_steps", 3);
523 const Real refine_fraction = input_file("refine_fraction", 0.5);
524 const Real coarsen_fraction = input_file("coarsen_fraction", 0.);
525 const unsigned int max_h_level = input_file("max_h_level", 10);
526 const std::string refinement_type = input_file("refinement_type","p");
527 Order p_order = static_cast<Order>(input_file("p_order", 1));
528 const std::string element_type = input_file("element_type", "tensor");
529 const Real penalty = input_file("ip_penalty", 10.);
530 const bool singularity = input_file("singularity", true);
531 const unsigned int dim = input_file("dimension", 3);
532 const std::string fe_family = input_file("fe_family", "MONOMIAL");
533
534 // Skip higher-dimensional examples on a lower-dimensional libMesh build
535 libmesh_example_requires(dim <= LIBMESH_DIM, "2D/3D support");
536
537
538 // Create a mesh, with dimension to be overridden later, distributed
539 // across the default MPI communicator.
540 Mesh mesh(init.comm());
541
542 if (dim == 1)
544 else if (dim == 2)
545 mesh.read("lshaped.xda");
546 else
547 mesh.read ("lshaped3D.xda");
548
549 // Use triangles if the config file says so
550 if (element_type == "simplex")
552
553 // Mesh Refinement object
554 MeshRefinement mesh_refinement(mesh);
555 mesh_refinement.refine_fraction() = refine_fraction;
556 mesh_refinement.coarsen_fraction() = coarsen_fraction;
557 mesh_refinement.max_h_level() = max_h_level;
558
559 // Do uniform refinement
560 for (unsigned int rstep=0; rstep<uniform_refinement_steps; rstep++)
561 mesh_refinement.uniformly_refine(1);
562
563 // Create an equation system object
564 EquationSystems equation_system (mesh);
565
566 // Set parameters for the equation system and the solver
567 equation_system.parameters.set<Real>("linear solver tolerance") = TOLERANCE * TOLERANCE;
568 equation_system.parameters.set<unsigned int>("linear solver maximum iterations") = 1000;
569 equation_system.parameters.set<Real>("penalty") = penalty;
570 equation_system.parameters.set<bool>("singularity") = singularity;
571 equation_system.parameters.set<std::string>("refinement") = refinement_type;
572
573 // Create a system named ellipticdg
574 LinearImplicitSystem & ellipticdg_system = equation_system.add_system<LinearImplicitSystem> ("EllipticDG");
575
576 // Add a variable "u" to "ellipticdg" using the p_order specified in the config file
577 ellipticdg_system.add_variable ("u", p_order, Utility::string_to_enum<FEFamily>(fe_family));
578
579 // Give the system a pointer to the matrix assembly function
580 ellipticdg_system.attach_assemble_function (assemble_ellipticdg);
581
582 // Initialize the data structures for the equation system
583 equation_system.init();
584
585 // Construct ExactSolution object and attach solution functions
586 ExactSolution exact_sol(equation_system);
589
590 // A refinement loop.
591 for (unsigned int rstep=0; rstep<adaptive_refinement_steps; ++rstep)
592 {
593 libMesh::out << " Beginning Solve " << rstep << std::endl;
594 libMesh::out << "Number of elements: " << mesh.n_elem() << std::endl;
595
596 // Solve the system
597 ellipticdg_system.solve();
598
599 libMesh::out << "System has: "
600 << equation_system.n_active_dofs()
601 << " degrees of freedom."
602 << std::endl;
603
604 libMesh::out << "Linear solver converged at step: "
605 << ellipticdg_system.n_linear_iterations()
606 << ", final residual: "
607 << ellipticdg_system.final_linear_residual()
608 << std::endl;
609
610 // Compute the error
611 exact_sol.compute_error("EllipticDG", "u");
612
613 // Print out the error values
614 libMesh::out << "L2-Error is: "
615 << exact_sol.l2_error("EllipticDG", "u")
616 << std::endl;
617
618 // Possibly refine the mesh
619 if (rstep+1 < adaptive_refinement_steps)
620 {
621 // The ErrorVector is a particular StatisticsVector
622 // for computing error information on a finite element mesh.
623 ErrorVector error;
624
625 // The discontinuity error estimator
626 // evaluate the jump of the solution
627 // on elements faces
628 DiscontinuityMeasure error_estimator;
629 error_estimator.estimate_error(ellipticdg_system,error);
630
631 // Take the error in error and decide which elements will be coarsened or refined
632 mesh_refinement.flag_elements_by_error_fraction(error);
633 if (refinement_type == "p")
634 mesh_refinement.switch_h_to_p_refinement();
635 if (refinement_type == "hp")
636 mesh_refinement.add_p_to_h_refinement();
637
638 // Refine and coarsen the flagged elements
639 mesh_refinement.refine_and_coarsen_elements();
640 equation_system.reinit();
641 }
642 }
643
644 // Write out the solution
645 // After solving the system write the solution
646 // to a ExodusII-formatted plot file.
647#ifdef LIBMESH_HAVE_EXODUS_API
648 ExodusII_IO (mesh).write_discontinuous_exodusII("lshaped_dg.e", equation_system);
649#endif
650
651#endif // #ifndef LIBMESH_ENABLE_AMR
652
653 // All done.
654 return 0;
655}
bool singularity
unsigned int dim
Gradient(* exact_derivative)(const Point &p, const Parameters &, const std::string &, const std::string &)
Number(* exact_solution)(const Point &p, const Parameters &, const std::string &, const std::string &)
BasicOStreamProxy & flush()
Flush the associated stream buffer.
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 measures discontinuities between elements for debugging purposes.
This class handles the numbering of degrees of freedom on a mesh.
Definition dof_map.h:181
dof_id_type id() const
Definition dof_object.h:819
Helper for building element sides that minimizes the construction of new elements.
This is the base class from which all geometric element types are derived.
Definition elem.h:96
bool active() const
Definition elem.h:2958
unsigned int which_neighbor_am_i(const Elem *e) const
This function tells you which neighbor e is.
Definition elem.h:2936
unsigned int level() const
Definition elem.h:3091
virtual Real volume() const
Definition elem.C:3462
const Elem * neighbor_ptr(unsigned int i) const
Definition elem.h:2615
This is the EquationSystems class.
virtual void reinit()
Handle any mesh changes and reinitialize all the systems on the updated mesh.
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...
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)
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 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...
Definition exodusII_io.h:53
void write_discontinuous_exodusII(const std::string &name, const EquationSystems &es, const std::set< std::string > *system_names=nullptr)
Writes a exodusII file with discontinuous data.
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.
static Point inverse_map(const unsigned int dim, const Elem *elem, const Point &p, const Real tolerance=TOLERANCE, const bool secure=true, const bool extra_checks=true)
Definition fe_map.C:1512
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Definition fe_type.h:197
Order default_quadrature_order() const
Definition fe_type.h:415
const SparseMatrix< Number > & get_system_matrix() const
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...
The LibMeshInit class, when constructed, initializes the dependent libraries (e.g.
Definition libmesh.h:92
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 dof_id_type n_elem() const =0
virtual void read(const std::string &name, void *mesh_data=nullptr, bool skip_renumber_nodes_and_elements=false, bool skip_find_neighbors=false, bool skip_detect_interior_parents=false)=0
Interfaces for reading/writing a mesh to/from a file.
Implements (adaptive) mesh refinement algorithms for a MeshBase.
void uniformly_refine(unsigned int n=1)
Uniformly refines the mesh n times.
void switch_h_to_p_refinement()
Takes a mesh whose elements are flagged for h refinement and coarsening, and switches those flags to ...
void flag_elements_by_error_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.
void add_p_to_h_refinement()
Takes a mesh whose elements are flagged for h refinement and coarsening, and adds flags to request p ...
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.
Definition mesh.h:51
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...
Definition parameters.h:75
T & set(const std::string &)
Definition parameters.h:494
const T & get(std::string_view) const
Definition parameters.h:451
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition point.h:40
const std::vector< Point > & get_points() const
Definition quadrature.h:156
unsigned int n_points() const
Definition quadrature.h:131
This class implements specific orders of Gauss quadrature.
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 FEType & variable_type(const unsigned int i) const
Definition system.C:2721
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
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 assemble_ellipticdg(EquationSystems &es, const std::string &libmesh_dbg_var(system_name))
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 all_tri(MeshBase &mesh)
Subdivides any non-simplex elements in a Mesh to produce simplex (triangular in 2D,...
The libMesh namespace provides an interface to certain functionality in the library.
SolverPackage default_solver_package()
Definition libmesh.C:1064
OStreamProxy out
const Real pi
.
Definition libmesh.h:292
static constexpr Real TOLERANCE
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
int main()