Пример #1
0
arma::mat Methods::implicitJacobi(double time) {
    /* method implicit Jacobi */
    arma::mat uPrev(n,n, arma::fill::zeros); //empty matrix for previous values
    arma::mat uNew(n,n, arma::fill::zeros); //empty matrix for new values
    arma::mat temp(n,n, arma::fill::zeros); //empty matrix for temporary values of uPrev
    
    double threshold = 0.000001; //convergance threshold
    double diff = threshold + 1; //difference of uPrev and temp

    //set initial value
    for(int j=0; j<n ;j++) {
        for(int i=0; i<n ;i++) {
            uPrev(i,j) = (1-j*h)*std::exp(i*h); //steady-state
        } //end j
    } //end i

    temp = uPrev; //set intial guess as previous value
   
    while(diff > threshold) {
        /* calculate new values */
        for(int i=1; i<n-1 ;i++) {
            for(int j=1; j<n-1 ;j++) {
                uNew(i,j) = (1./(1+4*alpha))*(uPrev(i,j) + 
                        alpha*(temp(i+1,j)+temp(i-1,j)+temp(i,j+1)+temp(i,j-1)));
            } //end j
        } //end i

        for(int k=0; k<n ;k++) {
            /* set boundary conditions (assume x=y=[0,1]) */
            double kn   = float(k)/n;
            uNew(0,k)   = (1-kn)*std::exp(time);
            uNew(n-1,k) = (1-kn)*std::exp(1+time);
            uNew(k,0)   = std::exp(kn+time);
            uNew(k,n-1) = 0;
        } //end k
        
        diff = 0; //reset diff
        for(int i=0; i<n ;i++) {
            /* calculate difference */
            for(int j=0; j<n ;j++) {
                diff += std::abs(temp(i,j) - uNew(i,j));
            } //end i
        } //end j
        diff /= n*n; //assuming our matrix is square
        
        temp = uPrev;
        uPrev = uNew; //keep temp
    } //end while

    return uNew;
} //end function implicitJacobi
Пример #2
0
arma::mat Methods::explicitEuler2D(double time) {
    /* methods explicit euler (in 2D) */
    arma::mat uPrev(n,n, arma::fill::zeros); //empty vector for previous values
    arma::mat uNew(n,n, arma::fill::zeros); //empty vector for new values
    
    //set initial value
    for(int j=0; j<n ;j++) {
        for(int i=0; i<n ;i++) {
            uPrev(i,j) = (1-j*h)*std::exp(i*h); //steady-state
        } //end j
    } //end i
   
    
    for(int t=1; t<=(time/wlk->dt) ;t++) {
        /* calculate new values */
        for(int i=1; i<n-1 ;i++) {
            for(int j=1; j<n-1 ;j++) {
                uNew(i,j) = uPrev(i,j) + alpha*(uPrev(i+1,j)+uPrev(i-1,j)
                        +uPrev(i,j+1)+uPrev(i,j-1)-4*uPrev(i,j));
            } //end j
        } //end i
        
        for(int k=0; k<n ;k++) {
            /* set boundary conditions (assume x=y=[0,1]) */
            double kn   = float(k)/n;
            uNew(0,k)   = (1-kn)*std::exp(time);
            uNew(n-1,k) = (1-kn)*std::exp(1+time);
            uNew(k,0)   = std::exp(kn+time);
            uNew(k,n-1) = 0;
        } //end k

        uPrev = uNew; //update value
    } //end t
    
    return uNew;
} //end function explicitEuler2D
void
StochBlockJacobiSolver::solve(const Array<LinearOperator<double> >& KBlock,
  const Array<int>& hasNonzeroMatrix,
  const Array<Vector<double> >& fBlock,
  Array<Vector<double> >& xBlock) const
{
  int L = KBlock.size();
  int P = pcBasis_.nterms();
  int Q = fBlock.size();

  /*
   * Solve the equations using block Gauss-Jacobi iteration
   */
  Array<Vector<double> > uPrev(P);
  Array<Vector<double> > uCur(P);

  for (int i=0; i<P; i++)
  {
    TEUCHOS_TEST_FOR_EXCEPTION(fBlock[0].ptr().get()==0, 
      std::runtime_error, "empty RHS vector block i=[" << i << "]");
    uPrev[i] = fBlock[0].copy();
    uCur[i] = fBlock[0].copy();
    uPrev[i].zero();
    uCur[i].zero();
  }

  if (verbosity_) Out::root() << "starting Jacobi loop" << std::endl;
  bool converged = false;
  for (int iter=0; iter<maxIters_; iter++)
  {
    if (verbosity_) Out::root() << "Jacobi iter=" << iter << std::endl;
    bool haveNonConvergedBlock = false;
    double maxErr = -1.0;
    int numNonzeroBlocks = 0;
    for (int i=0; i<P; i++)
    {
      if (verbosity_) Out::root() << "Iter " << iter << ": block row i=" << i << " of " << P << " ..." << ends;
      Vector<double> b = fBlock[0].copy();
      b.zero();
      int nVecAdds = 0;
      for (int j=0; j<Q; j++)
      {
        double c_ij0 = pcBasis_.expectation(i,j,0);
        if (std::fabs(c_ij0) > 0.0) 
        {
          b = b + c_ij0 * fBlock[j];
          nVecAdds++;
        }
        if (j>=L) continue; 
        if (!hasNonzeroMatrix[j]) continue;
        Vector<double> tmp = fBlock[0].copy();
        tmp.zero();
        bool blockIsNeeded = false;
        for (int k=0; k<P; k++)
        {
          if (j==0 && k==i) continue;
          double c_ijk = pcBasis_.expectation(i,j,k);
          if (std::fabs(c_ijk) > 0.0)
          {
            tmp = tmp + c_ijk * uPrev[k];
            nVecAdds++;
            blockIsNeeded = true;
          }
        }
        numNonzeroBlocks += blockIsNeeded;
        b = (b - KBlock[j]*tmp);
        nVecAdds++;
      }
      b = b * (1.0/pcBasis_.expectation(i,i,0));
      if (verbosity_) Out::root() << "num vec adds = " << nVecAdds << std::endl;
      diagonalSolver_.solve(KBlock[0], b, uCur[i]);
      double err = (uCur[i]-uPrev[i]).norm2();
      if (err > convTol_) haveNonConvergedBlock=true;
      if (err > maxErr) maxErr = err;
    }

    /* update solution blocks */
    for (int i=0; i<P; i++) uPrev[i] = uCur[i].copy();
      
    /* done all block rows -- check convergence */
    if (!haveNonConvergedBlock)
    {
      if (verbosity_) Out::root() << "=======> max err=" << maxErr << std::endl;
      if (verbosity_) Out::root() << "=======> converged! woo-hoo!" << std::endl;
      if (verbosity_) Out::root() << "estimated storage cost: " 
                  << setprecision(3) << 100*((double) L)/((double) numNonzeroBlocks) 
                  << " percent of monolithic storage" << std::endl;
      converged = true;
      break;
    }
    else
    {
      if (verbosity_) Out::root() << "maxErr=" << maxErr << ", trying again" << std::endl;
    }
  }

  TEUCHOS_TEST_FOR_EXCEPT(!converged);
  xBlock = uCur;
}