From: David Wells <wellsd2@rpi.edu>
Date: Sat, 31 Mar 2018 23:13:16 +0000 (-0400)
Subject: Use at least three temporary vectors for GMRES.
X-Git-Tag: v9.0.0-rc1~253^2
X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9dc9c1b4c1c6c86bcb2b587e1cd75f2c649191a5;p=dealii.git

Use at least three temporary vectors for GMRES.

This prevents possible integer wrap-around that is not desired.

This was found by coverity.
---

diff --git a/include/deal.II/lac/solver_gmres.h b/include/deal.II/lac/solver_gmres.h
index 47d51d4c34..dcdc6b6f55 100644
--- a/include/deal.II/lac/solver_gmres.h
+++ b/include/deal.II/lac/solver_gmres.h
@@ -197,7 +197,8 @@ public:
     /**
      * Maximum number of temporary vectors. This parameter controls the size
      * of the Arnoldi basis, which for historical reasons is
-     * #max_n_tmp_vectors-2.
+     * #max_n_tmp_vectors-2. SolverGMRES assumes that there are at least three
+     * temporary vectors, so this value must be greater than or equal to three.
      */
     unsigned int    max_n_tmp_vectors;
 
@@ -598,7 +599,10 @@ AdditionalData (const unsigned int max_n_tmp_vectors,
   right_preconditioning(right_preconditioning),
   use_default_residual(use_default_residual),
   force_re_orthogonalization(force_re_orthogonalization)
-{}
+{
+  Assert(3 <= max_n_tmp_vectors, ExcMessage("SolverGMRES needs at least three "
+                                            "temporary vectors."));
+}
 
 
 
@@ -774,7 +778,10 @@ SolverGMRES<VectorType>::solve (const MatrixType         &A,
 //TODO:[GK] Make sure the parameter in the constructor means maximum basis size
 
   LogStream::Prefix prefix("GMRES");
-  const unsigned int n_tmp_vectors = additional_data.max_n_tmp_vectors;
+
+  // extra call to std::max to placate static analyzers: coverity rightfully
+  // complains that data.max_n_tmp_vectors - 2 may overflow
+  const unsigned int n_tmp_vectors = std::max(additional_data.max_n_tmp_vectors, 3u);
 
   // Generate an object where basis vectors are stored.
   internal::SolverGMRESImplementation::TmpVectors<VectorType> tmp_vectors (n_tmp_vectors, this->memory);