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 77 of file miscellaneous_ex3.C.

Constructor & Destructor Documentation

◆ LaplaceYoung()

LaplaceYoung::LaplaceYoung ( )
inline

Definition at line 83 of file miscellaneous_ex3.C.

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

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 455 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(), libMesh::DenseMatrix< T >::resize(), and std::sqrt().

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

◆ 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 583 of file miscellaneous_ex3.C.

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

589 {
590  // Back up along the search direction by some amount. Since Newton
591  // already works well for this problem, the only affect of this is
592  // to degrade the rate of convergence.
593  //
594  // The minus sign is due to the sign of the "search_direction"
595  // vector which comes in from the Newton solve. The RHS of the
596  // nonlinear system, i.e. the residual, is generally not multiplied
597  // by -1, so the solution vector, i.e. the search_direction, has a
598  // factor -1.
599  if (_gamma != 1.0)
600  {
601  new_soln = old_soln;
602  new_soln.add(-_gamma, search_direction);
603  changed_new_soln = true;
604  }
605  else
606  changed_new_soln = false;
607 }
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 285 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(), std::sqrt(), and libMesh::NumericVector< T >::zero().

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

◆ 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 128 of file miscellaneous_ex3.C.

◆ _kappa

Real LaplaceYoung::_kappa
private

Definition at line 124 of file miscellaneous_ex3.C.

◆ _sigma

Real LaplaceYoung::_sigma
private

Definition at line 125 of file miscellaneous_ex3.C.


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