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