SundanceStochBlockJacobiSolver.cpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                             Sundance
00005 //                 Copyright 2011 Sandia Corporation
00006 // 
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Kevin Long (kevin.long@ttu.edu)
00038 // 
00039 
00040 /* @HEADER@ */
00041 
00042 
00043 #include "SundanceStochBlockJacobiSolver.hpp"
00044 #include "Sundance.hpp"
00045 
00046 
00047 
00048 #ifndef HAVE_TEUCHOS_EXPLICIT_INSTANTIATION
00049 #include "PlayaVectorImpl.hpp"
00050 #endif
00051 
00052 
00053 
00054 namespace Sundance
00055 {
00056 
00057   using std::ends;
00058   using std::setprecision;
00059 
00060 void
00061 StochBlockJacobiSolver::solve(const Array<LinearOperator<double> >& KBlock,
00062   const Array<Vector<double> >& fBlock,
00063   Array<Vector<double> >& xBlock) const
00064 {
00065   Array<int> hasNonzeroMatrix(KBlock.size());
00066   for (int i=0; i<KBlock.size(); i++) hasNonzeroMatrix[i] = true;
00067   
00068   solve(KBlock, hasNonzeroMatrix, fBlock, xBlock);
00069 }
00070 
00071 
00072 void
00073 StochBlockJacobiSolver::solve(const Array<LinearOperator<double> >& KBlock,
00074   const Array<int>& hasNonzeroMatrix,
00075   const Array<Vector<double> >& fBlock,
00076   Array<Vector<double> >& xBlock) const
00077 {
00078   int L = KBlock.size();
00079   int P = pcBasis_.nterms();
00080   int Q = fBlock.size();
00081 
00082   /*
00083    * Solve the equations using block Gauss-Jacobi iteration
00084    */
00085   Array<Vector<double> > uPrev(P);
00086   Array<Vector<double> > uCur(P);
00087 
00088   for (int i=0; i<P; i++)
00089   {
00090     TEUCHOS_TEST_FOR_EXCEPTION(fBlock[0].ptr().get()==0, 
00091       std::runtime_error, "empty RHS vector block i=[" << i << "]");
00092     uPrev[i] = fBlock[0].copy();
00093     uCur[i] = fBlock[0].copy();
00094     uPrev[i].zero();
00095     uCur[i].zero();
00096   }
00097 
00098   if (verbosity_) Out::root() << "starting Jacobi loop" << std::endl;
00099   bool converged = false;
00100   for (int iter=0; iter<maxIters_; iter++)
00101   {
00102     if (verbosity_) Out::root() << "Jacobi iter=" << iter << std::endl;
00103     bool haveNonConvergedBlock = false;
00104     double maxErr = -1.0;
00105     int numNonzeroBlocks = 0;
00106     for (int i=0; i<P; i++)
00107     {
00108       if (verbosity_) Out::root() << "Iter " << iter << ": block row i=" << i << " of " << P << " ..." << ends;
00109       Vector<double> b = fBlock[0].copy();
00110       b.zero();
00111       int nVecAdds = 0;
00112       for (int j=0; j<Q; j++)
00113       {
00114         double c_ij0 = pcBasis_.expectation(i,j,0);
00115         if (std::fabs(c_ij0) > 0.0) 
00116         {
00117           b = b + c_ij0 * fBlock[j];
00118           nVecAdds++;
00119         }
00120         if (j>=L) continue; 
00121         if (!hasNonzeroMatrix[j]) continue;
00122         Vector<double> tmp = fBlock[0].copy();
00123         tmp.zero();
00124         bool blockIsNeeded = false;
00125         for (int k=0; k<P; k++)
00126         {
00127           if (j==0 && k==i) continue;
00128           double c_ijk = pcBasis_.expectation(i,j,k);
00129           if (std::fabs(c_ijk) > 0.0)
00130           {
00131             tmp = tmp + c_ijk * uPrev[k];
00132             nVecAdds++;
00133             blockIsNeeded = true;
00134           }
00135         }
00136         numNonzeroBlocks += blockIsNeeded;
00137         b = (b - KBlock[j]*tmp);
00138         nVecAdds++;
00139       }
00140       b = b * (1.0/pcBasis_.expectation(i,i,0));
00141       if (verbosity_) Out::root() << "num vec adds = " << nVecAdds << std::endl;
00142       diagonalSolver_.solve(KBlock[0], b, uCur[i]);
00143       double err = (uCur[i]-uPrev[i]).norm2();
00144       if (err > convTol_) haveNonConvergedBlock=true;
00145       if (err > maxErr) maxErr = err;
00146     }
00147 
00148     /* update solution blocks */
00149     for (int i=0; i<P; i++) uPrev[i] = uCur[i].copy();
00150       
00151     /* done all block rows -- check convergence */
00152     if (!haveNonConvergedBlock)
00153     {
00154       if (verbosity_) Out::root() << "=======> max err=" << maxErr << std::endl;
00155       if (verbosity_) Out::root() << "=======> converged! woo-hoo!" << std::endl;
00156       if (verbosity_) Out::root() << "estimated storage cost: " 
00157                   << setprecision(3) << 100*((double) L)/((double) numNonzeroBlocks) 
00158                   << " percent of monolithic storage" << std::endl;
00159       converged = true;
00160       break;
00161     }
00162     else
00163     {
00164       if (verbosity_) Out::root() << "maxErr=" << maxErr << ", trying again" << std::endl;
00165     }
00166   }
00167 
00168   TEUCHOS_TEST_FOR_EXCEPT(!converged);
00169   xBlock = uCur;
00170 }
00171 }

Site Contact