* InverseMatrixRichardson, SchurMatrix, ShiftedMatrix,
* ShiftedMatrixGeneralized, TransposeMatrix
*
+ *
+ * <h3>Packaged Operation</h3>
+ *
+ * An application of a LinearOperator object to a vector via
+ * <code>operator*</code> yields a PackagedOperation object that stores
+ * this computation.
+ *
+ * The PackagedOperation class allows lazy evaluation of expressions
+ * involving vectors and linear operators. This is done by storing the
+ * computational expression and only performing the computation when either
+ * the object is implicitly converted to a vector object, or
+ * <code>apply</code> (or <code>apply_add</code>) is invoked by hand. This
+ * avoids unnecessary temporary storage of intermediate results.
+ *
+ * As an example consider the addition of multiple vectors:
+ * @code
+ * dealii::Vector<double> a, b, c, d;
+ * // ..
+ * dealii::Vector<double> result = a + b - c + d;
+ * @endcode
+ * Converting the PackagedOperation <code>a + b - c + d</code> to a vector
+ * results in code equivalent to the following code
+ * @code
+ * dealii::Vector<double> a, b, c, d;
+ * // ..
+ * dealii::Vector<double> result = a;
+ * result += b;
+ * result -= c;
+ * result += d;
+ * @endcode
+ * that avoids any intermediate storage. As a second example (involving a
+ * LinearOperator object) consider the computation of a residual $b-Ax$:
+ *
+ * @code
+ * dealii::SparseMatrix<double> A;
+ * dealii::Vector<double> b, x;
+ * // ..
+ * const auto op_a = linear_operator(A);
+ *
+ * dealii::Vector<double> residual = b - op_a * x;
+ * @endcode
+ *
+ * @note
+ * Lazy evaluation of a computational expression necessarily involves
+ * references to the underlying vector and matrix objects. For example, the
+ * creation of a <code>residual_expr</code> object
+ * @code
+ * auto residual_expr = b - op_a * x;
+ * @endcode
+ * stores the computational expression of the residual with references to
+ * the vector <code>b</code> and matrix <code>A</code>. It does not perform
+ * any computation at this point. In particular, if <code>b</code> or
+ * <code>A</code> are changed <b>after</b> the creation of
+ * <code>residual_expr</code> every subsequent evaluation of the expression
+ * is performed with the new values
+ * @code
+ * auto residual_expr = b - op_a * x;
+ * residual_expr.apply(tmp); // tmp is a Vector<double>
+ *
+ * // modify b, or A
+ *
+ * residual_expr.apply(tmp2); // tmp2 is a Vector<double>
+ *
+ * // tmp and tmp2 are different
+ * @endcode
+ * Thus, as a safeguard, if you want to compute the result of an expression
+ * right away, always explicitly use a vector type on the left side (and
+ * not <code>auto</code>):
+ * @code
+ * Vector<double> residual = b - op_a * x; // computes the residual at this point
+ * @endcode
+ *
+ *
* @ingroup LAC
* @ingroup MATRICES
*/
/**
* A class to store a computation.
*
+ * The PackagedOperation class allows lazy evaluation of expressions
+ * involving vectors and linear operators. This is done by storing the
+ * computational expression and only performing the computation when either
+ * the object is implicitly converted to a vector object, or
+ * <code>apply</code> (or <code>apply_add</code>) is invoked by hand. This
+ * avoids unnecessary temporary storage of intermediate results.
+ *
* The class essentially consists of <code>std::function</code> objects
* that store the knowledge of how to generate the result of a computation
* and store it in a vector:
* std::function<void(Range &, bool)> reinit_vector;
* @endcode
*
- * The primary purpose of this class is to allow lazy evaluation of
- * expressions involving vectors and linear operators. As an example
- * consider the addition of multiple vectors
+ * As an example consider the addition of multiple vectors
* @code
* dealii::Vector<double> a, b, c, d;
* // ..
* // ..
* const auto op_a = linear_operator(A);
*
- * const auto residual = b - op_a * x;
+ * dealii::Vector<double> residual = b - op_a * x;
* @endcode
* The expression <code>residual</code> is of type
* <code>PackagedOperation<dealii::Vector<double>></code>. It stores