14#ifndef ANASAZI_MINRES_HPP
15#define ANASAZI_MINRES_HPP
18#include "Teuchos_TimeMonitor.hpp"
23template <
class Scalar,
class MV,
class OP>
24class PseudoBlockMinres
33 PseudoBlockMinres(Teuchos::RCP<OP> A, Teuchos::RCP<OP> Prec = Teuchos::null);
36 void setTol(
const std::vector<Scalar>& tolerances) { tolerances_ = tolerances; };
37 void setMaxIter(
const int maxIt) { maxIt_ = maxIt; };
40 void setSol(Teuchos::RCP<MV> X) { X_ = X; };
41 void setRHS(Teuchos::RCP<const MV> B) { B_ = B; };
48 Teuchos::RCP<OP> Prec_;
50 Teuchos::RCP<const MV> B_;
51 std::vector<Scalar> tolerances_;
54 void symOrtho(Scalar a, Scalar b, Scalar *c, Scalar *s, Scalar *r);
56#ifdef ANASAZI_TEUCHOS_TIME_MONITOR
57 Teuchos::RCP<Teuchos::Time> AddTime_, ApplyOpTime_, ApplyPrecTime_, AssignTime_, DotTime_, LockTime_, NormTime_, ScaleTime_, TotalTime_;
63template <
class Scalar,
class MV,
class OP>
64PseudoBlockMinres<Scalar,MV,OP>::PseudoBlockMinres(Teuchos::RCP<OP> A, Teuchos::RCP<OP> Prec) :
65 ONE(Teuchos::ScalarTraits<Scalar>::one()),
66 ZERO(Teuchos::ScalarTraits<Scalar>::zero())
68#ifdef ANASAZI_TEUCHOS_TIME_MONITOR
69 AddTime_ = Teuchos::TimeMonitor::getNewTimer(
"Anasazi: PseudoBlockMinres::Add Multivectors");
70 ApplyOpTime_ = Teuchos::TimeMonitor::getNewTimer(
"Anasazi: PseudoBlockMinres::Apply Operator");
71 ApplyPrecTime_ = Teuchos::TimeMonitor::getNewTimer(
"Anasazi: PseudoBlockMinres::Apply Preconditioner");
72 AssignTime_ = Teuchos::TimeMonitor::getNewTimer(
"Anasazi: PseudoBlockMinres::Assignment (no locking)");
73 DotTime_ = Teuchos::TimeMonitor::getNewTimer(
"Anasazi: PseudoBlockMinres::Compute Dot Product");
74 LockTime_ = Teuchos::TimeMonitor::getNewTimer(
"Anasazi: PseudoBlockMinres::Lock Converged Vectors");
75 NormTime_ = Teuchos::TimeMonitor::getNewTimer(
"Anasazi: PseudoBlockMinres::Compute Norm");
76 ScaleTime_ = Teuchos::TimeMonitor::getNewTimer(
"Anasazi: PseudoBlockMinres::Scale Multivector");
77 TotalTime_ = Teuchos::TimeMonitor::getNewTimer(
"Anasazi: PseudoBlockMinres::Total Time");
87template <
class Scalar,
class MV,
class OP>
88void PseudoBlockMinres<Scalar,MV,OP>::solve()
90 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
91 Teuchos::TimeMonitor outertimer( *TotalTime_ );
95 int ncols = MVT::GetNumberVecs(*B_);
99 std::vector<Scalar> alpha(ncols), beta, beta1(ncols), phibar, oldBeta(ncols,ZERO), epsln(ncols,ZERO), cs(ncols,-ONE), sn(ncols,ZERO), dbar(ncols,ZERO), oldeps(ncols), delta(ncols), gbar(ncols), phi(ncols), gamma(ncols), tmpvec(ncols);
100 std::vector<int> indicesToRemove, newlyConverged, unconvergedIndices(ncols);
101 Teuchos::RCP<MV> V, Y, R1, R2, W, W1, W2, locX, scaleHelper, swapHelper;
104 V = MVT::Clone(*B_, ncols);
105 Y = MVT::Clone(*B_, ncols);
106 R1 = MVT::Clone(*B_, ncols);
107 R2 = MVT::Clone(*B_, ncols);
108 W = MVT::Clone(*B_, ncols);
109 W1 = MVT::Clone(*B_, ncols);
110 W2 = MVT::Clone(*B_, ncols);
111 scaleHelper = MVT::Clone(*B_, ncols);
114 indicesToRemove.reserve(ncols);
115 newlyConverged.reserve(ncols);
118 for(
int i=0; i<ncols; i++)
119 unconvergedIndices[i] = i;
123 locX = MVT::CloneCopy(*X_);
128 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
129 Teuchos::TimeMonitor lcltimer( *ApplyOpTime_ );
131 OPT::Apply(*A_,*locX,*R1);
134 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
135 Teuchos::TimeMonitor lcltimer( *AddTime_ );
137 MVT::MvAddMv(ONE, *B_, -ONE, *R1, *R1);
142 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
143 Teuchos::TimeMonitor lcltimer( *AssignTime_ );
145 MVT::Assign(*R1,*R2);
153 if(Prec_ != Teuchos::null)
155 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
156 Teuchos::TimeMonitor lcltimer( *ApplyPrecTime_ );
159 OPT::Apply(*Prec_,*R1,*Y);
163 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
164 Teuchos::TimeMonitor lcltimer( *AssignTime_ );
171 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
172 Teuchos::TimeMonitor lcltimer( *DotTime_ );
174 MVT::MvDot(*Y,*R1, beta1);
176 for(
size_t i=0; i<beta1.size(); i++)
177 beta1[i] = sqrt(beta1[i]);
188 for(
int iter=1; iter <= maxIt_; iter++)
191 indicesToRemove.clear();
192 for(
int i=0; i<ncols; i++)
194 Scalar relres = phibar[i]/beta1[i];
199 if(relres < tolerances_[i])
201 indicesToRemove.push_back(i);
206 newNumConverged = indicesToRemove.size();
207 if(newNumConverged > 0)
209 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
210 Teuchos::TimeMonitor lcltimer( *LockTime_ );
214 newlyConverged.resize(newNumConverged);
215 for(
int i=0; i<newNumConverged; i++)
216 newlyConverged[i] = unconvergedIndices[indicesToRemove[i]];
218 Teuchos::RCP<MV> helperLocX = MVT::CloneCopy(*locX,indicesToRemove);
220 MVT::SetBlock(*helperLocX,newlyConverged,*X_);
223 if(newNumConverged == ncols)
227 std::vector<int> helperVec(ncols - newNumConverged);
229 std::set_difference(unconvergedIndices.begin(), unconvergedIndices.end(), newlyConverged.begin(), newlyConverged.end(), helperVec.begin());
230 unconvergedIndices = helperVec;
233 std::vector<int> thingsToKeep(ncols - newNumConverged);
234 helperVec.resize(ncols);
235 for(
int i=0; i<ncols; i++)
237 ncols = ncols - newNumConverged;
239 std::set_difference(helperVec.begin(), helperVec.end(), indicesToRemove.begin(), indicesToRemove.end(), thingsToKeep.begin());
242 Teuchos::RCP<MV> helperMV;
243 helperMV = MVT::CloneCopy(*V,thingsToKeep);
245 helperMV = MVT::CloneCopy(*Y,thingsToKeep);
247 helperMV = MVT::CloneCopy(*R1,thingsToKeep);
249 helperMV = MVT::CloneCopy(*R2,thingsToKeep);
251 helperMV = MVT::CloneCopy(*W,thingsToKeep);
253 helperMV = MVT::CloneCopy(*W1,thingsToKeep);
255 helperMV = MVT::CloneCopy(*W2,thingsToKeep);
257 helperMV = MVT::CloneCopy(*locX,thingsToKeep);
259 scaleHelper = MVT::Clone(*V,ncols);
263 oldeps.resize(ncols);
268 tmpvec.resize(ncols);
269 std::vector<Scalar> helperVecS(ncols);
270 for(
int i=0; i<ncols; i++)
271 helperVecS[i] = beta[thingsToKeep[i]];
273 for(
int i=0; i<ncols; i++)
274 helperVecS[i] = beta1[thingsToKeep[i]];
276 for(
int i=0; i<ncols; i++)
277 helperVecS[i] = phibar[thingsToKeep[i]];
279 for(
int i=0; i<ncols; i++)
280 helperVecS[i] = oldBeta[thingsToKeep[i]];
281 oldBeta = helperVecS;
282 for(
int i=0; i<ncols; i++)
283 helperVecS[i] = epsln[thingsToKeep[i]];
285 for(
int i=0; i<ncols; i++)
286 helperVecS[i] = cs[thingsToKeep[i]];
288 for(
int i=0; i<ncols; i++)
289 helperVecS[i] = sn[thingsToKeep[i]];
291 for(
int i=0; i<ncols; i++)
292 helperVecS[i] = dbar[thingsToKeep[i]];
296 A_->removeIndices(indicesToRemove);
302 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
303 Teuchos::TimeMonitor lcltimer( *AssignTime_ );
307 for(
int i=0; i<ncols; i++)
308 tmpvec[i] = ONE/beta[i];
310 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
311 Teuchos::TimeMonitor lcltimer( *ScaleTime_ );
313 MVT::MvScale (*V, tmpvec);
319 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
320 Teuchos::TimeMonitor lcltimer( *ApplyOpTime_ );
322 OPT::Apply(*A_, *V, *Y);
328 for(
int i=0; i<ncols; i++)
329 tmpvec[i] = beta[i]/oldBeta[i];
331 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
332 Teuchos::TimeMonitor lcltimer( *AssignTime_ );
334 MVT::Assign(*R1,*scaleHelper);
337 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
338 Teuchos::TimeMonitor lcltimer( *ScaleTime_ );
340 MVT::MvScale(*scaleHelper,tmpvec);
343 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
344 Teuchos::TimeMonitor lcltimer( *AddTime_ );
346 MVT::MvAddMv(ONE, *Y, -ONE, *scaleHelper, *Y);
352 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
353 Teuchos::TimeMonitor lcltimer( *DotTime_ );
355 MVT::MvDot(*V, *Y, alpha);
359 for(
int i=0; i<ncols; i++)
360 tmpvec[i] = alpha[i]/beta[i];
362 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
363 Teuchos::TimeMonitor lcltimer( *AssignTime_ );
365 MVT::Assign(*R2,*scaleHelper);
368 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
369 Teuchos::TimeMonitor lcltimer( *ScaleTime_ );
371 MVT::MvScale(*scaleHelper,tmpvec);
374 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
375 Teuchos::TimeMonitor lcltimer( *AddTime_ );
377 MVT::MvAddMv(ONE, *Y, -ONE, *scaleHelper, *Y);
388 if(Prec_ != Teuchos::null)
390 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
391 Teuchos::TimeMonitor lcltimer( *ApplyPrecTime_ );
394 OPT::Apply(*Prec_,*R2,*Y);
398 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
399 Teuchos::TimeMonitor lcltimer( *AssignTime_ );
408 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
409 Teuchos::TimeMonitor lcltimer( *DotTime_ );
411 MVT::MvDot(*Y,*R2, beta);
413 for(
int i=0; i<ncols; i++)
414 beta[i] = sqrt(beta[i]);
419 for(
int i=0; i<ncols; i++)
421 delta[i] = cs[i]*dbar[i] + sn[i]*alpha[i];
422 gbar[i] = sn[i]*dbar[i] - cs[i]*alpha[i];
423 epsln[i] = sn[i]*beta[i];
424 dbar[i] = - cs[i]*beta[i];
428 for(
int i=0; i<ncols; i++)
430 symOrtho(gbar[i], beta[i], &cs[i], &sn[i], &gamma[i]);
432 phi[i] = cs[i]*phibar[i];
433 phibar[i] = sn[i]*phibar[i];
445 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
446 Teuchos::TimeMonitor lcltimer( *AssignTime_ );
448 MVT::Assign(*W1,*scaleHelper);
451 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
452 Teuchos::TimeMonitor lcltimer( *ScaleTime_ );
454 MVT::MvScale(*scaleHelper,oldeps);
457 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
458 Teuchos::TimeMonitor lcltimer( *AddTime_ );
460 MVT::MvAddMv(ONE, *V, -ONE, *scaleHelper, *W);
463 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
464 Teuchos::TimeMonitor lcltimer( *AssignTime_ );
466 MVT::Assign(*W2,*scaleHelper);
469 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
470 Teuchos::TimeMonitor lcltimer( *ScaleTime_ );
472 MVT::MvScale(*scaleHelper,delta);
475 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
476 Teuchos::TimeMonitor lcltimer( *AddTime_ );
478 MVT::MvAddMv(ONE, *W, -ONE, *scaleHelper, *W);
480 for(
int i=0; i<ncols; i++)
481 tmpvec[i] = ONE/gamma[i];
483 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
484 Teuchos::TimeMonitor lcltimer( *ScaleTime_ );
486 MVT::MvScale(*W,tmpvec);
492 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
493 Teuchos::TimeMonitor lcltimer( *AssignTime_ );
495 MVT::Assign(*W,*scaleHelper);
498 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
499 Teuchos::TimeMonitor lcltimer( *ScaleTime_ );
501 MVT::MvScale(*scaleHelper,phi);
504 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
505 Teuchos::TimeMonitor lcltimer( *AddTime_ );
507 MVT::MvAddMv(ONE, *locX, ONE, *scaleHelper, *locX);
513 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
514 Teuchos::TimeMonitor lcltimer( *AssignTime_ );
516 MVT::SetBlock(*locX,unconvergedIndices,*X_);
520template <
class Scalar,
class MV,
class OP>
521void PseudoBlockMinres<Scalar,MV,OP>::symOrtho(Scalar a, Scalar b, Scalar *c, Scalar *s, Scalar *r)
523 const Scalar absA = std::abs(a);
524 const Scalar absB = std::abs(b);
525 if ( absB == ZERO ) {
532 }
else if ( absA == ZERO ) {
536 }
else if ( absB >= absA ) {
539 *s = -ONE / sqrt( ONE+tau*tau );
541 *s = ONE / sqrt( ONE+tau*tau );
547 *c = -ONE / sqrt( ONE+tau*tau );
549 *c = ONE / sqrt( ONE+tau*tau );
Anasazi header file which uses auto-configuration information to include necessary C++ headers.
Anasazi's templated virtual class for constructing an operator that can interface with the OperatorTr...
Namespace Anasazi contains the classes, structs, enums and utilities used by the Anasazi package.