<commit_before># NonlinearSystemBase

This class derives from [SystemBase.md] and is the immediate base class for
[NonlinearSystem.md] and NonlinearEigenSystem. In general a simulation will
always have exactly one `NonlinearSystemBase` object that holds and operates on
the simulation's nonlinear variables.

## Scaling id=scaling

A critical part to an efficient nonlinear solve is an efficient and accurate
linear solve. If the linear system has a poor condition number, the linear solve
may be inefficient or in the case of PJFNK, may even be
inaccurate. Preconditioning is meant to combat poor linear system conditioning,
but it may not be helpful if the preconditioning matrix, on which the
preconditioning process relies, is itself poorly conditioned. You can inspect
the condition number of your preconditioning matrix for small problems (should be less
than 1000 degrees of freedom) by running with the PETSc options `-pc_type svd
-pc_svd_monitor`. These options will tell you your condition number as well as how many singular
values you have. If you have any singular values, then you may have omitted a boundary condition,
you may have a null space (all Neumann boundary conditions for example), or you may have very poor
scaling between variables in a multi-physics simulation. You may even have run into issues if you
have nodal boundary conditions (which introduce values of unity on the diagonals) and the Jacobian
entries from your physics (kernels) are very large. You want your condition number to be as close to
unity as possible. To address the latter problem or poor relative scaling between variables, you
can use MOOSE's automatic scaling feature which will bring different physics Jacobians as close to
unity as possible. To turn on this feature, set the `automatic_scaling`
parameter in the `Executioner` block to `true`. Additionally, if you want to update scaling factors
at every time step then set `Executioner/compute_scaling_once=false`. By default this latter
parameter is set to `true` in order to save computational expense.<commit_msg>Increase automatic scaling documentation<commit_after># NonlinearSystemBase

This class derives from [SystemBase.md] and is the immediate base class for
[NonlinearSystem.md] and NonlinearEigenSystem. In general a simulation will
always have exactly one `NonlinearSystemBase` object that holds and operates on
the simulation's nonlinear variables.

## Scaling id=scaling

A critical part to an efficient nonlinear solve is an efficient and accurate
linear solve. If the linear system has a poor condition number, the linear solve
may be inefficient or in the case of PJFNK, may even be
inaccurate. Preconditioning is meant to combat poor linear system conditioning,
but it may not be helpful if the preconditioning matrix, on which the
preconditioning process relies, is itself poorly conditioned. You can inspect
the condition number of your preconditioning matrix for small problems (should be less
than 1000 degrees of freedom) by running with the PETSc options `-pc_type svd
-pc_svd_monitor`. These options will tell you your condition number as well as how many singular
values you have. If you have any singular values, then you may have omitted a boundary condition,
you may have a null space (all Neumann boundary conditions for example), or you may have very poor
scaling between variables in a multi-physics simulation. You may even have run into issues if you
have nodal boundary conditions (which introduce values of unity on the diagonals) and the Jacobian
entries from your physics (kernels) are very large. You want your condition number to be as close to
unity as possible.

### Automatic scaling id=auto-scaling

To address a poor condition number, which can often be the result of poor relative scaling between variables, you
can use MOOSE's automatic scaling feature which will bring different physics Jacobians as close to
unity as possible. To turn on this feature, set the `automatic_scaling`
parameter in the `Executioner` block to `true`. Additionally, if you want to update scaling factors
at every time step then set `Executioner/compute_scaling_once=false`. By default this latter
parameter is set to `true` in order to save computational expense.

By default scaling factors are computed solely based on information from
`compute.*Jacobian` methods. However, residual information or a hybrid of
Jacobian and residual information may also be used by setting the `Executioner`
parameter `resid_vs_jac_scaling_param`. The default value is `0`, signaling pure
Jacobian scaling. Setting a value of `1` requests pure residual scaling. Any
value in-between `0` and `1` represents a hybrid of residual and Jacobian.

Another parameter relevant to automatic scaling is the `scaling_group_variables`
parameter. Variables in a group will have a
single common factor applied to them. Multiple groups can be used with
semicolons separating them. An example of this is shown in the `Executioner`
block example below where residual/Jacobian information from all the
displacement (`disp_`) variables would be used to determine a single scaling
factor for themselves, and similarly the residual/Jacobian information from all
the velocity (`vel_`) variables would be used to determine a single scaling
factor for themselves.

```
[Executioner]
:
:
  automatic_scaling = true
  scaling_group_variables = 'disp_x disp_y disp_z; vel_x vel_y vel_z'
:
:
[]
```

The current implementation of automatic scaling in MOOSE is fairly simple and
proceeds according to these steps:

1. Compute the on-diagonal Jacobians and/or residuals for all `Kernels`, `ScalarKernels`,
   `NodalKernels`, and `FVKernels`
2. Assemble the results
3. Examine the Jacobian diagonal or residual for every row corresponding to a
   given variable (or group of variables; recall the `scaling_group_variables`
   parameter) and then compute a scaling factor such that the maximum absolute
   value of the Jacobian diagonal or residual across all of a variable's (or
   group of variables) rows is unity.
4. If a hybrid of residual and Jacobian scaling has been requested, then a
   single scaling factor is computed from the residual scaling factor and
   Jacobian scaling factor. That computation for each variable (group) is done
   with the following code, where `inverse_scaling_factor` actually denotes that
   it is the reciprocal/inverse of the final applied variable scaling factor:

```c++
inverse_scaling_factors[i] =
    std::exp(_resid_vs_jac_scaling_param * std::log(resid_inverse_scaling_factors[i]) +
             (1 - _resid_vs_jac_scaling_param) * std::log(jac_inverse_scaling_factors[i]));
```


We only execute kernel objects because objects like `BoundaryConditions`,
`DGKernels`, `InterfaceKernels`, and `Constraints` may apply penalty factors or
introduce global constraints for things like Dirichlet conditions or hanging
nodes in mesh adaptivity. We want our scaling factors to represent our physics,
not penalties or constraints.
{'fraction_non_alphanumeric': 0.040857142857142856, 'fraction_numerical': 0.0024285714285714284, 'mean_word_length': 5.114410480349345, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2367210', 'n_tokens_mistral': 1756, 'n_tokens_neox': 1631, 'n_words': 997}