Belos Version of the Day
Loading...
Searching...
No Matches
BelosSimpleOrthoManager.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Belos: Block Linear Solvers Package
4//
5// Copyright 2004-2016 NTESS and the Belos contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
13#ifndef __Belos_SimpleOrthoManager_hpp
14#define __Belos_SimpleOrthoManager_hpp
15
16#include <BelosConfigDefs.hpp>
19#include <BelosOrthoManager.hpp>
21#include <Teuchos_ParameterList.hpp>
22#include <Teuchos_StandardCatchMacros.hpp>
23#include <Teuchos_TimeMonitor.hpp>
24
25namespace Belos {
26
35 template<class Scalar, class MV, class DM>
37 public OrthoManager<Scalar, MV, DM>
38 {
39 public:
41 typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType magnitude_type;
42
43 private:
46 typedef Teuchos::ScalarTraits<Scalar> STS;
47 typedef Teuchos::ScalarTraits<magnitude_type> STM;
48
50 std::string label_;
52 Teuchos::RCP<OutputManager<Scalar> > outMan_;
54 bool reorthogonalize_;
56 bool useMgs_;
58 mutable Teuchos::RCP<Teuchos::ParameterList> defaultParams_;
59
60#ifdef BELOS_TEUCHOS_TIME_MONITOR
62 Teuchos::RCP<Teuchos::Time> timerOrtho_;
64 Teuchos::RCP<Teuchos::Time> timerProject_;
66 Teuchos::RCP<Teuchos::Time> timerNormalize_;
67
76 static Teuchos::RCP<Teuchos::Time>
77 makeTimer (const std::string& prefix,
78 const std::string& timerName)
79 {
80 const std::string timerLabel =
81 prefix.empty() ? timerName : (prefix + ": " + timerName);
82 return Teuchos::TimeMonitor::getNewCounter (timerLabel);
83 }
84#endif // BELOS_TEUCHOS_TIME_MONITOR
85
86 public:
87
94 Teuchos::RCP<const Teuchos::ParameterList>
96 {
97 using Teuchos::ParameterList;
98 using Teuchos::parameterList;
99 using Teuchos::RCP;
100
101 const std::string defaultNormalizationMethod ("MGS");
102 const bool defaultReorthogonalization = false;
103
104 if (defaultParams_.is_null()) {
106 params->set ("Normalization", defaultNormalizationMethod,
107 "Which normalization method to use. Valid values are \"MGS\""
108 " (for Modified Gram-Schmidt) and \"CGS\" (for Classical "
109 "Gram-Schmidt).");
110 params->set ("Reorthogonalization", defaultReorthogonalization,
111 "Whether to perform one (unconditional) reorthogonalization "
112 "pass.");
113 defaultParams_ = params;
114 }
115 return defaultParams_;
116 }
117
123 Teuchos::RCP<const Teuchos::ParameterList>
125 {
126 using Teuchos::ParameterList;
127 using Teuchos::parameterList;
128 using Teuchos::RCP;
129 using Teuchos::rcp;
130
131 const std::string fastNormalizationMethod ("CGS");
132 const bool fastReorthogonalization = false;
133
134 // Start with a clone of the default parameters.
136 fastParams->set ("Normalization", fastNormalizationMethod);
137 fastParams->set ("Reorthogonalization", fastReorthogonalization);
138
139 return fastParams;
140 }
141
142 void
143 setParameterList (const Teuchos::RCP<Teuchos::ParameterList>& plist)
144 {
145 using Teuchos::ParameterList;
146 using Teuchos::parameterList;
147 using Teuchos::RCP;
148 using Teuchos::Exceptions::InvalidParameter;
149
152 if (plist.is_null ()) {
154 } else {
155 params = plist;
156 params->validateParametersAndSetDefaults (*defaultParams);
157 }
158 const std::string normalizeImpl = params->get<std::string>("Normalization");
159 const bool reorthogonalize = params->get<bool>("Reorthogonalization");
160
161 if (normalizeImpl == "MGS" ||
162 normalizeImpl == "Mgs" ||
163 normalizeImpl == "mgs") {
164 useMgs_ = true;
165 params->set ("Normalization", std::string ("MGS")); // Standardize.
166 } else {
167 useMgs_ = false;
168 params->set ("Normalization", std::string ("CGS")); // Standardize.
169 }
170 reorthogonalize_ = reorthogonalize;
171
172 this->setMyParamList (params);
173 }
174
186 const std::string& label,
187 const Teuchos::RCP<Teuchos::ParameterList>& params) :
188 label_ (label),
189 outMan_ (outMan)
190 {
191#ifdef BELOS_TEUCHOS_TIME_MONITOR
192 timerOrtho_ = makeTimer (label, "All orthogonalization");
193 timerProject_ = makeTimer (label, "Projection");
194 timerNormalize_ = makeTimer (label, "Normalization");
195#endif // BELOS_TEUCHOS_TIME_MONITOR
196
198 if (! outMan_.is_null ()) {
199 using std::endl;
200 std::ostream& dbg = outMan_->stream(Debug);
201 dbg << "Belos::SimpleOrthoManager constructor:" << endl
202 << "-- Normalization method: "
203 << (useMgs_ ? "MGS" : "CGS") << endl
204 << "-- Reorthogonalize (unconditionally)? "
205 << (reorthogonalize_ ? "Yes" : "No") << endl;
206 }
207 }
208
212 SimpleOrthoManager (const std::string& label = "Belos") :
213 label_ (label)
214 {
215#ifdef BELOS_TEUCHOS_TIME_MONITOR
216 timerOrtho_ = makeTimer (label, "All orthogonalization");
217 timerProject_ = makeTimer (label, "Projection");
218 timerNormalize_ = makeTimer (label, "Normalization");
219#endif // BELOS_TEUCHOS_TIME_MONITOR
220
221 setParameterList (Teuchos::null);
222 }
223
226
227 void innerProd (const MV &X, const MV &Y, DM & Z) const {
228 MVT::MvTransMv (STS::one (), X, Y, Z);
229 }
230
231 void norm (const MV& X, std::vector<magnitude_type>& normVec) const {
232 const int numCols = MVT::GetNumberVecs (X);
233 // std::vector<T>::size_type is unsigned; int is signed. Mixed
234 // unsigned/signed comparisons trigger compiler warnings.
235 if (normVec.size () < static_cast<size_t> (numCols)) {
236 normVec.resize (numCols); // Resize normvec if necessary.
237 }
238 MVT::MvNorm (X, normVec);
239 }
240
241 void
242 project (MV &X,
243 Teuchos::Array<Teuchos::RCP<DM>> C,
244 Teuchos::ArrayView<Teuchos::RCP<const MV> > Q) const
245 {
246#ifdef BELOS_TEUCHOS_TIME_MONITOR
247 Teuchos::TimeMonitor timerMonitorOrtho(*timerOrtho_);
248 Teuchos::TimeMonitor timerMonitorProject(*timerProject_);
249#endif // BELOS_TEUCHOS_TIME_MONITOR
250
251 allocateProjectionCoefficients (C, Q, X, true);
252 rawProject (X, Q, C);
253 if (reorthogonalize_) { // Unconditional reorthogonalization
254 Teuchos::Array<Teuchos::RCP<DM> > C2;
255 allocateProjectionCoefficients (C2, Q, X, false);
256 for (int k = 0; k < Q.size(); ++k)
257 DMT::Add(*C[k], *C2[k]);
258 }
259 }
260
261 int
262 normalize (MV &X, Teuchos::RCP<DM> B) const
263 {
264#ifdef BELOS_TEUCHOS_TIME_MONITOR
265 Teuchos::TimeMonitor timerMonitorOrtho(*timerOrtho_);
266 Teuchos::TimeMonitor timerMonitorProject(*timerNormalize_);
267#endif // BELOS_TEUCHOS_TIME_MONITOR
268
269 if (useMgs_) {
270 return normalizeMgs (X, B);
271 } else {
272 return normalizeCgs (X, B);
273 }
274 }
275
276 protected:
277 virtual int
279 Teuchos::Array<Teuchos::RCP<DM>> C,
280 Teuchos::RCP<DM> B,
281 Teuchos::ArrayView<Teuchos::RCP<const MV> > Q) const
282 {
283 // Don't need time monitors here: project() and normalize() have
284 // their own.
285 this->project (X, C, Q);
286 return this->normalize (X, B);
287 }
288
289 public:
290
292 orthonormError(const MV &X) const
293 {
294 const Scalar ONE = STS::one();
295 const int ncols = MVT::GetNumberVecs(X);
296 Teuchos::RCP<DM> XTX = DMT::Create(ncols, ncols);
297 innerProd (X, X, *XTX);
298 DMT::SyncDeviceToHost(*XTX);
299 for (int k = 0; k < ncols; ++k) {
300 DMT::Value(*XTX,k,k) -= ONE;
301 }
302 DMT::SyncHostToDevice(*XTX);
303 return DMT::NormFrobenius(*XTX);
304 }
305
307 orthogError(const MV &X1, const MV &X2) const
308 {
309 const int ncols_X1 = MVT::GetNumberVecs (X1);
310 const int ncols_X2 = MVT::GetNumberVecs (X2);
311 Teuchos::RCP<DM> X1_T_X2 = DMT::Create(ncols_X1, ncols_X2);
312 innerProd (X1, X2, *X1_T_X2);
313 return DMT::NormFrobenius(*X1_T_X2);
314 }
315
316 void setLabel (const std::string& label) { label_ = label; }
317 const std::string& getLabel() const { return label_; }
318
319 private:
320
321 int
322 normalizeMgs (MV &X, Teuchos::RCP<DM> &B) const
323 {
324 using Teuchos::Range1D;
325 using Teuchos::RCP;
326 using Teuchos::rcp;
327 using Teuchos::View;
328
329 const int numCols = MVT::GetNumberVecs (X);
330 if (numCols == 0) {
331 return 0;
332 }
333
334 if (B.is_null ()) {
335 B = DMT::Create(numCols, numCols);
336 } else if (DMT::GetNumRows(*B) != numCols || DMT::GetNumCols(*B) != numCols) {
337 DMT::Reshape(*B, numCols, numCols);
338 }
339
340 RCP<DM> tmpBij = DMT::Create(1,1);
341
342 // Modified Gram-Schmidt orthogonalization
343 std::vector<magnitude_type> normVec (1);
344 for (int j = 0; j < numCols; ++j) {
345 RCP<MV> X_cur = MVT::CloneViewNonConst (X, Range1D(j, j));
346 MV& X_j = *X_cur;
347 for (int i = 0; i < j; ++i) {
348 RCP<const MV> X_prv = MVT::CloneView (X, Range1D(i, i));
349 const MV& X_i = *X_prv;
350 RCP<DM> B_ij = DMT::Subview(*B, 1, 1, i, j);
351 innerProd (X_i, X_j, *B_ij);
352 MVT::MvTimesMatAddMv (-STS::one(), X_i, *B_ij, STS::one(), X_j);
353 if (reorthogonalize_) { // Unconditional reorthogonalization
354 innerProd (X_i, X_j, *tmpBij);
355 MVT::MvTimesMatAddMv (-STS::one(), X_i, *tmpBij, STS::one(), X_j);
356 DMT::Add( *B_ij, *tmpBij );
357 }
358 }
359 // Normalize column j of X
360 norm (X_j, normVec);
361 const magnitude_type theNorm = normVec[0];
362 RCP<DM> B_jj = DMT::Subview(*B, 1, 1, j, j);
363 DMT::Value(*B_jj,0,0) = theNorm;
364 DMT::SyncHostToDevice(*B_jj);
365 if (normVec[0] != STM::zero()) {
366 MVT::MvScale (X_j, STS::one() / theNorm);
367 } else {
368 return j; // break out early
369 }
370 }
371 return numCols; // full rank, as far as we know
372 }
373
374
375 int
376 normalizeCgs (MV &X, Teuchos::RCP<DM> &B) const
377 {
378 using Teuchos::Range1D;
379 using Teuchos::RCP;
380 using Teuchos::rcp;
381 using Teuchos::View;
382
383 const int numCols = MVT::GetNumberVecs (X);
384 if (numCols == 0) {
385 return 0;
386 }
387
388 if (B.is_null ()) {
389 B = DMT::Create( numCols, numCols );
390 } else if (DMT::GetNumRows(*B) != numCols || DMT::GetNumCols(*B) != numCols) {
391 DMT::Reshape(*B, numCols, numCols);
392 }
393
394 // Classical Gram-Schmidt orthogonalization
395 std::vector<magnitude_type> normVec (1);
396
397 // Space for reorthogonalization
398 RCP<DM> B2 = DMT::Create(numCols, numCols);
399
400 // Do the first column first.
401 {
402 RCP<MV> X_cur = MVT::CloneViewNonConst (X, Range1D(0, 0));
403 // Normalize column 0 of X
404 norm (*X_cur, normVec);
405 const magnitude_type theNorm = normVec[0];
406 RCP<DM> B_00 = DMT::Subview(*B, 1, 1);
407 DMT::PutScalar(*B_00, theNorm);
408 if (theNorm != STM::zero ()) {
409 const Scalar invNorm = STS::one () / theNorm;
410 MVT::MvScale (*X_cur, invNorm);
411 }
412 else {
413 return 0; // break out early
414 }
415 }
416
417 // Orthogonalize the remaining columns of X
418 for (int j = 1; j < numCols; ++j) {
419 RCP<MV> X_cur = MVT::CloneViewNonConst (X, Range1D(j, j));
420 RCP<const MV> X_prv = MVT::CloneView (X, Range1D(0, j-1));
421 RCP<DM> B_prvcur = DMT::Subview(*B, j, 1, 0, j);
422
423 // Project X_cur against X_prv (first pass)
424 innerProd (*X_prv, *X_cur, *B_prvcur);
425 MVT::MvTimesMatAddMv (-STS::one(), *X_prv, *B_prvcur, STS::one(), *X_cur);
426 // Unconditional reorthogonalization:
427 // project X_cur against X_prv (second pass)
428 if (reorthogonalize_) {
429 RCP<DM> B2_prvcur = DMT::Subview(*B2, j, 1, 0, j);
430 innerProd (*X_prv, *X_cur, *B2_prvcur);
431 MVT::MvTimesMatAddMv (-STS::one(), *X_prv, *B2_prvcur, STS::one(), *X_cur);
432 DMT::Add(*B_prvcur, *B2_prvcur);
433 }
434 // Normalize column j of X
435 norm (*X_cur, normVec);
436 const magnitude_type theNorm = normVec[0];
437 RCP<DM> B_jj = DMT::Subview(*B, 1, 1, j, j);
438 DMT::PutScalar(*B_jj, theNorm);
439 if (theNorm != STM::zero ()) {
440 const Scalar invNorm = STS::one () / theNorm;
441 MVT::MvScale (*X_cur, invNorm);
442 }
443 else {
444 return j; // break out early
445 }
446 }
447 return numCols; // full rank, as far as we know
448 }
449
450
451 void
452 allocateProjectionCoefficients (Teuchos::Array<Teuchos::RCP<DM>>& C,
453 Teuchos::ArrayView<Teuchos::RCP<const MV> > Q,
454 const MV& X,
455 const bool attemptToRecycle = true) const
456 {
457 using Teuchos::rcp;
458
459 const int num_Q_blocks = Q.size();
460 const int ncols_X = MVT::GetNumberVecs (X);
461 C.resize (num_Q_blocks);
462 // # of block(s) that had to be (re)allocated (either allocated
463 // freshly, or resized).
464 int numAllocated = 0;
465 if (attemptToRecycle) {
466 for (int i = 0; i < num_Q_blocks; ++i) {
467 const int ncols_Qi = MVT::GetNumberVecs (*Q[i]);
468 // Create a new C[i] if necessary, otherwise resize if
469 // necessary, otherwise fill with zeros.
470 if (C[i].is_null ()) {
471 C[i] = DMT::Create(ncols_Qi, ncols_X);
472 numAllocated++;
473 }
474 else {
475 DM& Ci = *C[i];
476 if (DMT::GetNumRows(Ci) != ncols_Qi || DMT::GetNumCols(Ci) != ncols_X) {
477 DMT::Reshape(Ci, ncols_Qi, ncols_X);
478 numAllocated++;
479 }
480 else {
481 DMT::PutScalar(Ci, STS::zero());
482 }
483 }
484 }
485 }
486 else { // Just allocate; don't try to check if we can recycle
487 for (int i = 0; i < num_Q_blocks; ++i) {
488 const int ncols_Qi = MVT::GetNumberVecs (*Q[i]);
489 C[i] = DMT::Create( ncols_Qi, ncols_X );
490 numAllocated++;
491 }
492 }
493 if (! outMan_.is_null()) {
494 using std::endl;
495 std::ostream& dbg = outMan_->stream(Debug);
496 dbg << "SimpleOrthoManager::allocateProjectionCoefficients: "
497 << "Allocated " << numAllocated << " blocks out of "
498 << num_Q_blocks << endl;
499 }
500 }
501
502 void
503 rawProject (MV& X,
504 Teuchos::ArrayView<Teuchos::RCP<const MV> > Q,
505 Teuchos::ArrayView<Teuchos::RCP<DM> > C) const
506 {
507 // "Modified Gram-Schmidt" version of Block Gram-Schmidt.
508 const int num_Q_blocks = Q.size();
509 for (int i = 0; i < num_Q_blocks; ++i) {
510 DM& Ci = *C[i];
511 const MV& Qi = *Q[i];
512 innerProd (Qi, X, Ci);
513 MVT::MvTimesMatAddMv (-STS::one(), Qi, Ci, STS::one(), X);
514 }
515 }
516
517 };
518} // namespace Belos
519
520#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.
Alternative run-time polymorphic interface for operators.
Belos's templated virtual class for providing routines for orthogonalization and orthonormzalition of...
Simple OrthoManager implementation for benchmarks.
void norm(const MV &X, std::vector< magnitude_type > &normVec) const
magnitude_type orthonormError(const MV &X) const
This method computes the error in orthonormality of a multivector.
void project(MV &X, Teuchos::Array< Teuchos::RCP< DM > > C, Teuchos::ArrayView< Teuchos::RCP< const MV > > Q) const
Project X against the (orthogonal) entries of Q.
void innerProd(const MV &X, const MV &Y, DM &Z) const
Provides the inner product defining the orthogonality concepts.
Teuchos::ScalarTraits< Scalar >::magnitudeType magnitude_type
void setParameterList(const Teuchos::RCP< Teuchos::ParameterList > &plist)
const std::string & getLabel() const
This method returns the label being used by the timers in the orthogonalization manager.
void setLabel(const std::string &label)
This method sets the label used by the timers in the orthogonalization manager.
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
Get a default list of parameters.
virtual ~SimpleOrthoManager()
Virtual destructor for memory safety of derived classes.
SimpleOrthoManager(const std::string &label="Belos")
Constructor.
virtual int projectAndNormalizeImpl(MV &X, Teuchos::Array< Teuchos::RCP< DM > > C, Teuchos::RCP< DM > B, Teuchos::ArrayView< Teuchos::RCP< const MV > > Q) const
int normalize(MV &X, Teuchos::RCP< DM > 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.
SimpleOrthoManager(const Teuchos::RCP< OutputManager< Scalar > > &outMan, const std::string &label, const Teuchos::RCP< Teuchos::ParameterList > &params)
Constructor.
magnitude_type orthogError(const MV &X1, const MV &X2) const
This method computes the error in orthogonality of two multivectors.

Generated for Belos by doxygen 1.9.8