Belos Version of the Day
Loading...
Searching...
No Matches
BelosPseudoBlockStochasticCGIter.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_PSEUDO_BLOCK_STOCHASTIC_CG_ITER_HPP
11#define BELOS_PSEUDO_BLOCK_STOCHASTIC_CG_ITER_HPP
12
17#include "BelosConfigDefs.hpp"
18#include "BelosTypes.hpp"
20
24#include "BelosStatusTest.hpp"
27
28#include "Teuchos_SerialDenseVector.hpp"
29#include "Teuchos_SerialDenseHelpers.hpp"
30#include "Teuchos_ScalarTraits.hpp"
31#include "Teuchos_ParameterList.hpp"
32#include "Teuchos_TimeMonitor.hpp"
33
49namespace Belos {
50
51 template<class ScalarType, class MV, class OP, class DM>
52 class PseudoBlockStochasticCGIter : virtual public StochasticCGIteration<ScalarType,MV,OP,DM> {
53
54 public:
55
56 //
57 // Convenience typedefs
58 //
62 typedef Teuchos::ScalarTraits<ScalarType> SCT;
63 typedef typename SCT::magnitudeType MagnitudeType;
64
66
67
74 const Teuchos::RCP<OutputManager<ScalarType> > &printer,
75 const Teuchos::RCP<StatusTest<ScalarType,MV,OP,DM> > &tester,
76 Teuchos::ParameterList &params );
77
81
82
84
85
99 void iterate();
100
122
131
141 state.R = R_;
142 state.P = P_;
143 state.AP = AP_;
144 state.Z = Z_;
145 state.Y = Y_;
146 return state;
147 }
148
150
151
153
154
156 int getNumIters() const { return iter_; }
157
159 void resetNumIters( int iter = 0 ) { iter_ = iter; }
160
163 Teuchos::RCP<const MV> getNativeResiduals( std::vector<MagnitudeType> * /* norms */ ) const { return R_; }
164
166
168 Teuchos::RCP<MV> getCurrentUpdate() const { return Teuchos::null; }
169
171 Teuchos::RCP<MV> getStochasticVector() const { return Y_; }
172
174
176
177
179 const LinearProblem<ScalarType,MV,OP,DM>& getProblem() const { return *lp_; }
180
182 int getBlockSize() const { return 1; }
183
186 TEUCHOS_TEST_FOR_EXCEPTION(blockSize!=1,std::invalid_argument,
187 "Belos::PseudoBlockStochasticCGIter::setBlockSize(): Cannot use a block size that is not one.");
188 }
189
191 bool isInitialized() { return initialized_; }
192
194
195 private:
196
198 inline Teuchos::SerialDenseVector<int,ScalarType>& normal() {
199 // Do all of the calculations with doubles, because that is what the Odeh and Evans 1974 constants are for.
200 // Then cast to ScalarType.
201
202 const double p0 = -0.322232431088;
203 const double p1 = -1.0;
204 const double p2 = -0.342242088547;
205 const double p3 = -0.204231210245e-1;
206 const double p4 = -0.453642210148e-4;
207 const double q0 = 0.993484626060e-1;
208 const double q1 = 0.588581570495;
209 const double q2 = 0.531103462366;
210 const double q3 = 0.103537752850;
211 const double q4 = 0.38560700634e-2;
212 double r,p,q,y,z;
213
214 // Return a vector with random entries that are synchronized across processors.
215 Teuchos::randomSyncedMatrix( randvec_ );
216
217 for (int i=0; i<numRHS_; i++)
218 {
219 // Get a random number (-1,1) and rescale to (0,1).
220 r=0.5*SCT::real(randvec_[i]) + 1.0;
221
222 // Odeh and Evans algorithm (as modified by Park & Geyer)
223 if(r < 0.5) y=std::sqrt(-2.0 * log(r));
224 else y=std::sqrt(-2.0 * log(1.0 - r));
225
226 p = p0 + y * (p1 + y* (p2 + y * (p3 + y * p4)));
227 q = q0 + y * (q1 + y* (q2 + y * (q3 + y * q4)));
228
229 if(r < 0.5) z = (p / q) - y;
230 else z = y - (p / q);
231
232 randvec_[i] = Teuchos::as<ScalarType,double>(z);
233 }
234
235 return randvec_;
236 }
237
238 //
239 // Classes inputed through constructor that define the linear problem to be solved.
240 //
241 const Teuchos::RCP<LinearProblem<ScalarType,MV,OP,DM> > lp_;
242 const Teuchos::RCP<OutputManager<ScalarType> > om_;
243 const Teuchos::RCP<StatusTest<ScalarType,MV,OP,DM> > stest_;
244
245 //
246 // Algorithmic parameters
247 //
248 // numRHS_ is the current number of linear systems being solved.
249 int numRHS_;
250
251 //
252 // Current solver state
253 //
254 // initialized_ specifies that the basis vectors have been initialized and the iterate() routine
255 // is capable of running; _initialize is controlled by the initialize() member method
256 // For the implications of the state of initialized_, please see documentation for initialize()
257 bool initialized_;
258
259 // Current number of iterations performed.
260 int iter_;
261
262 // Current number of iterations performed.
263 bool assertPositiveDefiniteness_;
264
265 //
266 // State Storage
267 //
268 // Residual
269 Teuchos::RCP<MV> R_;
270 //
271 // Preconditioned residual
272 Teuchos::RCP<MV> Z_;
273 //
274 // Direction vector
275 Teuchos::RCP<MV> P_;
276 //
277 // Operator applied to direction vector
278 Teuchos::RCP<MV> AP_;
279 //
280 // Stochastic recurrence vector
281 Teuchos::RCP<MV> Y_;
282 //
283 // Stochastic variable storage (for normal() method)
284 Teuchos::SerialDenseVector<int,ScalarType> randvec_;
285
286 };
287
289 // Constructor.
290 template<class ScalarType, class MV, class OP, class DM>
292 const Teuchos::RCP<OutputManager<ScalarType> > &printer,
293 const Teuchos::RCP<StatusTest<ScalarType,MV,OP,DM> > &tester,
294 Teuchos::ParameterList &params ):
295 lp_(problem),
296 om_(printer),
297 stest_(tester),
298 numRHS_(0),
299 initialized_(false),
300 iter_(0),
301 assertPositiveDefiniteness_( params.get("Assert Positive Definiteness", true) )
302 {
303 }
304
305
307 // Initialize this iteration object
308 template<class ScalarType, class MV, class OP, class DM>
310 {
311 // Check if there is any multivector to clone from.
312 Teuchos::RCP<const MV> lhsMV = lp_->getCurrLHSVec();
313 Teuchos::RCP<const MV> rhsMV = lp_->getCurrRHSVec();
314 TEUCHOS_TEST_FOR_EXCEPTION((lhsMV==Teuchos::null && rhsMV==Teuchos::null),std::invalid_argument,
315 "Belos::PseudoBlockStochasticCGIter::initialize(): Cannot initialize state storage!");
316
317 // Get the multivector that is not null.
318 Teuchos::RCP<const MV> tmp = ( (rhsMV!=Teuchos::null)? rhsMV: lhsMV );
319
320 // Get the number of right-hand sides we're solving for now.
321 int numRHS = MVT::GetNumberVecs(*tmp);
322 numRHS_ = numRHS;
323
324 // Initialize the state storage
325 // If the subspace has not be initialized before or has changed sizes, generate it using the LHS or RHS from lp_.
326 if (Teuchos::is_null(R_) || MVT::GetNumberVecs(*R_)!=numRHS_) {
327 R_ = MVT::Clone( *tmp, numRHS_ );
328 Z_ = MVT::Clone( *tmp, numRHS_ );
329 P_ = MVT::Clone( *tmp, numRHS_ );
330 AP_ = MVT::Clone( *tmp, numRHS_ );
331 Y_ = MVT::Clone( *tmp, numRHS_ );
332 }
333
334 // Initialize the random vector container with zeros.
335 randvec_.size( numRHS_ );
336
337 // NOTE: In StochasticCGIter R_, the initial residual, is required!!!
338 //
339 std::string errstr("Belos::BlockPseudoStochasticCGIter::initialize(): Specified multivectors must have a consistent length and width.");
340
341 if (!Teuchos::is_null(newstate.R)) {
342
343 TEUCHOS_TEST_FOR_EXCEPTION( MVT::GetGlobalLength(*newstate.R) != MVT::GetGlobalLength(*R_),
344 std::invalid_argument, errstr );
345 TEUCHOS_TEST_FOR_EXCEPTION( MVT::GetNumberVecs(*newstate.R) != numRHS_,
346 std::invalid_argument, errstr );
347
348 // Copy basis vectors from newstate into V
349 if (newstate.R != R_) {
350 // copy over the initial residual (unpreconditioned).
351 MVT::Assign( *newstate.R, *R_ );
352 }
353
354 // Compute initial direction vectors
355 // Initially, they are set to the preconditioned residuals
356
357 if ( lp_->getLeftPrec() != Teuchos::null ) {
358 lp_->applyLeftPrec( *R_, *Z_ );
359 if ( lp_->getRightPrec() != Teuchos::null ) {
360 Teuchos::RCP<MV> tmp2 = MVT::Clone( *Z_, numRHS_ );
361 lp_->applyRightPrec( *Z_, *tmp2 );
362 Z_ = tmp2;
363 }
364 }
365 else if ( lp_->getRightPrec() != Teuchos::null ) {
366 lp_->applyRightPrec( *R_, *Z_ );
367 }
368 else {
369 Z_ = R_;
370 }
371 MVT::Assign( *Z_, *P_ );
372 }
373 else {
374
375 TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::is_null(newstate.R),std::invalid_argument,
376 "Belos::StochasticCGIter::initialize(): CGStateIterState does not have initial residual.");
377 }
378
379 // The solver is initialized
380 initialized_ = true;
381 }
382
383
385 // Iterate until the status test informs us we should stop.
386 template<class ScalarType, class MV, class OP, class DM>
388 {
389 //
390 // Allocate/initialize data structures
391 //
392 if (initialized_ == false) {
393 initialize();
394 }
395
396 // Allocate memory for scalars.
397 int i=0;
398 std::vector<int> index(1);
399 std::vector<ScalarType> rHz( numRHS_ ), rHz_old( numRHS_ ), pAp( numRHS_ ), beta( numRHS_ );
400 Teuchos::RCP<DM> alpha = DMT::Create( numRHS_,numRHS_ );
401 Teuchos::RCP<DM> zeta = DMT::Create( numRHS_,numRHS_ );
402
403 // Create convenience variables for zero and one.
404 const ScalarType one = Teuchos::ScalarTraits<ScalarType>::one();
405 const MagnitudeType zero = Teuchos::ScalarTraits<MagnitudeType>::zero();
406
407 // Get the current solution std::vector.
408 Teuchos::RCP<MV> cur_soln_vec = lp_->getCurrLHSVec();
409
410 // Compute first <r,z> a.k.a. rHz
411 MVT::MvDot( *R_, *Z_, rHz );
412
413 if ( assertPositiveDefiniteness_ )
414 for (i=0; i<numRHS_; ++i)
415 TEUCHOS_TEST_FOR_EXCEPTION( SCT::real(rHz[i]) < zero,
417 "Belos::PseudoBlockStochasticCGIter::iterate(): negative value for r^H*M*r encountered!" );
418
420 // Iterate until the status test tells us to stop.
421 //
422 while (stest_->checkStatus(this) != Passed) {
423
424 // Increment the iteration
425 iter_++;
426
427 // Multiply the current direction std::vector by A and store in AP_
428 lp_->applyOp( *P_, *AP_ );
429
430 // Compute alpha := <R_,Z_> / <P_,AP_>
431 MVT::MvDot( *P_, *AP_, pAp );
432
433 Teuchos::SerialDenseVector<int,ScalarType>& z = normal();
434
435 for (i=0; i<numRHS_; ++i) {
436 if ( assertPositiveDefiniteness_ )
437 // Check that pAp[i] is a positive number!
438 TEUCHOS_TEST_FOR_EXCEPTION( SCT::real(pAp[i]) <= zero,
440 "Belos::PseudoBlockStochasticCGIter::iterate(): non-positive value for p^H*A*p encountered!" );
441
442 DMT::Value(*alpha,i,i) = rHz[i] / pAp[i];
443
444 // Compute the scaling parameter for the stochastic vector
445 DMT::Value(*zeta,i,i) = z[i] / Teuchos::ScalarTraits<ScalarType>::squareroot(pAp[i]);
446 }
447 DMT::SyncDeviceToHost( *alpha );
448 DMT::SyncDeviceToHost( *zeta );
449
450 //
451 // Update the solution std::vector x := x + alpha * P_
452 //
453 MVT::MvTimesMatAddMv( one, *P_, *alpha, one, *cur_soln_vec );
454 lp_->updateSolution();
455
456 // Updates the stochastic vector y := y + zeta * P_
457 MVT::MvTimesMatAddMv( one, *P_, *zeta, one, *Y_);
458
459 //
460 // Save the denominator of beta before residual is updated [ old <R_, Z_> ]
461 //
462 for (i=0; i<numRHS_; ++i) {
463 rHz_old[i] = rHz[i];
464 }
465 //
466 // Compute the new residual R_ := R_ - alpha * AP_
467 //
468 MVT::MvTimesMatAddMv( -one, *AP_, *alpha, one, *R_ );
469 //
470 // Compute beta := [ new <R_, Z_> ] / [ old <R_, Z_> ],
471 // and the new direction std::vector p.
472 //
473 if ( lp_->getLeftPrec() != Teuchos::null ) {
474 lp_->applyLeftPrec( *R_, *Z_ );
475 if ( lp_->getRightPrec() != Teuchos::null ) {
476 Teuchos::RCP<MV> tmp = MVT::Clone( *Z_, numRHS_ );
477 lp_->applyRightPrec( *Z_, *tmp );
478 Z_ = tmp;
479 }
480 }
481 else if ( lp_->getRightPrec() != Teuchos::null ) {
482 lp_->applyRightPrec( *R_, *Z_ );
483 }
484 else {
485 Z_ = R_;
486 }
487 //
488 MVT::MvDot( *R_, *Z_, rHz );
489 if ( assertPositiveDefiniteness_ )
490 for (i=0; i<numRHS_; ++i)
491 TEUCHOS_TEST_FOR_EXCEPTION( SCT::real(rHz[i]) < zero,
493 "Belos::PseudoBlockStochasticCGIter::iterate(): negative value for r^H*M*r encountered!" );
494 //
495 // Update the search directions.
496 for (i=0; i<numRHS_; ++i) {
497 beta[i] = rHz[i] / rHz_old[i];
498 index[0] = i;
499 Teuchos::RCP<const MV> Z_i = MVT::CloneView( *Z_, index );
500 Teuchos::RCP<MV> P_i = MVT::CloneViewNonConst( *P_, index );
501 MVT::MvAddMv( one, *Z_i, beta[i], *P_i, *P_i );
502 }
503 //
504 } // end while (sTest_->checkStatus(this) != Passed)
505 }
506
507} // end Belos namespace
508
509#endif /* BELOS_PSEUDO_BLOCK_STOCHASTIC_CG_ITER_HPP */
Belos header file which uses auto-configuration information to include necessary C++ headers.
Class which describes the linear problem to be solved by the iterative solver.
Templated virtual class for providing orthogonalization/orthonormalization methods with matrix-based ...
Declaration of basic traits for the multivector type.
Class which defines basic traits for the operator type.
Class which manages the output and verbosity of the Belos solvers.
Pure virtual base class for defining the status testing capabilities of Belos.
Pure virtual base class which augments the basic interface for a stochastic conjugate gradient linear...
Collection of types and exceptions used within the Belos solvers.
CGPositiveDefiniteFailure is thrown when the the CG 'alpha = p^H*A*P' value is less than zero,...
Alternative run-time polymorphic interface for operators.
Operator()
Default constructor (does nothing).
This class implements the stochastic pseudo-block CG iteration, where the basic stochastic CG algorit...
int getBlockSize() const
Get the blocksize to be used by the iterative solver in solving this linear problem.
void resetNumIters(int iter=0)
Reset the iteration count.
const LinearProblem< ScalarType, MV, OP, DM > & getProblem() const
Get a constant reference to the linear problem.
Teuchos::RCP< MV > getCurrentUpdate() const
Get the current update to the linear system.
void setBlockSize(int blockSize)
Set the blocksize.
void iterate()
This method performs stochastic CG iterations on each linear system until the status test indicates t...
bool isInitialized()
States whether the solver has been initialized or not.
StochasticCGIterationState< ScalarType, MV > getState() const
Get the current state of the linear solver.
Teuchos::RCP< const MV > getNativeResiduals(std::vector< MagnitudeType > *) const
Get the norms of the residuals native to the solver.
Teuchos::RCP< MV > getStochasticVector() const
Get the stochastic vector
int getNumIters() const
Get the current iteration count.
void initialize()
Initialize the solver with the initial vectors from the linear problem or random data.
void initializeCG(StochasticCGIterationState< ScalarType, MV > &newstate)
Initialize the solver to an iterate, providing a complete state.
PseudoBlockStochasticCGIter(const Teuchos::RCP< LinearProblem< ScalarType, MV, OP, DM > > &problem, const Teuchos::RCP< OutputManager< ScalarType > > &printer, const Teuchos::RCP< StatusTest< ScalarType, MV, OP, DM > > &tester, Teuchos::ParameterList &params)
PseudoBlockStochasticCGIter constructor with linear problem, solver utilities, and parameter list of ...

Generated for Belos by doxygen 1.9.8