SundanceStochBlockJacobiSolver.cpp
Go to the documentation of this file.
00001 #include "SundanceStochBlockJacobiSolver.hpp"
00002 #include "Sundance.hpp"
00003 
00004 namespace Sundance
00005 {
00006 
00007 void
00008 StochBlockJacobiSolver::solve(const Array<LinearOperator<double> >& KBlock,
00009   const Array<Vector<double> >& fBlock,
00010   Array<Vector<double> >& xBlock) const
00011 {
00012   Array<int> hasNonzeroMatrix(KBlock.size());
00013   for (int i=0; i<KBlock.size(); i++) hasNonzeroMatrix[i] = true;
00014   
00015   solve(KBlock, hasNonzeroMatrix, fBlock, xBlock);
00016 }
00017 
00018 
00019 void
00020 StochBlockJacobiSolver::solve(const Array<LinearOperator<double> >& KBlock,
00021   const Array<int>& hasNonzeroMatrix,
00022   const Array<Vector<double> >& fBlock,
00023   Array<Vector<double> >& xBlock) const
00024 {
00025   int L = KBlock.size();
00026   int P = pcBasis_.nterms();
00027   int Q = fBlock.size();
00028 
00029   /*
00030    * Solve the equations using block Gauss-Jacobi iteration
00031    */
00032   Array<Vector<double> > uPrev(P);
00033   Array<Vector<double> > uCur(P);
00034 
00035   for (int i=0; i<P; i++)
00036   {
00037     TEST_FOR_EXCEPTION(fBlock[0].ptr().get()==0, 
00038       RuntimeError, "empty RHS vector block i=[" << i << "]");
00039     uPrev[i] = fBlock[0].copy();
00040     uCur[i] = fBlock[0].copy();
00041     uPrev[i].zero();
00042     uCur[i].zero();
00043   }
00044 
00045   if (verbosity_) Out::root() << "starting Jacobi loop" << std::endl;
00046   bool converged = false;
00047   for (int iter=0; iter<maxIters_; iter++)
00048   {
00049     if (verbosity_) Out::root() << "Jacobi iter=" << iter << std::endl;
00050     bool haveNonConvergedBlock = false;
00051     double maxErr = -1.0;
00052     int numNonzeroBlocks = 0;
00053     for (int i=0; i<P; i++)
00054     {
00055       if (verbosity_) Out::root() << "Iter " << iter << ": block row i=" << i << " of " << P << " ..." << ends;
00056       Vector<double> b = fBlock[0].copy();
00057       b.zero();
00058       int nVecAdds = 0;
00059       for (int j=0; j<Q; j++)
00060       {
00061         double c_ij0 = pcBasis_.expectation(i,j,0);
00062         if (std::fabs(c_ij0) > 0.0) 
00063         {
00064           b = b + c_ij0 * fBlock[j];
00065           nVecAdds++;
00066         }
00067         if (j>=L) continue; 
00068         if (!hasNonzeroMatrix[j]) continue;
00069         Vector<double> tmp = fBlock[0].copy();
00070         tmp.zero();
00071         bool blockIsNeeded = false;
00072         for (int k=0; k<P; k++)
00073         {
00074           if (j==0 && k==i) continue;
00075           double c_ijk = pcBasis_.expectation(i,j,k);
00076           if (std::fabs(c_ijk) > 0.0)
00077           {
00078             tmp = tmp + c_ijk * uPrev[k];
00079             nVecAdds++;
00080             blockIsNeeded = true;
00081           }
00082         }
00083         numNonzeroBlocks += blockIsNeeded;
00084         b = (b - KBlock[j]*tmp);
00085         nVecAdds++;
00086       }
00087       b = b * (1.0/pcBasis_.expectation(i,i,0));
00088       if (verbosity_) Out::root() << "num vec adds = " << nVecAdds << std::endl;
00089       diagonalSolver_.solve(KBlock[0], b, uCur[i]);
00090       double err = (uCur[i]-uPrev[i]).norm2();
00091       if (err > convTol_) haveNonConvergedBlock=true;
00092       if (err > maxErr) maxErr = err;
00093     }
00094 
00095     /* update solution blocks */
00096     for (int i=0; i<P; i++) uPrev[i] = uCur[i].copy();
00097       
00098     /* done all block rows -- check convergence */
00099     if (!haveNonConvergedBlock)
00100     {
00101       if (verbosity_) Out::root() << "=======> max err=" << maxErr << std::endl;
00102       if (verbosity_) Out::root() << "=======> converged! woo-hoo!" << std::endl;
00103       if (verbosity_) Out::root() << "estimated storage cost: " 
00104                   << setprecision(3) << 100*((double) L)/((double) numNonzeroBlocks) 
00105                   << " percent of monolithic storage" << std::endl;
00106       converged = true;
00107       break;
00108     }
00109     else
00110     {
00111       if (verbosity_) Out::root() << "maxErr=" << maxErr << ", trying again" << std::endl;
00112     }
00113   }
00114 
00115   TEST_FOR_EXCEPT(!converged);
00116   xBlock = uCur;
00117 }
00118 }

Site Contact