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
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
00096 for (int i=0; i<P; i++) uPrev[i] = uCur[i].copy();
00097
00098
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 }