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

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

References libMesh::MeshBase::active_local_element_ptr_range(), 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().

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

598 {
599  // Back up along the search direction by some amount. Since Newton
600  // already works well for this problem, the only affect of this is
601  // to degrade the rate of convergence.
602  //
603  // The minus sign is due to the sign of the "search_direction"
604  // vector which comes in from the Newton solve. The RHS of the
605  // nonlinear system, i.e. the residual, is generally not multiplied
606  // by -1, so the solution vector, i.e. the search_direction, has a
607  // factor -1.
608  if (_gamma != 1.0)
609  {
610  new_soln = old_soln;
611  new_soln.add(-_gamma, search_direction);
612  changed_new_soln = true;
613  }
614  else
615  changed_new_soln = false;
616 }

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

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

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

References libMesh::MeshBase::active_local_element_ptr_range(), 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().

◆ 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:
libMesh::Number
Real Number
Definition: libmesh_common.h:195
libMesh::NumericVector::add
virtual void add(const numeric_index_type i, const T value)=0
Adds value to each entry of the vector.
LaplaceYoung::residual
virtual void residual(const NumericVector< Number > &X, NumericVector< Number > &R, NonlinearImplicitSystem &S)
Function which computes the residual.
Definition: miscellaneous_ex3.C:294
libMesh::EquationSystems::get_mesh
const MeshBase & get_mesh() const
Definition: equation_systems.h:637
libMesh::QGauss
This class implements specific orders of Gauss quadrature.
Definition: quadrature_gauss.h:39
LaplaceYoung::jacobian
virtual void jacobian(const NumericVector< Number > &X, SparseMatrix< Number > &J, NonlinearImplicitSystem &S)
Function which computes the jacobian.
Definition: miscellaneous_ex3.C:464
libMesh::MeshBase::active_local_element_ptr_range
virtual SimpleRange< element_iterator > active_local_element_ptr_range()=0
libMesh::EquationSystems::get_system
const T_sys & get_system(const std::string &name) const
Definition: equation_systems.h:757
std::sqrt
MetaPhysicL::DualNumber< T, D > sqrt(const MetaPhysicL::DualNumber< T, D > &in)
libMesh::DenseMatrix< Number >
mesh
MeshBase & mesh
Definition: mesh_communication.C:1257
libMesh::MeshBase::mesh_dimension
unsigned int mesh_dimension() const
Definition: mesh_base.C:135
libMesh::FIFTH
Definition: enum_order.h:46
LaplaceYoung::_sigma
Real _sigma
Definition: miscellaneous_ex3.C:125
libMesh::NonlinearImplicitSystem
Manages consistently variables, degrees of freedom, coefficient vectors, matrices and non-linear solv...
Definition: nonlinear_implicit_system.h:54
dim
unsigned int dim
Definition: adaptivity_ex3.C:113
libMesh::DenseMatrix::resize
void resize(const unsigned int new_m, const unsigned int new_n)
Resize the matrix.
Definition: dense_matrix.h:822
libMesh::VectorValue< Number >
libMesh::MeshBase
This is the MeshBase class.
Definition: mesh_base.h:78
libMesh::EquationSystems
This is the EquationSystems class.
Definition: equation_systems.h:74
libMesh::DenseVector::resize
void resize(const unsigned int n)
Resize the vector.
Definition: dense_vector.h:355
libMesh::FEType
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Definition: fe_type.h:178
libMesh::DofMap
This class handles the numbering of degrees of freedom on a mesh.
Definition: dof_map.h:176
LaplaceYoung::_kappa
Real _kappa
Definition: miscellaneous_ex3.C:124
LaplaceYoung::_gamma
Real _gamma
Definition: miscellaneous_ex3.C:128
libMesh::System::get_dof_map
const DofMap & get_dof_map() const
Definition: system.h:2099
libMesh::DenseVector< Number >