Belos  Version of the Day
BelosSimpleOrthoManager.hpp
Go to the documentation of this file.
1 //@HEADER
2 // ************************************************************************
3 //
4 // Belos: Block Linear Solvers Package
5 // Copyright 2004 Sandia Corporation
6 //
7 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
8 // the U.S. Government retains certain rights in this software.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ************************************************************************
40 //@HEADER
41 
45 #ifndef __Belos_SimpleOrthoManager_hpp
46 #define __Belos_SimpleOrthoManager_hpp
47 
48 #include <BelosConfigDefs.hpp>
49 #include <BelosMultiVecTraits.hpp>
50 #include <BelosOrthoManager.hpp>
51 #include <BelosOutputManager.hpp>
52 #include <Teuchos_ParameterList.hpp>
53 #include <Teuchos_ParameterListAcceptorDefaultBase.hpp>
54 #include <Teuchos_StandardCatchMacros.hpp>
55 #include <Teuchos_TimeMonitor.hpp>
56 
57 namespace Belos {
58 
67  template<class Scalar, class MV>
69  public OrthoManager<Scalar, MV>,
70  public Teuchos::ParameterListAcceptorDefaultBase
71  {
72  public:
73  typedef Scalar scalar_type;
74  typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType magnitude_type;
75  typedef Teuchos::SerialDenseMatrix<int, Scalar> mat_type;
76  typedef Teuchos::RCP<Teuchos::SerialDenseMatrix<int, Scalar> > mat_ptr;
77 
78  private:
80  typedef Teuchos::ScalarTraits<Scalar> STS;
81  typedef Teuchos::ScalarTraits<magnitude_type> STM;
82 
84  std::string label_;
86  Teuchos::RCP<OutputManager<Scalar> > outMan_;
88  bool reorthogonalize_;
90  bool useMgs_;
92  mutable Teuchos::RCP<Teuchos::ParameterList> defaultParams_;
93 
94 #ifdef BELOS_TEUCHOS_TIME_MONITOR
96  Teuchos::RCP<Teuchos::Time> timerOrtho_;
98  Teuchos::RCP<Teuchos::Time> timerProject_;
100  Teuchos::RCP<Teuchos::Time> timerNormalize_;
101 
110  static Teuchos::RCP<Teuchos::Time>
111  makeTimer (const std::string& prefix,
112  const std::string& timerName)
113  {
114  const std::string timerLabel =
115  prefix.empty() ? timerName : (prefix + ": " + timerName);
116  return Teuchos::TimeMonitor::getNewCounter (timerLabel);
117  }
118 #endif // BELOS_TEUCHOS_TIME_MONITOR
119 
120  public:
121 
128  Teuchos::RCP<const Teuchos::ParameterList>
130  {
131  using Teuchos::ParameterList;
132  using Teuchos::parameterList;
133  using Teuchos::RCP;
134 
135  const std::string defaultNormalizationMethod ("MGS");
136  const bool defaultReorthogonalization = false;
137 
138  if (defaultParams_.is_null()) {
139  RCP<ParameterList> params = parameterList ("Simple");
140  params->set ("Normalization", defaultNormalizationMethod,
141  "Which normalization method to use. Valid values are \"MGS\""
142  " (for Modified Gram-Schmidt) and \"CGS\" (for Classical "
143  "Gram-Schmidt).");
144  params->set ("Reorthogonalization", defaultReorthogonalization,
145  "Whether to perform one (unconditional) reorthogonalization "
146  "pass.");
147  defaultParams_ = params;
148  }
149  return defaultParams_;
150  }
151 
157  Teuchos::RCP<const Teuchos::ParameterList>
159  {
160  using Teuchos::ParameterList;
161  using Teuchos::parameterList;
162  using Teuchos::RCP;
163  using Teuchos::rcp;
164 
165  const std::string fastNormalizationMethod ("CGS");
166  const bool fastReorthogonalization = false;
167 
168  // Start with a clone of the default parameters.
169  RCP<ParameterList> fastParams = parameterList (*getValidParameters());
170  fastParams->set ("Normalization", fastNormalizationMethod);
171  fastParams->set ("Reorthogonalization", fastReorthogonalization);
172 
173  return fastParams;
174  }
175 
176  void
177  setParameterList (const Teuchos::RCP<Teuchos::ParameterList>& plist)
178  {
179  using Teuchos::ParameterList;
180  using Teuchos::parameterList;
181  using Teuchos::RCP;
182  using Teuchos::Exceptions::InvalidParameter;
183 
184  RCP<const ParameterList> defaultParams = getValidParameters();
185  RCP<ParameterList> params;
186  if (plist.is_null ()) {
187  params = parameterList (*defaultParams);
188  } else {
189  params = plist;
190  params->validateParametersAndSetDefaults (*defaultParams);
191  }
192  const std::string normalizeImpl = params->get<std::string>("Normalization");
193  const bool reorthogonalize = params->get<bool>("Reorthogonalization");
194 
195  if (normalizeImpl == "MGS" ||
196  normalizeImpl == "Mgs" ||
197  normalizeImpl == "mgs") {
198  useMgs_ = true;
199  params->set ("Normalization", std::string ("MGS")); // Standardize.
200  } else {
201  useMgs_ = false;
202  params->set ("Normalization", std::string ("CGS")); // Standardize.
203  }
204  reorthogonalize_ = reorthogonalize;
205 
206  setMyParamList (params);
207  }
208 
219  SimpleOrthoManager (const Teuchos::RCP<OutputManager<Scalar> >& outMan,
220  const std::string& label,
221  const Teuchos::RCP<Teuchos::ParameterList>& params) :
222  label_ (label),
223  outMan_ (outMan)
224  {
225 #ifdef BELOS_TEUCHOS_TIME_MONITOR
226  timerOrtho_ = makeTimer (label, "All orthogonalization");
227  timerProject_ = makeTimer (label, "Projection");
228  timerNormalize_ = makeTimer (label, "Normalization");
229 #endif // BELOS_TEUCHOS_TIME_MONITOR
230 
231  setParameterList (params);
232  if (! outMan_.is_null ()) {
233  using std::endl;
234  std::ostream& dbg = outMan_->stream(Debug);
235  dbg << "Belos::SimpleOrthoManager constructor:" << endl
236  << "-- Normalization method: "
237  << (useMgs_ ? "MGS" : "CGS") << endl
238  << "-- Reorthogonalize (unconditionally)? "
239  << (reorthogonalize_ ? "Yes" : "No") << endl;
240  }
241  }
242 
246  SimpleOrthoManager (const std::string& label = "Belos") :
247  label_ (label)
248  {
249 #ifdef BELOS_TEUCHOS_TIME_MONITOR
250  timerOrtho_ = makeTimer (label, "All orthogonalization");
251  timerProject_ = makeTimer (label, "Projection");
252  timerNormalize_ = makeTimer (label, "Normalization");
253 #endif // BELOS_TEUCHOS_TIME_MONITOR
254 
255  setParameterList (Teuchos::null);
256  }
257 
259  virtual ~SimpleOrthoManager() {}
260 
261  void innerProd (const MV &X, const MV &Y, mat_type& Z) const {
262  MVT::MvTransMv (STS::one (), X, Y, Z);
263  }
264 
265  void norm (const MV& X, std::vector<magnitude_type>& normVec) const {
266  const int numCols = MVT::GetNumberVecs (X);
267  // std::vector<T>::size_type is unsigned; int is signed. Mixed
268  // unsigned/signed comparisons trigger compiler warnings.
269  if (normVec.size () < static_cast<size_t> (numCols)) {
270  normVec.resize (numCols); // Resize normvec if necessary.
271  }
272  MVT::MvNorm (X, normVec);
273  }
274 
275  void
276  project (MV &X,
277  Teuchos::Array<mat_ptr> C,
278  Teuchos::ArrayView<Teuchos::RCP<const MV> > Q) const
279  {
280 #ifdef BELOS_TEUCHOS_TIME_MONITOR
281  Teuchos::TimeMonitor timerMonitorOrtho(*timerOrtho_);
282  Teuchos::TimeMonitor timerMonitorProject(*timerProject_);
283 #endif // BELOS_TEUCHOS_TIME_MONITOR
284 
285  allocateProjectionCoefficients (C, Q, X, true);
286  rawProject (X, Q, C);
287  if (reorthogonalize_) { // Unconditional reorthogonalization
288  Teuchos::Array<Teuchos::RCP<Teuchos::SerialDenseMatrix<int,Scalar> > > C2;
289  allocateProjectionCoefficients (C2, Q, X, false);
290  for (int k = 0; k < Q.size(); ++k)
291  *C[k] += *C2[k];
292  }
293  }
294 
295  int
296  normalize (MV &X, mat_ptr B) const
297  {
298 #ifdef BELOS_TEUCHOS_TIME_MONITOR
299  Teuchos::TimeMonitor timerMonitorOrtho(*timerOrtho_);
300  Teuchos::TimeMonitor timerMonitorProject(*timerNormalize_);
301 #endif // BELOS_TEUCHOS_TIME_MONITOR
302 
303  if (useMgs_) {
304  return normalizeMgs (X, B);
305  } else {
306  return normalizeCgs (X, B);
307  }
308  }
309 
310  protected:
311  virtual int
313  Teuchos::Array<mat_ptr> C,
314  mat_ptr B,
315  Teuchos::ArrayView<Teuchos::RCP<const MV> > Q) const
316  {
317  // Don't need time monitors here: project() and normalize() have
318  // their own.
319  this->project (X, C, Q);
320  return this->normalize (X, B);
321  }
322 
323  public:
324 
326  orthonormError(const MV &X) const
327  {
328  const Scalar ONE = STS::one();
329  const int ncols = MVT::GetNumberVecs(X);
330  mat_type XTX (ncols, ncols);
331  innerProd (X, X, XTX);
332  for (int k = 0; k < ncols; ++k) {
333  XTX(k,k) -= ONE;
334  }
335  return XTX.normFrobenius();
336  }
337 
339  orthogError(const MV &X1, const MV &X2) const
340  {
341  const int ncols_X1 = MVT::GetNumberVecs (X1);
342  const int ncols_X2 = MVT::GetNumberVecs (X2);
343  mat_type X1_T_X2 (ncols_X1, ncols_X2);
344  innerProd (X1, X2, X1_T_X2);
345  return X1_T_X2.normFrobenius();
346  }
347 
348  void setLabel (const std::string& label) { label_ = label; }
349  const std::string& getLabel() const { return label_; }
350 
351  private:
352 
353  int
354  normalizeMgs (MV &X,
355  Teuchos::RCP<Teuchos::SerialDenseMatrix<int,Scalar> > B) const
356  {
357  using Teuchos::Range1D;
358  using Teuchos::RCP;
359  using Teuchos::rcp;
360  using Teuchos::View;
361 
362  const int numCols = MVT::GetNumberVecs (X);
363  if (numCols == 0) {
364  return 0;
365  }
366 
367  if (B.is_null ()) {
368  B = rcp (new mat_type (numCols, numCols));
369  } else if (B->numRows () != numCols || B->numCols () != numCols) {
370  B->shape (numCols, numCols);
371  }
372 
373  // Modified Gram-Schmidt orthogonalization
374  std::vector<magnitude_type> normVec (1);
375  for (int j = 0; j < numCols; ++j) {
376  RCP<MV> X_cur = MVT::CloneViewNonConst (X, Range1D(j, j));
377  MV& X_j = *X_cur;
378  for (int i = 0; i < j; ++i) {
379  RCP<const MV> X_prv = MVT::CloneView (X, Range1D(i, i));
380  const MV& X_i = *X_prv;
381  mat_type B_ij (View, *B, 1, 1, i, j);
382  innerProd (X_i, X_j, B_ij);
383  MVT::MvTimesMatAddMv (-STS::one(), X_i, B_ij, STS::one(), X_j);
384  if (reorthogonalize_) { // Unconditional reorthogonalization
385  // innerProd() overwrites B(i,j), so save the
386  // first-pass projection coefficient and update
387  // B(i,j) afterwards.
388  const Scalar B_ij_first = (*B)(i, j);
389  innerProd (X_i, X_j, B_ij);
390  MVT::MvTimesMatAddMv (-STS::one(), X_i, B_ij, STS::one(), X_j);
391  (*B)(i, j) += B_ij_first;
392  }
393  }
394  // Normalize column j of X
395  norm (X_j, normVec);
396  const magnitude_type theNorm = normVec[0];
397  (*B)(j, j) = theNorm;
398  if (normVec[0] != STM::zero()) {
399  MVT::MvScale (X_j, STS::one() / theNorm);
400  } else {
401  return j; // break out early
402  }
403  }
404  return numCols; // full rank, as far as we know
405  }
406 
407 
408  int
409  normalizeCgs (MV &X, mat_ptr B) const
410  {
411  using Teuchos::Range1D;
412  using Teuchos::RCP;
413  using Teuchos::rcp;
414  using Teuchos::View;
415 
416  const int numCols = MVT::GetNumberVecs (X);
417  if (numCols == 0) {
418  return 0;
419  }
420 
421  if (B.is_null ()) {
422  B = rcp (new mat_type (numCols, numCols));
423  } else if (B->numRows() != numCols || B->numCols() != numCols) {
424  B->shape (numCols, numCols);
425  }
426  mat_type& B_ref = *B;
427 
428  // Classical Gram-Schmidt orthogonalization
429  std::vector<magnitude_type> normVec (1);
430 
431  // Space for reorthogonalization
432  mat_type B2 (numCols, numCols);
433 
434  // Do the first column first.
435  {
436  RCP<MV> X_cur = MVT::CloneViewNonConst (X, Range1D(0, 0));
437  // Normalize column 0 of X
438  norm (*X_cur, normVec);
439  const magnitude_type theNorm = normVec[0];
440  B_ref(0,0) = theNorm;
441  if (theNorm != STM::zero ()) {
442  const Scalar invNorm = STS::one () / theNorm;
443  MVT::MvScale (*X_cur, invNorm);
444  }
445  else {
446  return 0; // break out early
447  }
448  }
449 
450  // Orthogonalize the remaining columns of X
451  for (int j = 1; j < numCols; ++j) {
452  RCP<MV> X_cur = MVT::CloneViewNonConst (X, Range1D(j, j));
453  RCP<const MV> X_prv = MVT::CloneView (X, Range1D(0, j-1));
454  mat_type B_prvcur (View, B_ref, j, 1, 0, j);
455 
456  // Project X_cur against X_prv (first pass)
457  innerProd (*X_prv, *X_cur, B_prvcur);
458  MVT::MvTimesMatAddMv (-STS::one(), *X_prv, B_prvcur, STS::one(), *X_cur);
459  // Unconditional reorthogonalization:
460  // project X_cur against X_prv (second pass)
461  if (reorthogonalize_) {
462  mat_type B2_prvcur (View, B2, j, 1, 0, j);
463  innerProd (*X_prv, *X_cur, B2_prvcur);
464  MVT::MvTimesMatAddMv (-STS::one(), *X_prv, B2_prvcur, STS::one(), *X_cur);
465  B_prvcur += B2_prvcur;
466  }
467  // Normalize column j of X
468  norm (*X_cur, normVec);
469  const magnitude_type theNorm = normVec[0];
470  B_ref(j,j) = theNorm;
471  if (theNorm != STM::zero ()) {
472  const Scalar invNorm = STS::one () / theNorm;
473  MVT::MvScale (*X_cur, invNorm);
474  }
475  else {
476  return j; // break out early
477  }
478  }
479  return numCols; // full rank, as far as we know
480  }
481 
482 
483  void
484  allocateProjectionCoefficients (Teuchos::Array<mat_ptr>& C,
485  Teuchos::ArrayView<Teuchos::RCP<const MV> > Q,
486  const MV& X,
487  const bool attemptToRecycle = true) const
488  {
489  using Teuchos::rcp;
490 
491  const int num_Q_blocks = Q.size();
492  const int ncols_X = MVT::GetNumberVecs (X);
493  C.resize (num_Q_blocks);
494  // # of block(s) that had to be (re)allocated (either allocated
495  // freshly, or resized).
496  int numAllocated = 0;
497  if (attemptToRecycle) {
498  for (int i = 0; i < num_Q_blocks; ++i) {
499  const int ncols_Qi = MVT::GetNumberVecs (*Q[i]);
500  // Create a new C[i] if necessary, otherwise resize if
501  // necessary, otherwise fill with zeros.
502  if (C[i].is_null ()) {
503  C[i] = rcp (new mat_type (ncols_Qi, ncols_X));
504  numAllocated++;
505  }
506  else {
507  mat_type& Ci = *C[i];
508  if (Ci.numRows() != ncols_Qi || Ci.numCols() != ncols_X) {
509  Ci.shape (ncols_Qi, ncols_X);
510  numAllocated++;
511  }
512  else {
513  Ci.putScalar (STS::zero());
514  }
515  }
516  }
517  }
518  else { // Just allocate; don't try to check if we can recycle
519  for (int i = 0; i < num_Q_blocks; ++i) {
520  const int ncols_Qi = MVT::GetNumberVecs (*Q[i]);
521  C[i] = rcp (new mat_type (ncols_Qi, ncols_X));
522  numAllocated++;
523  }
524  }
525  if (! outMan_.is_null()) {
526  using std::endl;
527  std::ostream& dbg = outMan_->stream(Debug);
528  dbg << "SimpleOrthoManager::allocateProjectionCoefficients: "
529  << "Allocated " << numAllocated << " blocks out of "
530  << num_Q_blocks << endl;
531  }
532  }
533 
534  void
535  rawProject (MV& X,
536  Teuchos::ArrayView<Teuchos::RCP<const MV> > Q,
537  Teuchos::ArrayView<mat_ptr> C) const
538  {
539  // "Modified Gram-Schmidt" version of Block Gram-Schmidt.
540  const int num_Q_blocks = Q.size();
541  for (int i = 0; i < num_Q_blocks; ++i) {
542  mat_type& Ci = *C[i];
543  const MV& Qi = *Q[i];
544  innerProd (Qi, X, Ci);
545  MVT::MvTimesMatAddMv (-STS::one(), Qi, Ci, STS::one(), X);
546  }
547  }
548 
549  };
550 } // namespace Belos
551 
552 #endif // __Belos_SimpleOrthoManager_hpp
Belos header file which uses auto-configuration information to include necessary C++ headers.
Declaration of basic traits for the multivector type.
Templated virtual class for providing orthogonalization/orthonormalization methods.
Class which manages the output and verbosity of the Belos solvers.
Traits class which defines basic operations on multivectors.
static void MvTransMv(const ScalarType alpha, const MV &A, const MV &mv, Teuchos::SerialDenseMatrix< int, ScalarType > &B)
Compute a dense matrix B through the matrix-matrix multiply .
static void MvScale(MV &mv, const ScalarType alpha)
Scale each element of the vectors in mv with alpha.
static void MvTimesMatAddMv(const ScalarType alpha, const MV &A, const Teuchos::SerialDenseMatrix< int, ScalarType > &B, const ScalarType beta, MV &mv)
Update mv with .
static void MvNorm(const MV &mv, std::vector< typename Teuchos::ScalarTraits< ScalarType >::magnitudeType > &normvec, NormType type=TwoNorm)
Compute the norm of each individual vector of mv. Upon return, normvec[i] holds the value of ,...
static Teuchos::RCP< const MV > CloneView(const MV &mv, const std::vector< int > &index)
Creates a new const MV that shares the selected contents of mv (shallow copy).
static Teuchos::RCP< MV > CloneViewNonConst(MV &mv, const std::vector< int > &index)
Creates a new MV that shares the selected contents of mv (shallow copy).
static int GetNumberVecs(const MV &mv)
Obtain the number of vectors in mv.
Belos's templated virtual class for providing routines for orthogonalization and orthonormzalition of...
Belos's basic output manager for sending information of select verbosity levels to the appropriate ou...
Simple OrthoManager implementation for benchmarks.
magnitude_type orthogError(const MV &X1, const MV &X2) const
This method computes the error in orthogonality of two multivectors.
int normalize(MV &X, mat_ptr B) const
This method takes a multivector X and attempts to compute an orthonormal basis for ,...
Teuchos::RCP< const Teuchos::ParameterList > getFastParameters()
Get a "fast" list of parameters.
void norm(const MV &X, std::vector< magnitude_type > &normVec) const
Teuchos::RCP< Teuchos::SerialDenseMatrix< int, Scalar > > mat_ptr
Teuchos::ScalarTraits< Scalar >::magnitudeType magnitude_type
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
Get a default list of parameters.
const std::string & getLabel() const
This method returns the label being used by the timers in the orthogonalization manager.
virtual int projectAndNormalizeImpl(MV &X, Teuchos::Array< mat_ptr > C, mat_ptr B, Teuchos::ArrayView< Teuchos::RCP< const MV > > Q) const
SimpleOrthoManager(const std::string &label="Belos")
Constructor.
magnitude_type orthonormError(const MV &X) const
This method computes the error in orthonormality of a multivector.
void project(MV &X, Teuchos::Array< mat_ptr > C, Teuchos::ArrayView< Teuchos::RCP< const MV > > Q) const
Project X against the (orthogonal) entries of Q.
void setLabel(const std::string &label)
This method sets the label used by the timers in the orthogonalization manager.
void setParameterList(const Teuchos::RCP< Teuchos::ParameterList > &plist)
void innerProd(const MV &X, const MV &Y, mat_type &Z) const
Provides the inner product defining the orthogonality concepts.
SimpleOrthoManager(const Teuchos::RCP< OutputManager< Scalar > > &outMan, const std::string &label, const Teuchos::RCP< Teuchos::ParameterList > &params)
Constructor.
Teuchos::SerialDenseMatrix< int, Scalar > mat_type
virtual ~SimpleOrthoManager()
Virtual destructor for memory safety of derived classes.

Generated on Sat Jun 5 2021 10:50:20 for Belos by doxygen 1.9.1