-
Notifications
You must be signed in to change notification settings - Fork 156
Add FAQ section to docs #566
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 3 commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
fe19da7
add FAQ section
balos1 ac8772b
few fixes
balos1 df91319
Merge branch 'develop' into feature/doc-faq
balos1 19f7f18
Apply spelling patch
balos1 47f53a5
Merge branch 'develop' into feature/doc-faq
gardner48 e3b310d
Apply suggestions from code review
balos1 3ff1f1f
fix indentation
balos1 93cf126
fix conflicting reference
balos1 3e4208a
Merge branch 'develop' into feature/doc-faq
gardner48 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,335 @@ | ||
.. | ||
---------------------------------------------------------------- | ||
SUNDIALS Copyright Start | ||
Copyright (c) 2002-2024, Lawrence Livermore National Security | ||
and Southern Methodist University. | ||
All rights reserved. | ||
See the top-level LICENSE and NOTICE files for details. | ||
|
||
SPDX-License-Identifier: BSD-3-Clause | ||
SUNDIALS Copyright End | ||
---------------------------------------------------------------- | ||
|
||
.. _FAQ: | ||
|
||
########################## | ||
Frequently Asked Questions | ||
########################## | ||
|
||
The following are some questions frequently asked by SUNDIALS users. | ||
If you do not see your question here, please do not hesistate to ask the | ||
SUNDIALS mailing list by emailing your question to ``sundials-users@llnl.gov``, | ||
or by opening an issue on our GitHub at `https://github.com/LLNL/sundials`. | ||
|
||
Installation Related | ||
-------------------- | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
.. collapse:: I have the sundials source, how do I build it? | ||
|
||
See the :ref:`Installation.CMake` section. | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
|
||
.. collapse:: Can I use a non-default compiler to build SUNDIALS? | ||
|
||
Yes, specific compilers can be specified on the CMake command line. | ||
The following example specifies gcc and g++ for the CXX compiler: | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
.. code-block:: cpp | ||
cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ ../srcdir | ||
.. note:: | ||
If you wish to change the compiler after already configuring, then you must start | ||
with a fresh build directory and specify the compiler on the command line as shown. | ||
|
||
|
||
.. collapse:: How do I install SUNDIALS on Windows systems? | ||
|
||
One way of obtaining Windows libraries for the SUNDIALS solvers is to use cygwin | ||
`cygwin <www.cygwin.com>`_, in which case the installation procedure is the same | ||
as for any other Linux system. | ||
|
||
Otherwise, refer to :ref:`Installation.CMake.Windows`. | ||
|
||
|
||
.. collapse:: Everything installed fine! How do I link the SUNDIALS libraries to my own application? | ||
|
||
Refer to :ref:`Installation.Results`. | ||
|
||
|
||
CVODE/IDA/ARKODE Related | ||
------------------------ | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
.. collapse:: How do I choose tolerances? | ||
|
||
The same advice applies to CVODE, IDA and ARKODE: | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
1. The scalar relative tolerance ``reltol`` is to be set to control relative errors. So | ||
:math:`\texttt{reltol} = 10^{-4}` means that errors are controlled to .01%. We do not recommend | ||
using ``reltol`` larger than :math:`10^{-3}`. On the other hand, ``reltol`` should not be so small | ||
that it is comparable to the unit roundoff of the machine arithmetic (generally | ||
around :math:`10^{-15}`). | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
2. The absolute tolerances ``abstol`` (whether scalar or vector) need to be set to control | ||
absolute errors when any components of the solution vector ``y`` may be so small that | ||
pure relative error control is meaningless. For example, if ``y[i]`` starts at some | ||
nonzero value, but in time decays to zero, then pure relative error control on ``y[i]`` | ||
makes no sense (and is overly costly) after ``y[i]`` is below some noise level. Then | ||
``abstol`` (if scalar) or ``abstol[i]`` (if a vector) needs to be set to that noise level. If the different | ||
components have different noise levels, then ``abstol`` should be a vector. See the example ``cvsRoberts_dns`` | ||
in the CVODE package, and the discussion of it in the CVODE Examples document | ||
:cite:p:`cvodes_ex`. In that problem, the three components vary between 0 and 1, | ||
and have different noise levels; hence the ``abstol`` vector. It is impossible to give any | ||
general advice on ``abstol`` values, because the appropriate noise levels are completely | ||
problem-dependent. The user or modeler hopefully has some idea as to what those | ||
noise levels are. | ||
|
||
3. Finally, it is important to pick all the tolerance values conservatively, | ||
because they control the error committed on each individual time step. The final | ||
(global) errors are some sort of accumulation of those per-step errors. A good | ||
rule of thumb is to reduce the tolerances by a factor of .01 from the actual | ||
desired limits on errors. So if you want .01% accuracy (globally), a good choice | ||
is :math:`\texttt{reltol} = 10^{-6}`. But in any case, it is a good idea to do a few experiments | ||
with the tolerances to see how the computed solution values vary as tolerances | ||
are reduced. | ||
|
||
|
||
.. collapse:: How do I choose what linear solver to use for the stiff case? | ||
|
||
If the problem is size is fairly small (say :math:`N < 100`), then using the dense solver is | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
probably best; it is the simplest to use, and reasonably inexpensive for small N. For larger N, it | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
is important to take advantage of sparsity (zero-nonzero) structure within the problem. If there | ||
is local (nearest-neighbor) coupling, or if the coupling is local after a suitable reordering of | ||
y, then use the banded linear solver. Local coupling means that the i-th component of the RHS or | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
residual function depends only on components :math:`y_j` for which :math:`|i-j|` is small relative | ||
to N. (Note that the dense and band solvers are only applicable for the serial version of the | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
solver.) For even larger problems, consider one of the Krylov iterative methods. These are hardest | ||
to use, because for best results they usually require preconditioning. However they offer the best | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
opportunity to exploit the sparsity structure in the problem. The preconditioner is a matrix | ||
which, at least crudely, approximates the actual matrix in the linear system to be solved, and is | ||
typically built from an approximation of the relevant Jacobian matrix. Typically, that | ||
approximation uses only part of the true Jacobian, but as a result is much less expensive to | ||
solve. If the Jacobian can be approximated by a matrix that is banded (serial case) or | ||
block-diagonal with banded blocks (parallel case), SUNDIALS includes preconditioner modules for | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
such cases. In each of the user guides, the section 'Linear solver specification functions' and | ||
the section on preconditioner modules contain more detailed comments on preconditioning. On the | ||
construction of preconditioners for problems arising from the spatial discretization of | ||
time-dependent partial differential equation systems, there is considerable discussion in the | ||
paper :cite:p:`BrHi:89`. | ||
|
||
.. collapse:: How do I handle a data-defined function within the RHS function? | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
Often the RHS or residual function depends on some function :math:`A(t)` that is data-defined, | ||
i.e. defined only at a set of discrete set of times t. The solver must be able to obtain values of | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
the user-supplied functions at arbitrary times t in the integration interval. So the user must fit | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
the data with a reasonably smooth function :math:`A(t)` that is defined continuously for all | ||
relevant t, and incorporate an evaluation of that fit function in the user function involved. This | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
may be as simple as a piecewise linear fit, but a smoother fit (e.g. spline) would make the | ||
integration more efficient. If there is noise in the data, the fit should be a least-squares fit | ||
instead of a straight interpolation. The same advice applies if the user function has a | ||
data-defined function :math:`A(y)` that involves one or more components of the dependent variable | ||
vector y. Of course, if more that one component is involved, the fit is more complicated. | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
.. collapse:: How do I control unphysical negative values? | ||
|
||
In many applications, some components in the true solution are always positive | ||
or non-negative, though at times very small. In the numerical solution, however, | ||
small negative (hence unphysical) values can then occur. In most cases, these | ||
values are harmless, and simply need to be controlled, not eliminated. The | ||
following pieces of advice are relevant. | ||
|
||
1. The way to control the size of unwanted negative computed values is with | ||
tighter absolute tolerances. Again this requires some knowledge of the noise | ||
level of these components, which may or may not be different for different | ||
components. Some experimentation may be needed. | ||
|
||
2. If output plots or tables are being generated, and it is important to avoid | ||
having negative numbers appear there (for the sake of avoiding a long | ||
explanation of them, if nothing else), then eliminate them, but only in the | ||
context of the output medium. Then the internal values carried by the solver are | ||
unaffected. Remember that a small negative value in ``y`` returned by CVODE, with | ||
magnitude comparable to ``abstol`` or less, is equivalent to zero as far as the computation | ||
is concerned. | ||
|
||
3. The user’s right-hand side routine ``f`` should never change a negative value in | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
the solution vector ``y`` to a non-negative value, as a "solution" to this problem. | ||
This can cause instability. If the ``f`` routine cannot tolerate a zero or negative | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
value (e.g. because there is a square root or log of it), then the offending | ||
value should be changed to zero or a tiny positive number in a temporary | ||
variable (not in the input ``y`` vector) for the purposes of computing :math:`f(t,y)`. | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
4. Positivity and non-negativity constraints on components can be enforced by | ||
use of the recoverable error return feature in the user-supplied right-hand side | ||
function. However, because this option involves some extra overhead cost, it | ||
should only be exercised if the use of absolute tolerances to control the | ||
computed values is unsuccessful. | ||
|
||
In addition, IDA provides the option of enforcing positivity or non-negativity on components. But | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
these constraint options should only be exercised if the use of absolute tolerances to control the | ||
computed values is unsuccessful, because they involve some extra overhead cost. | ||
|
||
|
||
.. collapse:: How do I treat discontinuities in the RHS function? | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
If the jumps at the discontinuities are relatively small, simply keep them in the RHS function, | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
and let the integrator respond to them (possibly taking smaller steps through each point of | ||
discontinuity). If the jumps are large, it is more efficient to stop at the point of discontinuity | ||
and restart the integrator with a readjusted ODE model. To stop when the location of the | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
discontinuity is known, simply make that location a value of tout. To stop when the location of | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
the discontinuity is determined by the solution, use the rootfinding feature. In either case, it | ||
is critical that the RHS function not incorporate the discontinuity, but rather have a smooth | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
extension over the discontinuity, so that the step across it (and subsequent rootfinding, if used) | ||
can be done efficiently. Then use a switch within the RHS function that can be flipped between the | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
stopping of the integration and the restart, so that the restarted problem uses the new values | ||
(which have jumped). | ||
|
||
|
||
.. collapse:: When is it advantageous to supply my own EwtFn function? | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
The main situation where this is a good idea is where the problem needs something "in between" the | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
cases covered by scalar and vector absolute tolerances. Namely, suppose there are a few groups of | ||
variables (relative to the total number of variables) such that all the variables in each group | ||
require the same value of abstol, but these values are very different from one group to another. | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
Then a user EwtFn function can keep an array of those values and construct the ewt vector without | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
any additional storage. Also, in rare cases, one may want to use this option to apply different | ||
values of reltol to different variables (or groups of variables). | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
|
||
.. collapse:: How do switch on/off forward sensitivity computations in CVODES? | ||
|
||
If you want to turn on and off forward sensitivity calculations during several successive | ||
integrations (such as if you were using CVODES within a dynamically-constrained optimization loop, | ||
when sometimes you want to only integrate the states and sometimes you also need sensitivities | ||
computed), it is most efficient to use :c:func:`CVodeSensToggleOff`. | ||
|
||
|
||
.. collapse:: What is the role of plist in CVODES? | ||
|
||
The argument plist to :c:func:`CVodeSetSensParams` is used to specify the problem parameters with | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
respect to which solution sensitivities are to be computed. | ||
|
||
``plist`` is used only if the sensitivity right-hand sides are evaluated using the internal | ||
difference-quotient approximation function. In that case, plist should be declared as an array of | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
Ns integers and should contain the indices in the array of problem parameters p with respect to | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
which sensitivities are desired. For example, if you want to compute sensitivities with respect to | ||
the first and third parameters in the p array, p[0] and p[2], you need to set | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
.. code-block:: C | ||
plist[0] = 0 | ||
plist[1] = 2 | ||
If plist is not provided, CVODES will compute sensitivities with respect to the first Ns | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
parameters in the array p (i.e. it will use plist[i]=i, i=0,1,...Ns). If the user provides a | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
function to evaluate the right-hand sides of the sensitivity equations or if the default values | ||
are desired, a NULL pointer can be passed to :c:func:`CVodeSetSensParams`. | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
|
||
.. collapse:: What is the role of pbar in CVODES? | ||
|
||
The argument ``pbar`` to :c:func:`CVodeSetSensParams` is used to specify scaling factors for the | ||
problem parameters. | ||
|
||
``pbar`` is used only if | ||
|
||
* the internal difference-quotient functions are used for the evaluation of the sensitivity | ||
right-hand sides, in which case ``pbar`` is used in computing an appropriate perturbation for | ||
the finite-difference approximation | ||
|
||
or | ||
|
||
* the tolerances for the sensitivity variables are estimated automatically by CVODES from those | ||
specified for the state variables. | ||
|
||
If provided, ``pbar`` should be declared as an array of Ns realtypes and should contain non-zero | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
scaling factors for the Ns parameters with respect to which sensitivities are to be computed. For | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
non-zero problem parameters, a good choice is | ||
|
||
.. code-block:: C | ||
pbar[i] = p[plist[i]] | ||
If ``pbar`` is not provided, CVODES will use pbar[i]=1.0, i=0,1,...Ns-1. | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
If the user provides a function to evaluate the right-hand sides of the sensitivity equations and | ||
also specifies tolerances for the sensitivity variables (through the ``CVodeSens*tolerances`` | ||
functions) or if the default values are desired, a ``NULL`` pointer can be passed to | ||
:c:func:`CVodeSetSensParams`. | ||
|
||
|
||
.. collapse:: What is pure quadrature integration? | ||
|
||
Suppose your ODE is :math:`y'=F(t,y)` and you integrate it from 0 to T and that you are also interested in computing an integral of the form | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
.. math:: | ||
G = int_0^T g(t,y(t)) dt | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
for some function *g*. The most efficient way of computing *z* is by appending one additional differential equation to your ODE system: | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
.. math:: | ||
z' = g(t,y) | ||
with initial condition z(0)=0, in which case :math:`G = z(T)`. | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
This additional equation is "a pure quadrature equation" and its main characteristic is that the | ||
new differential variable z does not appear in the right hand side of the extended ODE system. If | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
CVODES is notified of such "pure quadrature equations", it can take advantage of this property and | ||
do less work than if it didn't know about them (these variables need not be considered in the | ||
nonlinear system solution). | ||
|
||
The main reason for the special treatment of "pure quadrature equations" in CVODES is that such | ||
integrals (very often a large number of them) need to be computed for adjoint sensitivity. | ||
|
||
|
||
KINSOL | ||
------ | ||
|
||
.. collapse:: How do I reinitialize KINSOL within a C/C++ program? | ||
|
||
Although KINSOL does not provide a reinitialization function, it is possible to reinitialize the | ||
solver (meaning reuse a KINSOL object), but only if the problem size remains unchanged. To | ||
reinitialize KINSOL, begin by making any necessary changes to the problem definition by calling | ||
the appropriate KINSet* functions (e.g., :c:func:`KINSetSysFunc`). Next, if you would like to use | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
a different linear solver, call the appropriate function, followed by any calls to the | ||
corresponding KIN*Set* functions. Then you can call the KINSol function to solve the updated | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
nonlinear algebraic system. | ||
|
||
|
||
.. collapse:: Why is the system function being evaluated at points that violate the constraints? | ||
|
||
If you have not supplied a function to compute either J(u) (of type :c:type:`KINLsJacFn`) or J(u)v | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
(of type :c:type:`KINLsJacTimesVecFn`), then the internal function may be the culprit. The | ||
default function used to compute a difference quotient approximation to the Jacobian (direct | ||
methods) or Jacobian matrix-vector product (Kylov methods) evaluates the user-supplied system | ||
function at a slightly perturbed point, but does not check if that point violates the constraints. | ||
|
||
|
||
Miscellaneous | ||
------------- | ||
|
||
.. collapse:: How do I determine which version of SUNDIALS I have? | ||
|
||
If you still have access to the distribution files, then the SUNDIALS release number is indicated | ||
in the header of sundials/README and the corresponding solver versions can be determined by | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
reading the appropriate row of the "Release History" table. You can also call the functions | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
:c:func:`SUNDIALSGetVersion` and :c:func:`SUNDIALSGetVersionNumber` from your program, or | ||
use the ``SUNDIALS_VERSION*`` macros found in the header file ``sundials/sundials_version.h``. | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
The specific version number of each solver is contained in corresponding README files: | ||
``sundials/src/<solver>/README``. | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
|
||
.. collapse:: http://sundials.wikidot.com | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
Some additional information might be found at `http://sundials.wikidot.com | ||
<http://sundials.wikidot.com/>`_ however the wikidot page has not been maintained in many years so | ||
it contains plenty of outdated information. | ||
|
||
.. warning:: | ||
balos1 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
The SUNDIALS team does not maintain the wikidot web page. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
.. ---------------------------------------------------------------- | ||
SUNDIALS Copyright Start | ||
Copyright (c) 2002-2024, Lawrence Livermore National Security | ||
and Southern Methodist University. | ||
All rights reserved. | ||
|
||
See the top-level LICENSE and NOTICE files for details. | ||
|
||
SPDX-License-Identifier: BSD-3-Clause | ||
SUNDIALS Copyright End | ||
---------------------------------------------------------------- | ||
|
||
.. include:: ../../shared/FAQ.rst |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.