libMesh
Public Member Functions | Private Attributes | List of all members
LaplaceYoung Class Referenceabstract

A class which provides the residual and jacobian assembly functions for the Laplace-Young system of equations. More...

Inheritance diagram for LaplaceYoung:
[legend]

Public Member Functions

 LaplaceYoung ()
 
virtual void residual (const NumericVector< Number > &X, NumericVector< Number > &R, NonlinearImplicitSystem &S)
 Function which computes the residual. More...
 
virtual void jacobian (const NumericVector< Number > &X, SparseMatrix< Number > &J, NonlinearImplicitSystem &S)
 Function which computes the jacobian. More...
 
virtual void postcheck (const NumericVector< Number > &old_soln, NumericVector< Number > &search_direction, NumericVector< Number > &new_soln, bool &changed_search_direction, bool &changed_new_soln, NonlinearImplicitSystem &S)
 Function which performs a postcheck on the solution. More...
 
virtual void residual (const NumericVector< Number > &X, NumericVector< Number > &R, sys_type &S)=0
 Residual function. More...
 
virtual void jacobian (const NumericVector< Number > &X, SparseMatrix< Number > &J, sys_type &S)=0
 Jacobian function. More...
 
virtual void postcheck (const NumericVector< Number > &old_soln, NumericVector< Number > &search_direction, NumericVector< Number > &new_soln, bool &changed_search_direction, bool &changed_new_soln, sys_type &S)=0
 This interface, which is inspired by PETSc's, passes the user: .) A constant reference to the "old" solution vector (previous Newton iterate), .) A pointer to the search direction (update) vector, and .) The "proposed" new solution vector. More...
 

Private Attributes

Real _kappa
 
Real _sigma
 
Real _gamma
 

Detailed Description

A class which provides the residual and jacobian assembly functions for the Laplace-Young system of equations.

Definition at line 78 of file miscellaneous_ex3.C.

Constructor & Destructor Documentation

◆ LaplaceYoung()

LaplaceYoung::LaplaceYoung ( )
inline

Definition at line 84 of file miscellaneous_ex3.C.

84  :
85  _kappa(1.),
86  _sigma(0.2),
87  _gamma(1.0)
88  {}

Member Function Documentation

◆ jacobian() [1/2]

void LaplaceYoung::jacobian ( const NumericVector< Number > &  X,
SparseMatrix< Number > &  J,
NonlinearImplicitSystem S 
)
virtual

Function which computes the jacobian.

Definition at line 456 of file miscellaneous_ex3.C.

References libMesh::SparseMatrix< T >::add_matrix(), libMesh::FEGenericBase< OutputType >::build(), dim, libMesh::FIFTH, libMesh::System::get_dof_map(), libMesh::System::get_equation_systems(), libMesh::EquationSystems::get_mesh(), libMesh::EquationSystems::get_system(), mesh, libMesh::MeshBase::mesh_dimension(), libMesh::QBase::n_points(), and libMesh::DenseMatrix< T >::resize().

459 {
460  // Get a reference to the equation system.
461  EquationSystems & es = sys.get_equation_systems();
462 
463  // Get a constant reference to the mesh object.
464  const MeshBase & mesh = es.get_mesh();
465 
466  // The dimension that we are running
467  const unsigned int dim = mesh.mesh_dimension();
468 
469  // Get a reference to the NonlinearImplicitSystem we are solving
470  NonlinearImplicitSystem & system =
471  es.get_system<NonlinearImplicitSystem>("Laplace-Young");
472 
473  // A reference to the DofMap object for this system. The DofMap
474  // object handles the index translation from node and element numbers
475  // to degree of freedom numbers. We will talk more about the DofMap
476  // in future examples.
477  const DofMap & dof_map = system.get_dof_map();
478 
479  // Get a constant reference to the Finite Element type
480  // for the first (and only) variable in the system.
481  FEType fe_type = dof_map.variable_type(0);
482 
483  // Build a Finite Element object of the specified type. Since the
484  // FEBase::build() member dynamically creates memory we will
485  // store the object as a std::unique_ptr<FEBase>. This can be thought
486  // of as a pointer that will clean up after itself.
487  std::unique_ptr<FEBase> fe (FEBase::build(dim, fe_type));
488 
489  // A 5th order Gauss quadrature rule for numerical integration.
490  QGauss qrule (dim, FIFTH);
491 
492  // Tell the finite element object to use our quadrature rule.
493  fe->attach_quadrature_rule (&qrule);
494 
495  // Here we define some references to cell-specific data that
496  // will be used to assemble the linear system.
497  // We begin with the element Jacobian * quadrature weight at each
498  // integration point.
499  const std::vector<Real> & JxW = fe->get_JxW();
500 
501  // The element shape functions evaluated at the quadrature points.
502  const std::vector<std::vector<Real>> & phi = fe->get_phi();
503 
504  // The element shape function gradients evaluated at the quadrature
505  // points.
506  const std::vector<std::vector<RealGradient>> & dphi = fe->get_dphi();
507 
508  // Define data structures to contain the Jacobian element matrix.
509  // Following basic finite element terminology we will denote these
510  // "Ke". More detail is in example 3.
512 
513  // This vector will hold the degree of freedom indices for
514  // the element. These define where in the global system
515  // the element degrees of freedom get mapped.
516  std::vector<dof_id_type> dof_indices;
517 
518  // Now we will loop over all the active elements in the mesh which
519  // are local to this processor.
520  // We will compute the element Jacobian contribution.
521  for (const auto & elem : mesh.active_local_element_ptr_range())
522  {
523  // Get the degree of freedom indices for the
524  // current element. These define where in the global
525  // matrix and right-hand-side this element will
526  // contribute to.
527  dof_map.dof_indices (elem, dof_indices);
528 
529  // Compute the element-specific data for the current
530  // element. This involves computing the location of the
531  // quadrature points (q_point) and the shape functions
532  // (phi, dphi) for the current element.
533  fe->reinit (elem);
534 
535  // Zero the element Jacobian before
536  // summing them. We use the resize member here because
537  // the number of degrees of freedom might have changed from
538  // the last element. Note that this will be the case if the
539  // element type is different (i.e. the last element was a
540  // triangle, now we are on a quadrilateral).
541  const unsigned int n_dofs =
542  cast_int<unsigned int>(dof_indices.size());
543  Ke.resize (n_dofs, n_dofs);
544 
545  // Now we will build the element Jacobian. This involves
546  // a double loop to integrate the test functions (i) against
547  // the trial functions (j). Note that the Jacobian depends
548  // on the current solution x, which we access using the soln
549  // vector.
550  //
551  for (unsigned int qp=0; qp<qrule.n_points(); qp++)
552  {
553  Gradient grad_u;
554 
555  for (unsigned int i=0; i<n_dofs; i++)
556  grad_u += dphi[i][qp]*soln(dof_indices[i]);
557 
558  const Number
559  sa = 1. + grad_u*grad_u,
560  K = 1. / std::sqrt(sa),
561  dK = -K / sa;
562 
563  for (unsigned int i=0; i<n_dofs; i++)
564  for (unsigned int j=0; j<n_dofs; j++)
565  Ke(i,j) += JxW[qp]*(
566  K * (dphi[i][qp]*dphi[j][qp]) +
567  dK * (grad_u*dphi[j][qp]) * (grad_u*dphi[i][qp]) +
568  _kappa * phi[i][qp] * phi[j][qp]
569  );
570  }
571 
572  dof_map.constrain_element_matrix (Ke, dof_indices);
573 
574  // Add the element matrix to the system Jacobian.
575  jacobian.add_matrix (Ke, dof_indices);
576  }
577 
578  // That's it.
579 }
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Definition: fe_type.h:196
This is the EquationSystems class.
unsigned int dim
MeshBase & mesh
This class defines a vector in LIBMESH_DIM dimensional Real or Complex space.
const T_sys & get_system(std::string_view name) const
This is the MeshBase class.
Definition: mesh_base.h:75
This class handles the numbering of degrees of freedom on a mesh.
Definition: dof_map.h:179
Manages consistently variables, degrees of freedom, coefficient vectors, matrices and non-linear solv...
virtual void jacobian(const NumericVector< Number > &X, SparseMatrix< Number > &J, NonlinearImplicitSystem &S)
Function which computes the jacobian.
const MeshBase & get_mesh() const
void resize(const unsigned int new_m, const unsigned int new_n)
Resizes the matrix to the specified size and calls zero().
Definition: dense_matrix.h:895
This class implements specific orders of Gauss quadrature.
unsigned int mesh_dimension() const
Definition: mesh_base.C:372
const DofMap & get_dof_map() const
Definition: system.h:2374

◆ jacobian() [2/2]

virtual void libMesh::NonlinearImplicitSystem::ComputeJacobian::jacobian ( const NumericVector< Number > &  X,
SparseMatrix< Number > &  J,
sys_type S 
)
pure virtualinherited

Jacobian function.

This function will be called to compute the jacobian and must be implemented by the user in a derived class.

Referenced by libMesh::Problem_Interface::computeJacobian(), libMesh::Problem_Interface::computePreconditioner(), and libMesh::libmesh_petsc_snes_jacobian().

◆ postcheck() [1/2]

void LaplaceYoung::postcheck ( const NumericVector< Number > &  old_soln,
NumericVector< Number > &  search_direction,
NumericVector< Number > &  new_soln,
bool &  changed_search_direction,
bool &  changed_new_soln,
NonlinearImplicitSystem S 
)
virtual

Function which performs a postcheck on the solution.

In this example, we take a "damped" Newton step defined by:

u_new = u_old + gamma*delta_u

where delta_u is the search direction, and 0 < gamma <= 1 is a damping parameter. gamma=1 corresponds to a full Newton step.

This is really for demonstration purposes only, as it just degrades the rate of nonlinear convergence in this particular example.

Definition at line 584 of file miscellaneous_ex3.C.

References libMesh::NumericVector< T >::add().

590 {
591  // Back up along the search direction by some amount. Since Newton
592  // already works well for this problem, the only affect of this is
593  // to degrade the rate of convergence.
594  //
595  // The minus sign is due to the sign of the "search_direction"
596  // vector which comes in from the Newton solve. The RHS of the
597  // nonlinear system, i.e. the residual, is generally not multiplied
598  // by -1, so the solution vector, i.e. the search_direction, has a
599  // factor -1.
600  if (_gamma != 1.0)
601  {
602  new_soln = old_soln;
603  new_soln.add(-_gamma, search_direction);
604  changed_new_soln = true;
605  }
606  else
607  changed_new_soln = false;
608 }
virtual void add(const numeric_index_type i, const T value)=0
Adds value to the vector entry specified by i.

◆ postcheck() [2/2]

virtual void libMesh::NonlinearImplicitSystem::ComputePostCheck::postcheck ( const NumericVector< Number > &  old_soln,
NumericVector< Number > &  search_direction,
NumericVector< Number > &  new_soln,
bool &  changed_search_direction,
bool &  changed_new_soln,
sys_type S 
)
pure virtualinherited

This interface, which is inspired by PETSc's, passes the user: .) A constant reference to the "old" solution vector (previous Newton iterate), .) A pointer to the search direction (update) vector, and .) The "proposed" new solution vector.

The user can then modify either the search direction or the new solution vector according to their own application-specific criteria. If they do, they must set the associated boolean references appropriately.

Referenced by libMesh::libmesh_petsc_snes_postcheck().

◆ residual() [1/2]

void LaplaceYoung::residual ( const NumericVector< Number > &  X,
NumericVector< Number > &  R,
NonlinearImplicitSystem S 
)
virtual

Function which computes the residual.

Definition at line 286 of file miscellaneous_ex3.C.

References libMesh::NumericVector< T >::add_vector(), libMesh::FEGenericBase< OutputType >::build(), dim, libMesh::FIFTH, libMesh::System::get_dof_map(), libMesh::System::get_equation_systems(), libMesh::EquationSystems::get_mesh(), libMesh::EquationSystems::get_system(), mesh, libMesh::MeshBase::mesh_dimension(), libMesh::QBase::n_points(), libMesh::DenseVector< T >::resize(), and libMesh::NumericVector< T >::zero().

289 {
290  EquationSystems & es = sys.get_equation_systems();
291 
292  // Get a constant reference to the mesh object.
293  const MeshBase & mesh = es.get_mesh();
294 
295  // The dimension that we are running
296  const unsigned int dim = mesh.mesh_dimension();
297  libmesh_assert_equal_to (dim, 2);
298 
299  // Get a reference to the NonlinearImplicitSystem we are solving
300  NonlinearImplicitSystem & system =
301  es.get_system<NonlinearImplicitSystem>("Laplace-Young");
302 
303  // A reference to the DofMap object for this system. The DofMap
304  // object handles the index translation from node and element numbers
305  // to degree of freedom numbers. We will talk more about the DofMap
306  // in future examples.
307  const DofMap & dof_map = system.get_dof_map();
308 
309  // Get a constant reference to the Finite Element type
310  // for the first (and only) variable in the system.
311  FEType fe_type = dof_map.variable_type(0);
312 
313  // Build a Finite Element object of the specified type. Since the
314  // FEBase::build() member dynamically creates memory we will
315  // store the object as a std::unique_ptr<FEBase>. This can be thought
316  // of as a pointer that will clean up after itself.
317  std::unique_ptr<FEBase> fe (FEBase::build(dim, fe_type));
318 
319  // A 5th order Gauss quadrature rule for numerical integration.
320  QGauss qrule (dim, FIFTH);
321 
322  // Tell the finite element object to use our quadrature rule.
323  fe->attach_quadrature_rule (&qrule);
324 
325  // Declare a special finite element object for
326  // boundary integration.
327  std::unique_ptr<FEBase> fe_face (FEBase::build(dim, fe_type));
328 
329  // Boundary integration requires one quadrature rule,
330  // with dimensionality one less than the dimensionality
331  // of the element.
332  QGauss qface(dim-1, FIFTH);
333 
334  // Tell the finite element object to use our
335  // quadrature rule.
336  fe_face->attach_quadrature_rule (&qface);
337 
338  // Here we define some references to cell-specific data that
339  // will be used to assemble the linear system.
340  // We begin with the element Jacobian * quadrature weight at each
341  // integration point.
342  const std::vector<Real> & JxW = fe->get_JxW();
343 
344  // The element shape functions evaluated at the quadrature points.
345  const std::vector<std::vector<Real>> & phi = fe->get_phi();
346 
347  // The element shape function gradients evaluated at the quadrature
348  // points.
349  const std::vector<std::vector<RealGradient>> & dphi = fe->get_dphi();
350 
351  // Define data structures to contain the residual contributions
353 
354  // This vector will hold the degree of freedom indices for
355  // the element. These define where in the global system
356  // the element degrees of freedom get mapped.
357  std::vector<dof_id_type> dof_indices;
358 
359  // Now we will loop over all the active elements in the mesh which
360  // are local to this processor.
361  // We will compute the element residual.
362  residual.zero();
363 
364  for (const auto & elem : mesh.active_local_element_ptr_range())
365  {
366  // Get the degree of freedom indices for the
367  // current element. These define where in the global
368  // matrix and right-hand-side this element will
369  // contribute to.
370  dof_map.dof_indices (elem, dof_indices);
371 
372  // Compute the element-specific data for the current
373  // element. This involves computing the location of the
374  // quadrature points (q_point) and the shape functions
375  // (phi, dphi) for the current element.
376  fe->reinit (elem);
377 
378  // We use the resize member here because
379  // the number of degrees of freedom might have changed from
380  // the last element. Note that this will be the case if the
381  // element type is different (i.e. the last element was a
382  // triangle, now we are on a quadrilateral).
383  const unsigned int n_dofs =
384  cast_int<unsigned int>(dof_indices.size());
385  Re.resize (n_dofs);
386 
387  // Now we will build the residual. This involves
388  // the construction of the matrix K and multiplication of it
389  // with the current solution x. We rearrange this into two loops:
390  // In the first, we calculate only the contribution of
391  // K_ij*x_j which is independent of the row i. In the second loops,
392  // we multiply with the row-dependent part and add it to the element
393  // residual.
394 
395  for (unsigned int qp=0; qp<qrule.n_points(); qp++)
396  {
397  Number u = 0;
398  Gradient grad_u;
399 
400  for (unsigned int j=0; j<n_dofs; j++)
401  {
402  u += phi[j][qp]*soln(dof_indices[j]);
403  grad_u += dphi[j][qp]*soln(dof_indices[j]);
404  }
405 
406  const Number K = 1./std::sqrt(1. + grad_u*grad_u);
407 
408  for (unsigned int i=0; i<n_dofs; i++)
409  Re(i) += JxW[qp]*(
410  K*(dphi[i][qp]*grad_u) +
411  _kappa*phi[i][qp]*u
412  );
413  }
414 
415  // At this point the interior element integration has
416  // been completed. However, we have not yet addressed
417  // boundary conditions.
418 
419  // The following loops over the sides of the element.
420  // If the element has no neighbor on a side then that
421  // side MUST live on a boundary of the domain.
422  for (auto side : elem->side_index_range())
423  if (elem->neighbor_ptr(side) == nullptr)
424  {
425  // The value of the shape functions at the quadrature
426  // points.
427  const std::vector<std::vector<Real>> & phi_face = fe_face->get_phi();
428 
429  // The Jacobian * Quadrature Weight at the quadrature
430  // points on the face.
431  const std::vector<Real> & JxW_face = fe_face->get_JxW();
432 
433  // Compute the shape function values on the element face.
434  fe_face->reinit(elem, side);
435 
436  // Loop over the face quadrature points for integration.
437  for (unsigned int qp=0; qp<qface.n_points(); qp++)
438  {
439  // This is the right-hand-side contribution (f),
440  // which has to be subtracted from the current residual
441  for (unsigned int i=0; i<n_dofs; i++)
442  Re(i) -= JxW_face[qp]*_sigma*phi_face[i][qp];
443  }
444  }
445 
446  dof_map.constrain_element_vector (Re, dof_indices);
447  residual.add_vector (Re, dof_indices);
448  }
449 
450  // That's it.
451 }
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Definition: fe_type.h:196
This is the EquationSystems class.
unsigned int dim
void resize(const unsigned int n)
Resize the vector.
Definition: dense_vector.h:396
MeshBase & mesh
This class defines a vector in LIBMESH_DIM dimensional Real or Complex space.
const T_sys & get_system(std::string_view name) const
This is the MeshBase class.
Definition: mesh_base.h:75
This class handles the numbering of degrees of freedom on a mesh.
Definition: dof_map.h:179
Manages consistently variables, degrees of freedom, coefficient vectors, matrices and non-linear solv...
const MeshBase & get_mesh() const
This class implements specific orders of Gauss quadrature.
unsigned int mesh_dimension() const
Definition: mesh_base.C:372
virtual void residual(const NumericVector< Number > &X, NumericVector< Number > &R, NonlinearImplicitSystem &S)
Function which computes the residual.
const DofMap & get_dof_map() const
Definition: system.h:2374

◆ residual() [2/2]

virtual void libMesh::NonlinearImplicitSystem::ComputeResidual::residual ( const NumericVector< Number > &  X,
NumericVector< Number > &  R,
sys_type S 
)
pure virtualinherited

Residual function.

This function will be called to compute the residual and must be implemented by the user in a derived class.

Referenced by libMesh::Problem_Interface::computeF(), libMesh::libmesh_petsc_snes_fd_residual(), libMesh::libmesh_petsc_snes_mffd_residual(), and libMesh::libmesh_petsc_snes_residual().

Member Data Documentation

◆ _gamma

Real LaplaceYoung::_gamma
private

Definition at line 129 of file miscellaneous_ex3.C.

◆ _kappa

Real LaplaceYoung::_kappa
private

Definition at line 125 of file miscellaneous_ex3.C.

◆ _sigma

Real LaplaceYoung::_sigma
private

Definition at line 126 of file miscellaneous_ex3.C.


The documentation for this class was generated from the following file: