libMesh
Loading...
Searching...
No Matches
Functions
miscellaneous_ex5.C File Reference

Go to the source code of this file.

Functions

Number exact_solution (const Point &p, const Parameters &parameters, const std::string &, const std::string &)
 
Gradient exact_derivative (const Point &p, const Parameters &parameters, const std::string &, const std::string &)
 
void assemble_ellipticdg (EquationSystems &es, const std::string &libmesh_dbg_var(system_name))
 
int main (int argc, char **argv)
 

Function Documentation

◆ assemble_ellipticdg()

void assemble_ellipticdg ( EquationSystems es,
const std::string &  libmesh_dbg_varsystem_name 
)

Definition at line 141 of file miscellaneous_ex5.C.

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}
unsigned int dim
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 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
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.
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
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].
const T & get(std::string_view) const
Definition parameters.h:451
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
const DofMap & get_dof_map() const
Definition system.h:2417
MeshBase & mesh
T pow(const T &x)
Definition utility.h:296
OStreamProxy out
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real

References libMesh::Elem::active(), libMesh::SparseMatrix< T >::add_matrix(), libMesh::NumericVector< T >::add_vector(), libMesh::FEGenericBase< OutputType >::build(), libMesh::FEType::default_quadrature_order(), dim, exact_solution, libMesh::BasicOStreamProxy< charT, traits >::flush(), libMesh::Parameters::get(), libMesh::System::get_dof_map(), libMesh::EquationSystems::get_mesh(), libMesh::QBase::get_points(), libMesh::EquationSystems::get_system(), libMesh::ImplicitSystem::get_system_matrix(), libMesh::DofObject::id(), libMesh::FEMap::inverse_map(), libMesh::Elem::level(), mesh, libMesh::MeshBase::mesh_dimension(), libMesh::QBase::n_points(), libMesh::Elem::neighbor_ptr(), libMesh::out, libMesh::EquationSystems::parameters, libMesh::Real, libMesh::DenseVector< T >::resize(), libMesh::DenseMatrix< T >::resize(), libMesh::ExplicitSystem::rhs, libMesh::System::variable_type(), libMesh::Elem::volume(), and libMesh::Elem::which_neighbor_am_i().

Referenced by main().

◆ exact_derivative()

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

Definition at line 90 of file miscellaneous_ex5.C.

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}
This class defines a vector in LIBMESH_DIM dimensional Real or Complex space.
const Real pi
.
Definition libmesh.h:292

References libMesh::Parameters::get(), libMesh::pi, and libMesh::Real.

◆ exact_solution()

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

Definition at line 63 of file miscellaneous_ex5.C.

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}

References libMesh::Parameters::get(), libMesh::pi, and libMesh::Real.

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 501 of file miscellaneous_ex5.C.

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);
587 exact_sol.attach_exact_value(exact_solution);
588 exact_sol.attach_exact_deriv(exact_derivative);
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
Gradient(* exact_derivative)(const Point &p, const Parameters &, const std::string &, const std::string &)
This class measures discontinuities between elements for debugging purposes.
This is the EquationSystems class.
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...
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.
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
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.
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
Definition mesh.h:51
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
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,...
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
SolverPackage default_solver_package()
Definition libmesh.C:1064
static constexpr Real TOLERANCE

References libMesh::MeshRefinement::add_p_to_h_refinement(), libMesh::EquationSystems::add_system(), libMesh::System::add_variable(), libMesh::MeshTools::Modification::all_tri(), assemble_ellipticdg(), libMesh::ExactSolution::attach_exact_deriv(), libMesh::ExactSolution::attach_exact_value(), libMesh::MeshTools::Generation::build_line(), libMesh::MeshRefinement::coarsen_fraction(), libMesh::ExactSolution::compute_error(), libMesh::default_solver_package(), dim, libMesh::JumpErrorEstimator::estimate_error(), exact_derivative, exact_solution, libMesh::MeshRefinement::flag_elements_by_error_fraction(), libMesh::EquationSystems::init(), libMesh::INVALID_SOLVER_PACKAGE, libMesh::ExactSolution::l2_error(), main(), libMesh::MeshRefinement::max_h_level(), mesh, libMesh::EquationSystems::n_active_dofs(), libMesh::MeshBase::n_elem(), libMesh::out, libMesh::EquationSystems::parameters, libMesh::MeshBase::read(), libMesh::Real, libMesh::MeshRefinement::refine_and_coarsen_elements(), libMesh::MeshRefinement::refine_fraction(), libMesh::EquationSystems::reinit(), libMesh::Parameters::set(), singularity, libMesh::MeshRefinement::switch_h_to_p_refinement(), libMesh::TOLERANCE, libMesh::MeshRefinement::uniformly_refine(), and libMesh::ExodusII_IO::write_discontinuous_exodusII().