VCP

Varialble condensation preconditioner (VCP) condenses out specified variable(s) from the Jacobian matrix and produces a system of equations with less unkowns to be solved by the underlying preconditioners.

Overview

The Variable Condensation Preconditioner (VCP) is designed to condense out variables from the linear system of equations and apply the preconditioner/solver on the reduced simplified system of equations. The development of VCP is motivated by the need to enable a broader range of robust and scalable preconditioners for problems that have a saddle point type of Jacobian. The saddle point type of Jacobian may come from different applications. One typical example is the enforcement of constraints using Lagrange multipliers. Its special numerical character prevents the usage of many scalable iterative solvers. To resolve this issue, a static condensation step is carried out in VCP to remove the Degree of Freedoms (DoFs) that are associated with the Lagrange multipliers. This may result in an easy-to-solve system (sometimes it is positive definite ) which can be handled by a broader range of solvers/preconditioners with improved efficiency. With VCP, we can efficiently apply iterative solvers, e.g., BoomerAMG, to mortar-based mechanical contact problems.

System Simplification

To illustrate the saddle point structure of the Jacobian matrix and how it can be simplified by static condensation of the Lagrange multiplier, we take the Jacobian matrix from a simple diffusion problem with equal value constraint as an example. The system of equations at a typical time step can be written as a block matrix as follows, (1) Here, we omit the identifier of time for simplicity. The first subscript and denote the primary and secondary subdomains, respectively. The second subscript denotes the part of the subdomain that is in contact and denotes the rest of the subdomain. The blocks denote the respective stiffness matrices. The block represents the coupling between the Lagrange multipliers and the primal variable in the secondary subdomain. The block denotes the coupling between the Lagrange multipliers and the primal variable in the primary subdomain.

The system of equations from mortar-based mechanical contact has a similar saddle point character, but is more complex than Eq. (1), considering the primary and secondary surfaces being partially in contact. For readers who are interested in the Jacobian matrix from mortar-based mechanical contact, please refer to (Popp et al., 2010).

Condensation of the Lagrange Multiplier

The discrete Lagrange multipliers (i.e., ) can be eliminated by condensation as follows, (2)

By substituting Eq. (2) into Eq. (1), we obtain a simplified linear system of equations that contains only the primal variable DOFs,

(3) This condensed system (i.e., Eq. (3)) is positive definite and therefore state-of-art iterative solution techniques, such as multigrid methods, are applicable. As a post-processing step, the Lagrange multipliers can be recovered from the displacement following Eq. (2).

Dual Basis Function

The computation of in Eq. (2) and Eq. (3) can be reduced by using dual basis for the Lagrange multipliers. The dual basis is a relative definition to the standard basis, which satisfies a biorthogonal condition as follows (4) where is the standard shape function, is the dual shape function, and is the Kronecker delta function. This biorthogonal condition can be assumed to hold in every lower-dimensional element . Owing to the biorthogonality property of the dual basis functions, the integral matrix become strict diagonal. Thus computation of and condensation steps in Eq. (2) and Eq. (3) become trivial.

commentnote:Use of dual basis is optional but recommended

In order to reduce the computational cost brought by the condensation steps (see Eq. (2) and Eq. (3)), we recommend the usage of dual basis function for the Lagrange multipliers. Meanwhile, we suggest setting the option is_lm_coupling_diagonal = true in the preconditioning block to let VCP take the diagonal structure of the couple matrix () into account for improved efficiency. If D is not diagonal, but the number of multiplier DoFs is small, VCP will be still beneficial. It may be expensive to compute non-diagonal D when the number of multiplier DOFs is large.

One can enable the usage of dual basis by enabling use_dual = true in the Variables block:


[Variables]
 [./lm]
   order = FIRST
   family = LAGRANGE
   use_dual = true
 [../]
[]

Or, for mortar-based contact problems, the dual basis function is used by default for the Lagrange multipliers (while using the contact action). An example input block for contact action is as follows:

[Contact]
  [frictionless]
    primary = plank_right
    secondary = block_left
    formulation = mortar
    c_normal = 1e0
  []
[]
(moose/modules/contact/test/tests/mortar_tm/2d/frictionless_first/small.i)

VCP Workflow

A schematic is included in Figure 1 to demonstrate the solution process of VCP. Compared to the standard precondition and solve procedure, VCP features two additional customized computation steps (i.e., one to condense out the variable and the other to obtain the full solution vector) (see Figure 1). During static condensation of the variable (e.g., ), the DoFs are obtained for both the variable itself () and its coupled variable (). Based on this information, the coupling matrices (i.e., and ) will be extracted from the original Jacobian matrix. Then a reduced system of equations will be obtained with the necessary submatrix operations following Eq. (3). After solving the reduced system of equations, we obtain the primal variable solution vector, which is then utilized to update the variable (see Eq. (2)) and assemble the full solution vector.

Figure 1: The variable condensation preconditioner (VCP) workflow. Blue represents the original preconditioning steps. Orange shows the additional steps customized for VCP.

Special Designs in VCP

Several special designs in VCP foster improved performance:

  • Adaptive variable condensation The idea is to obtain the actual DoFs that have zero diagonal entries by checking the Jacobian matrix at runtime. This refines the DoF list such that variable condensation will only be carried out for those DoFs that actually result in a saddle point structure. For contact problems, this will make sure that variable condensation will only happen when the material bodies come into contact. One can optionally turn on/off this capability by setting the adaptive_condensation = true or false.

  • Standard basis As mentioned above, we recommend the usage of dual basis to reduce computational overhead due to the condensation step. However, it can happen if the dual basis does not work for certain problems. In this case, the user can set use_dual = false to use the standard basis functions. Then has off-diagonal entries. During the computation of , the user can choose to either use an LU solver (by setting is_lm_coupling_diagonal = false) or obtain an approximated inverse using the diagonal entries (by setting is_lm_coupling_diagonal = true).

  • Generalized condensation Although we are focused on using VCP for mortar-based contact problems with a saddle point structure, VCP is developed to be applicable to general problems in which improved conditioning is achievable via a reduced number of DoFs.

commentnote:Generalized variable condensation is not fully tested

VCP acts on the discretized system of equations and is designed to be as general as possible. However, the current implementation is mainly tested for mortar-based mechanical contact problems. We are actively improving this implementation and are looking for applications beyond contact. Therefore, please feel free to create an issue or start a discussion if you may come across any problem with VCP.

Performance

As an illustration, we solve the 2D Hertzian problem by using VCP with several sub-preconditioner types, including BoomerAMG (AMG), successive over-relaxation (SOR), additive Schwarz method (ASM), and block Jacobi (BJAC). For all the cases, we set adaptive_condensation = true and is_lm_coupling_diagonal = true. Note that here, ASM, and BJAC converge for the mortar-based mechanical contact problem, both as a standalone preconditioner and as a sub-preconditioner. AMG and SOR stagnate as a standalone preconditioner, while converge well as a sub-preconditioner under VCP. Figure 2 shows the performance of VCP in terms of total wall time and total number of linear iterations. It can be seen that VCP can pretty efficiently converge using AMG and SOR, whereas the standard preconditioner stagnates or diverges. For the other sub-preconditioner types, VCP is still more efficient than the standard preconditioner, despite the additional computational cost from the variable condensation step. This is because a better-conditioned system is obtained after static condensation of the Lagrange multipliers. For readers who are interested in getting more details, please refer to (Yushu et al., 2021). Note the performance of VCP for problems with increased complexities, e.g., larger, multi-physics problems, is to be examined in the future.

Figure 2: Performance of VCP for the Hertzian problem. Different sub-preconditioner types are utilized for comparison. Results are shown for four processors. Note the “inf.” identifies the case when the solver stagnates thus the wall time and total number of iterations go to infinity.

Example Input File Syntax

[Preconditioning]
  [vcp]
    type = VCP
    full = true
    lm_variable = 'leftright_normal_lm'
    primary_variable = 'disp_x'
    preconditioner = 'AMG'
    is_lm_coupling_diagonal = true
    adaptive_condensation = true
  []
[]
(moose/modules/contact/test/tests/dual_mortar/dm_mechanical_contact_precon.i)

Input Parameters

  • lm_variableName of the variable(s) that is to be condensed out. Usually this will be the Lagrange multiplier variable(s).

    C++ Type:std::vector<std::string>

    Unit:(no unit assumed)

    Controllable:No

    Description:Name of the variable(s) that is to be condensed out. Usually this will be the Lagrange multiplier variable(s).

  • preconditionerPreconditioner type.

    C++ Type:std::vector<std::string>

    Unit:(no unit assumed)

    Controllable:No

    Description:Preconditioner type.

  • primary_variableName of the variable(s) that couples with the variable(s) specified in the `variable` block. Usually this is the primary variable that the Lagrange multiplier correspond to.

    C++ Type:std::vector<std::string>

    Unit:(no unit assumed)

    Controllable:No

    Description:Name of the variable(s) that couples with the variable(s) specified in the `variable` block. Usually this is the primary variable that the Lagrange multiplier correspond to.

Required Parameters

  • adaptive_condensationTrueBy default VCP will check the Jacobian and only condense the rows with zero diagonals. Set to false if you want to condense out all the specified variable dofs.

    Default:True

    C++ Type:bool

    Unit:(no unit assumed)

    Controllable:No

    Description:By default VCP will check the Jacobian and only condense the rows with zero diagonals. Set to false if you want to condense out all the specified variable dofs.

  • coupled_groupsList multiple space separated groups of comma separated variables. Off-diagonal jacobians will be generated for all pairs within a group.

    C++ Type:std::vector<NonlinearVariableName>

    Unit:(no unit assumed)

    Controllable:No

    Description:List multiple space separated groups of comma separated variables. Off-diagonal jacobians will be generated for all pairs within a group.

  • fullFalseSet to true if you want the full set of couplings between variables simply for convenience so you don't have to set every off_diag_row and off_diag_column combination.

    Default:False

    C++ Type:bool

    Unit:(no unit assumed)

    Controllable:No

    Description:Set to true if you want the full set of couplings between variables simply for convenience so you don't have to set every off_diag_row and off_diag_column combination.

  • is_lm_coupling_diagonalFalseSet to true if you are sure the coupling matrix between Lagrange multiplier variable and the coupled primal variable is strict diagonal. This will speedup the linear solve. Otherwise set to false to ensure linear solve accuracy.

    Default:False

    C++ Type:bool

    Unit:(no unit assumed)

    Controllable:No

    Description:Set to true if you are sure the coupling matrix between Lagrange multiplier variable and the coupled primal variable is strict diagonal. This will speedup the linear solve. Otherwise set to false to ensure linear solve accuracy.

  • ksp_normunpreconditionedSets the norm that is used for convergence testing

    Default:unpreconditioned

    C++ Type:MooseEnum

    Unit:(no unit assumed)

    Options:none, preconditioned, unpreconditioned, natural, default

    Controllable:No

    Description:Sets the norm that is used for convergence testing

  • nl_sysThe nonlinear system whose linearization this preconditioner should be applied to.

    C++ Type:NonlinearSystemName

    Unit:(no unit assumed)

    Controllable:No

    Description:The nonlinear system whose linearization this preconditioner should be applied to.

  • off_diag_columnThe variable names for the off-diagonal columns you want to add into the matrix; they will be associated with an off-diagonal row from the same position in off_diag_row.

    C++ Type:std::vector<NonlinearVariableName>

    Unit:(no unit assumed)

    Controllable:No

    Description:The variable names for the off-diagonal columns you want to add into the matrix; they will be associated with an off-diagonal row from the same position in off_diag_row.

  • off_diag_rowThe variable names for the off-diagonal rows you want to add into the matrix; they will be associated with an off-diagonal column from the same position in off_diag_column.

    C++ Type:std::vector<NonlinearVariableName>

    Unit:(no unit assumed)

    Controllable:No

    Description:The variable names for the off-diagonal rows you want to add into the matrix; they will be associated with an off-diagonal column from the same position in off_diag_column.

  • pc_sidedefaultPreconditioning side

    Default:default

    C++ Type:MooseEnum

    Unit:(no unit assumed)

    Options:left, right, symmetric, default

    Controllable:No

    Description:Preconditioning side

Optional Parameters

  • control_tagsAdds user-defined labels for accessing object parameters via control logic.

    C++ Type:std::vector<std::string>

    Unit:(no unit assumed)

    Controllable:No

    Description:Adds user-defined labels for accessing object parameters via control logic.

  • enableTrueSet the enabled status of the MooseObject.

    Default:True

    C++ Type:bool

    Unit:(no unit assumed)

    Controllable:No

    Description:Set the enabled status of the MooseObject.

Advanced Parameters

  • mffd_typewpSpecifies the finite differencing type for Jacobian-free solve types. Note that the default is wp (for Walker and Pernice).

    Default:wp

    C++ Type:MooseEnum

    Unit:(no unit assumed)

    Options:wp, ds

    Controllable:No

    Description:Specifies the finite differencing type for Jacobian-free solve types. Note that the default is wp (for Walker and Pernice).

  • petsc_optionsSingleton PETSc options

    C++ Type:MultiMooseEnum

    Unit:(no unit assumed)

    Options:-dm_moose_print_embedding, -dm_view, -ksp_converged_reason, -ksp_gmres_modifiedgramschmidt, -ksp_monitor, -ksp_monitor_snes_lg-snes_ksp_ew, -ksp_snes_ew, -snes_converged_reason, -snes_ksp, -snes_ksp_ew, -snes_linesearch_monitor, -snes_mf, -snes_mf_operator, -snes_monitor, -snes_test_display, -snes_view

    Controllable:No

    Description:Singleton PETSc options

  • petsc_options_inameNames of PETSc name/value pairs

    C++ Type:MultiMooseEnum

    Unit:(no unit assumed)

    Options:-ksp_atol, -ksp_gmres_restart, -ksp_max_it, -ksp_pc_side, -ksp_rtol, -ksp_type, -mat_fd_coloring_err, -mat_fd_type, -mat_mffd_type, -pc_asm_overlap, -pc_factor_levels, -pc_factor_mat_ordering_type, -pc_hypre_boomeramg_grid_sweeps_all, -pc_hypre_boomeramg_max_iter, -pc_hypre_boomeramg_strong_threshold, -pc_hypre_type, -pc_type, -snes_atol, -snes_linesearch_type, -snes_ls, -snes_max_it, -snes_rtol, -snes_divergence_tolerance, -snes_type, -sub_ksp_type, -sub_pc_type

    Controllable:No

    Description:Names of PETSc name/value pairs

  • petsc_options_valueValues of PETSc name/value pairs (must correspond with "petsc_options_iname"

    C++ Type:std::vector<std::string>

    Unit:(no unit assumed)

    Controllable:No

    Description:Values of PETSc name/value pairs (must correspond with "petsc_options_iname"

  • solve_typePJFNK: Preconditioned Jacobian-Free Newton Krylov JFNK: Jacobian-Free Newton Krylov NEWTON: Full Newton Solve FD: Use finite differences to compute Jacobian LINEAR: Solving a linear problem

    C++ Type:MooseEnum

    Unit:(no unit assumed)

    Options:PJFNK, JFNK, NEWTON, FD, LINEAR

    Controllable:No

    Description:PJFNK: Preconditioned Jacobian-Free Newton Krylov JFNK: Jacobian-Free Newton Krylov NEWTON: Full Newton Solve FD: Use finite differences to compute Jacobian LINEAR: Solving a linear problem

Petsc Parameters

References

  1. Alexander Popp, Markus Gitterle, Michael W Gee, and Wolfgang A Wall. A dual mortar approach for 3D finite deformation contact with consistent linearization. International Journal for Numerical Methods in Engineering, 83(11):1428–1465, 2010.[BibTeX]
  2. Dewen Yushu, Antonio Martin Recuero, Daniel Schwen, Alexander Lindsay, and Benjamin Spencer. M3 milestone: advanced contact 2021. 2021.[BibTeX]