Belos Version of the Day
Loading...
Searching...
No Matches
BelosSolutionProjection.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
10#ifndef BELOS_SOLUTION_PROJECTION_HPP
11#define BELOS_SOLUTION_PROJECTION_HPP
12
42#include "BelosConfigDefs.hpp"
43#include "BelosTypes.hpp"
49
50#include "Teuchos_ParameterList.hpp"
51#include "Teuchos_RCP.hpp"
52#include "Teuchos_ScalarTraits.hpp"
53
54#include <string>
55#include <vector>
56
57namespace Belos {
58
60public:
63};
64
74template<class ScalarType, class MV, class OP,
75 class DM = DefaultDenseMatrix<int, ScalarType> >
77public:
81 typedef Teuchos::ScalarTraits<ScalarType> SCT;
82 typedef typename SCT::magnitudeType MagnitudeType;
83 typedef Teuchos::ScalarTraits<MagnitudeType> MT;
84
86 SolutionProjection(const Teuchos::RCP<const OP>& A,
87 const int maxBasisSize) :
88 A_(A),
89 maxBasisSize_(maxBasisSize),
90 curBasisSize_(0),
91 replacementStrategy_("Restart"),
92 projectionTol_(static_cast<MagnitudeType>(100) * MT::eps()),
93 reorthogonalizationSteps_(2),
94 U_(Teuchos::null),
95 C_(Teuchos::null)
96 {
97 validateParameters();
98 }
99
101 SolutionProjection(const Teuchos::RCP<const OP>& A,
102 const Teuchos::RCP<Teuchos::ParameterList>& params) :
103 A_(A),
104 maxBasisSize_(20),
105 curBasisSize_(0),
106 replacementStrategy_("Restart"),
107 projectionTol_(static_cast<MagnitudeType>(100) * MT::eps()),
108 reorthogonalizationSteps_(2),
109 U_(Teuchos::null),
110 C_(Teuchos::null)
111 {
112 if (!params.is_null()) {
113 maxBasisSize_ =
114 params->get("Maximum Basis Size", maxBasisSize_);
115 replacementStrategy_ =
116 params->get("Replacement Strategy", replacementStrategy_);
117 projectionTol_ =
118 params->get("Projection Tolerance", projectionTol_);
119 reorthogonalizationSteps_ =
120 params->get("Reorthogonalization Steps", reorthogonalizationSteps_);
121 }
122
123 validateParameters();
124 }
125
127
131 void setOperator(const Teuchos::RCP<const OP>& A) {
132 A_ = A;
133 reset();
134 }
135
137 void reset() {
138 curBasisSize_ = 0;
139 }
140
142 int getBasisSize() const {
143 return curBasisSize_;
144 }
145
147 int getMaxBasisSize() const {
148 return maxBasisSize_;
149 }
150
152 void setReplacementStrategy(const std::string& strategy) {
153 replacementStrategy_ = strategy;
154 validateParameters();
155 }
156
158 std::string getReplacementStrategy() const {
159 return replacementStrategy_;
160 }
161
164 projectionTol_ = tol;
165 validateParameters();
166 }
167
170 return projectionTol_;
171 }
172
175 reorthogonalizationSteps_ = steps;
176 validateParameters();
177 }
178
181 return reorthogonalizationSteps_;
182 }
183
185 Teuchos::RCP<const MV> getCorrectionBasis() const {
186 if (curBasisSize_ == 0 || U_.is_null()) {
187 return Teuchos::null;
188 }
189
190 std::vector<int> ind(curBasisSize_);
191 for (int i = 0; i < curBasisSize_; ++i) {
192 ind[i] = i;
193 }
194
195 return MVT::CloneView(*U_, ind);
196 }
197
199 Teuchos::RCP<const MV> getImageBasis() const {
200 if (curBasisSize_ == 0 || C_.is_null()) {
201 return Teuchos::null;
202 }
203
204 std::vector<int> ind(curBasisSize_);
205 for (int i = 0; i < curBasisSize_; ++i) {
206 ind[i] = i;
207 }
208
209 return MVT::CloneView(*C_, ind);
210 }
211
213 int addSolution(const MV& u) {
215 A_.is_null(),
217 "Belos::SolutionProjection::addSolution(): operator is null.");
218
219 const int numVecs = MVT::GetNumberVecs(u);
220
222 numVecs <= 0,
223 std::invalid_argument,
224 "Belos::SolutionProjection::addSolution(): input multivector must contain at least one vector.");
225
226 Teuchos::RCP<MV> c = MVT::Clone(u, numVecs);
227
228 OPT::Apply(*A_, u, *c);
229
230 return addPair(u, *c);
231 }
232
234 int addPair(const MV& u, const MV& c) {
235 const int numVecs = MVT::GetNumberVecs(u);
236
238 numVecs <= 0,
239 std::invalid_argument,
240 "Belos::SolutionProjection::addPair(): input multivector must contain at least one vector.");
241
243 MVT::GetNumberVecs(c) != numVecs,
244 std::invalid_argument,
245 "Belos::SolutionProjection::addPair(): u and c must have the same number of vectors.");
246
248 MVT::GetGlobalLength(u) != MVT::GetGlobalLength(c),
249 std::invalid_argument,
250 "Belos::SolutionProjection::addPair(): u and c must have the same global length.");
251
252 if (maxBasisSize_ == 0) {
253 return 0;
254 }
255
256 ensureStorage(u, c);
257
258 int accepted = 0;
259
260 for (int j = 0; j < numVecs; ++j) {
261 std::vector<int> srcInd(1);
262 srcInd[0] = j;
263
264 Teuchos::RCP<const MV> uSrc = MVT::CloneView(u, srcInd);
265 Teuchos::RCP<const MV> cSrc = MVT::CloneView(c, srcInd);
266
267 Teuchos::RCP<MV> uNew = MVT::CloneCopy(*uSrc);
268 Teuchos::RCP<MV> cNew = MVT::CloneCopy(*cSrc);
269
270 const bool ok = addOnePair(*uNew, *cNew);
271 if (ok) {
272 ++accepted;
273 }
274 }
275
276 return accepted;
277 }
278
280 void project(MV& x, MV& r) const {
281 if (curBasisSize_ == 0) {
282 return;
283 }
284
285 validateProjectionInputs(x, r);
286
287 const ScalarType one = SCT::one();
288
289 const int numRhs = MVT::GetNumberVecs(r);
290
291 std::vector<int> ind(curBasisSize_);
292 for (int i = 0; i < curBasisSize_; ++i) {
293 ind[i] = i;
294 }
295
296 Teuchos::RCP<const MV> Ucur = MVT::CloneView(*U_, ind);
297 Teuchos::RCP<const MV> Ccur = MVT::CloneView(*C_, ind);
298
299 Teuchos::RCP<DM> gamma = DMT::Create(curBasisSize_, numRhs);
300
301 // gamma = C^H r.
302 MVT::MvTransMv(one, *Ccur, r, *gamma);
303
304 // x <- x + U gamma.
305 MVT::MvTimesMatAddMv(one, *Ucur, *gamma, one, x);
306
307 // r <- r - C gamma.
308 MVT::MvTimesMatAddMv(-one, *Ccur, *gamma, one, r);
309 }
310
312 void project(MV& x,
313 const MV& b,
314 Teuchos::RCP<MV> projectedResidual = Teuchos::null) const {
316 A_.is_null(),
318 "Belos::SolutionProjection::project(): operator is null.");
319
320 validateProjectionInputs(x, b);
321
322 if (!projectedResidual.is_null()) {
324 MVT::GetNumberVecs(*projectedResidual) != MVT::GetNumberVecs(b),
325 std::invalid_argument,
326 "Belos::SolutionProjection::project(): projectedResidual must have the same number of vectors as b.");
327
329 MVT::GetGlobalLength(*projectedResidual) != MVT::GetGlobalLength(b),
330 std::invalid_argument,
331 "Belos::SolutionProjection::project(): projectedResidual must have the same global length as b.");
332 }
333
334 Teuchos::RCP<MV> r = MVT::Clone(b, MVT::GetNumberVecs(b));
335
336 OPT::Apply(*A_, x, *r);
337 MVT::MvAddMv(-SCT::one(), *r, SCT::one(), b, *r);
338
339 project(x, *r);
340
341 if (!projectedResidual.is_null()) {
342 MVT::Assign(*r, *projectedResidual);
343 }
344 }
345
348 Teuchos::RCP<MV> projectedResidual = Teuchos::null) const {
349 Teuchos::RCP<MV> x = problem.getCurrLHSVec();
350
352 x.is_null(),
354 "Belos::SolutionProjection::project(LinearProblem): current LHS is null. "
355 "Did you call setLSIndex() or otherwise set the current linear system?");
356
357 Teuchos::RCP<const MV> b = problem.getCurrRHSVec();
358
360 b.is_null(),
362 "Belos::SolutionProjection::project(LinearProblem): current RHS is null. "
363 "Did you call setLSIndex() or otherwise set the current linear system?");
364
365 if (!projectedResidual.is_null()) {
367 MVT::GetNumberVecs(*projectedResidual) != MVT::GetNumberVecs(*b),
368 std::invalid_argument,
369 "Belos::SolutionProjection::project(LinearProblem): projectedResidual has wrong number of vectors.");
370
372 MVT::GetGlobalLength(*projectedResidual) != MVT::GetGlobalLength(*b),
373 std::invalid_argument,
374 "Belos::SolutionProjection::project(LinearProblem): projectedResidual has wrong global length.");
375 }
376
377 Teuchos::RCP<MV> r = MVT::Clone(*b, MVT::GetNumberVecs(*b));
378
379 // True residual, not preconditioned residual.
380 problem.computeCurrResVec(&*r);
381
382 project(*x, *r);
383
384 if (!projectedResidual.is_null()) {
385 MVT::Assign(*r, *projectedResidual);
386 }
387 }
388
389private:
390 void validateParameters() const {
392 maxBasisSize_ < 0,
393 std::invalid_argument,
394 "Belos::SolutionProjection: maximum basis size must be nonnegative.");
395
397 projectionTol_ < MT::zero(),
398 std::invalid_argument,
399 "Belos::SolutionProjection: projection tolerance must be nonnegative.");
400
402 reorthogonalizationSteps_ < 1,
403 std::invalid_argument,
404 "Belos::SolutionProjection: reorthogonalization steps must be at least one.");
405
407 replacementStrategy_ != "Restart",
408 std::invalid_argument,
409 "Belos::SolutionProjection: currently only \"Restart\" replacement strategy is implemented.");
410 }
411
412 void validateProjectionInputs(const MV& x, const MV& r) const {
413 TEUCHOS_TEST_FOR_EXCEPTION(
414 MVT::GetNumberVecs(x) != MVT::GetNumberVecs(r),
415 std::invalid_argument,
416 "Belos::SolutionProjection::project(): x and residual/right-hand side must have the same number of vectors.");
417
418 TEUCHOS_TEST_FOR_EXCEPTION(
419 MVT::GetGlobalLength(x) != MVT::GetGlobalLength(r),
420 std::invalid_argument,
421 "Belos::SolutionProjection::project(): x and residual/right-hand side must have the same global length.");
422
423 TEUCHOS_TEST_FOR_EXCEPTION(
424 !U_.is_null() && MVT::GetGlobalLength(*U_) != MVT::GetGlobalLength(x),
425 std::invalid_argument,
426 "Belos::SolutionProjection::project(): x has incompatible global length with stored basis.");
427
428 TEUCHOS_TEST_FOR_EXCEPTION(
429 !C_.is_null() && MVT::GetGlobalLength(*C_) != MVT::GetGlobalLength(r),
430 std::invalid_argument,
431 "Belos::SolutionProjection::project(): residual/right-hand side has incompatible global length with stored basis.");
432 }
433
435 void ensureStorage(const MV& uPrototype, const MV& cPrototype) {
436 if (U_.is_null()) {
437 U_ = MVT::Clone(uPrototype, maxBasisSize_);
438 }
439 else if (MVT::GetNumberVecs(*U_) < maxBasisSize_) {
440 Teuchos::RCP<const MV> tmp = U_;
441 U_ = MVT::Clone(*tmp, maxBasisSize_);
442 }
443
444 // Important: clone C_ from the image vector cPrototype, not uPrototype.
445 if (C_.is_null()) {
446 C_ = MVT::Clone(cPrototype, maxBasisSize_);
447 }
448 else if (MVT::GetNumberVecs(*C_) < maxBasisSize_) {
449 Teuchos::RCP<const MV> tmp = C_;
450 C_ = MVT::Clone(*tmp, maxBasisSize_);
451 }
452 }
453
455 bool addOnePair(MV& uNew, MV& cNew) {
456 const ScalarType one = SCT::one();
457
458 std::vector<MagnitudeType> initialNorm(1);
459 MVT::MvNorm(cNew, initialNorm);
460
461 if (initialNorm[0] == MT::zero()) {
462 return false;
463 }
464
465 if (curBasisSize_ == maxBasisSize_) {
466 if (replacementStrategy_ == "Restart") {
467 // The next accepted vector starts a new basis, using the most
468 // recent information available.
469 curBasisSize_ = 0;
470 }
471 else {
472 TEUCHOS_TEST_FOR_EXCEPTION(
473 true,
474 SolutionProjectionFailure,
475 "Belos::SolutionProjection: unsupported replacement strategy.");
476 }
477 }
478
479 for (int pass = 0; pass < reorthogonalizationSteps_; ++pass) {
480 if (curBasisSize_ == 0) {
481 break;
482 }
483
484 std::vector<int> ind(curBasisSize_);
485 for (int i = 0; i < curBasisSize_; ++i) {
486 ind[i] = i;
487 }
488
489 Teuchos::RCP<const MV> Ucur = MVT::CloneView(*U_, ind);
490 Teuchos::RCP<const MV> Ccur = MVT::CloneView(*C_, ind);
491
492 Teuchos::RCP<DM> h = DMT::Create(curBasisSize_, 1);
493
494 // h = C^H cNew.
495 MVT::MvTransMv(one, *Ccur, cNew, *h);
496
497 // cNew <- cNew - C h.
498 MVT::MvTimesMatAddMv(-one, *Ccur, *h, one, cNew);
499
500 // uNew <- uNew - U h.
501 //
502 // This keeps A uNew = cNew, assuming A U = C before this step.
503 MVT::MvTimesMatAddMv(-one, *Ucur, *h, one, uNew);
504 }
505
506 std::vector<MagnitudeType> finalNorm(1);
507 MVT::MvNorm(cNew, finalNorm);
508
509 if (finalNorm[0] <= projectionTol_ * initialNorm[0]) {
510 return false;
511 }
512
513 const ScalarType scale =
514 static_cast<ScalarType>(MT::one() / finalNorm[0]);
515
516 MVT::MvScale(cNew, scale);
517 MVT::MvScale(uNew, scale);
518
519 std::vector<int> dstInd(1);
520 dstInd[0] = curBasisSize_;
521
522 MVT::SetBlock(uNew, dstInd, *U_);
523 MVT::SetBlock(cNew, dstInd, *C_);
524
525 ++curBasisSize_;
526
527 return true;
528 }
529
530private:
531 Teuchos::RCP<const OP> A_;
532
533 int maxBasisSize_;
534 int curBasisSize_;
535
536 std::string replacementStrategy_;
537
538 // Relative tolerance. Candidate pair is rejected if
539 // ||c_orth|| <= projectionTol_ * ||c_original||.
540 MagnitudeType projectionTol_;
541
542 int reorthogonalizationSteps_;
543
544 // Correction basis and image basis.
545 //
546 // Invariant:
547 //
548 // A U = C,
549 // C^H C = I.
550 Teuchos::RCP<MV> U_;
551 Teuchos::RCP<MV> C_;
552};
553
554} // namespace Belos
555
556#endif // BELOS_SOLUTION_PROJECTION_HPP
Belos header file which uses auto-configuration information to include necessary C++ headers.
Full specialization of Belos::DenseMatTraits for Kokkos::DualView with arbitrary scalarType....
Class which describes the linear problem to be solved by the iterative solver.
Declaration of basic traits for the multivector type.
Class which defines basic traits for the operator type.
Full specialization of Belos::DenseMatTraits for Teuchos::SerialDenseMatrix with ordinal type int and...
Collection of types and exceptions used within the Belos solvers.
Parent class to all Belos exceptions.
Alternative run-time polymorphic interface for operators.
virtual void Apply(const MultiVec< ScalarType, DM > &x, MultiVec< ScalarType, DM > &y, ETrans trans=NOTRANS) const =0
Apply the operator to x, putting the result in y.
SolutionProjectionFailure(const std::string &what_arg)
Fischer Method 1 style projection utility.
std::string getReplacementStrategy() const
Get replacement strategy.
int addSolution(const MV &u)
Add solution vector(s) u. The class computes c = A u.
void reset()
Clear the stored projection basis.
MagnitudeType getProjectionTolerance() const
Get relative projection tolerance.
void project(MV &x, const MV &b, Teuchos::RCP< MV > projectedResidual=Teuchos::null) const
Compute r = b - A x, then apply projection to x and r.
void setOperator(const Teuchos::RCP< const OP > &A)
Set or replace the operator.
Teuchos::ScalarTraits< MagnitudeType > MT
Teuchos::RCP< const MV > getCorrectionBasis() const
Get correction basis U.
void setReplacementStrategy(const std::string &strategy)
Set replacement strategy.
void setProjectionTolerance(const MagnitudeType tol)
Set relative projection tolerance.
Teuchos::RCP< const MV > getImageBasis() const
Get image basis C.
int addPair(const MV &u, const MV &c)
Add pair(s) u and c, where c should equal A u.
int getBasisSize() const
Current number of stored basis vectors.
MultiVecTraits< ScalarType, MV, DM > MVT
void project(MV &x, MV &r) const
Apply projection to x and r, where r is assumed to be b - A x.
SolutionProjection(const Teuchos::RCP< const OP > &A, const Teuchos::RCP< Teuchos::ParameterList > &params)
Constructor with parameter list.
SolutionProjection(const Teuchos::RCP< const OP > &A, const int maxBasisSize)
Constructor with explicit maximum basis size.
void project(LinearProblem< ScalarType, MV, OP, DM > &problem, Teuchos::RCP< MV > projectedResidual=Teuchos::null) const
Project the current solution in a LinearProblem.
Teuchos::ScalarTraits< ScalarType > SCT
void setReorthogonalizationSteps(const int steps)
Set number of reorthogonalization passes.
int getReorthogonalizationSteps() const
Get number of reorthogonalization passes.
OperatorTraits< ScalarType, MV, OP > OPT
DenseMatTraits< ScalarType, DM > DMT
int getMaxBasisSize() const
Maximum number of stored basis vectors.

Generated for Belos by doxygen 1.9.8