コード例 #1
0
int main(int argc, char *argv[]) 
{
  int stat = 0;
  try
  {
    GlobalMPISession session(&argc, &argv);
    MPIComm::world().synchronize();

    Out::os() << "go!" << std::endl;
    VectorType<double> type = new EpetraVectorType();

    Array<int> domainBlockSizes = tuple(2,3,4);
    Array<int> rangeBlockSizes = tuple(2,2);

    Array<VectorSpace<double> > domainBlocks(domainBlockSizes.size());
    Array<VectorSpace<double> > rangeBlocks(rangeBlockSizes.size());

    for (int i=0; i<domainBlocks.size(); i++)
    {
      domainBlocks[i] = type.createEvenlyPartitionedSpace(MPIComm::world(),
        domainBlockSizes[i]);
    }

    for (int i=0; i<rangeBlocks.size(); i++)
    {
      rangeBlocks[i] = type.createEvenlyPartitionedSpace(MPIComm::world(),
        rangeBlockSizes[i]);
    }
      
    VectorSpace<double> domain = blockSpace(domainBlocks);
    VectorSpace<double> range = blockSpace(rangeBlocks);

    double blockDensity = 0.75;
    double onProcDensity = 0.5;
    double offProcDensity = 0.1;
      
    RandomBlockMatrixBuilder<double> builder(domain, range, 
      blockDensity,
      onProcDensity,
      offProcDensity,
      type);

    LinearOperator<double> A = builder.getOp();

    Out::os() << "A num block rows = " << A.numBlockRows() << std::endl;
    Out::os() << "A num block cols = " << A.numBlockCols() << std::endl;

    Vector<double> x = domain.createMember();
    Out::os() << "randomizing trial vector" << std::endl;
    x.randomize();

    Array<Vector<double> > xBlock(domain.numBlocks());
    for (int i=0; i<xBlock.size(); i++)
    {
      xBlock[i] = x.getBlock(i);
    }

    Vector<double> xx = x.copy();

      

    Out::os() << "------------------------------------------------------------" << std::endl;
    Out::os() << "computing A*x..." << std::endl;
    Vector<double> y0 = A * x;
    for (int i=0; i<y0.space().numBlocks(); i++)
    {
      Out::os() << "y0[" << i << "] = " << std::endl << y0.getBlock(i) << std::endl;
    }
      

    Vector<double> y1 = range.createMember();
    Out::os() << "------------------------------------------------------------" << std::endl;
    Out::os() << "computing A*x block-by-block..." << std::endl;
    Array<Vector<double> > yBlock(range.numBlocks());
    for (int i=0; i<yBlock.size(); i++)
    {
      yBlock[i] = range.getBlock(i).createMember();
      yBlock[i].zero();
      for (int j=0; j<xBlock.size(); j++)
      {
        LinearOperator<double> Aij = A.getBlock(i,j);
        if (Aij.ptr().get() != 0)
        {
          Out::os() << "A(" << i << ", " << j << ") = " << std::endl 
                    << Aij << std::endl;
        }
        else
        {
          Out::os() << "A(" << i << ", " << j << ") = 0 " << std::endl;
        }
        Out::os() << "x[" << j << "] = " << std::endl << xBlock[j] << std::endl;
        if (Aij.ptr().get()==0) continue;
        yBlock[i] = yBlock[i] + Aij * xBlock[j];
      }
      y1.setBlock(i, yBlock[i]);
    }

    for (int i=0; i<y1.space().numBlocks(); i++)
    {
      Out::os() << "y1[" << i << "] = " << std::endl << y1.getBlock(i) << std::endl;
    }
    double err = (y1 - y0).norm2();
    Out::os() << "error = " << err << std::endl;

    double tol = 1.0e-13;
    if (err < tol)
    {
      Out::os() << "block op test PASSED" << std::endl;
    }
    else
    {
      stat = -1;
      Out::os() << "block op test FAILED" << std::endl;
    }
  }
  catch(std::exception& e)
  {
    stat = -1;
    Out::os() << "Caught exception: " << e.what() << std::endl;
  }
  return stat;
}
コード例 #2
0
  template <class Scalar> inline
  SolverState<Scalar> BlockTriangularSolver<Scalar>
  ::solve(const LinearOperator<Scalar>& op,
          const Vector<Scalar>& rhs,
          Vector<Scalar>& soln) const
  {
    int nRows = op.numBlockRows();
    int nCols = op.numBlockCols();

    soln = op.domain().createMember();
    //    bool converged = false;

    TEST_FOR_EXCEPTION(nRows != rhs.space().numBlocks(), std::runtime_error,
                       "number of rows in operator " << op
                       << " not equal to number of blocks on RHS "
                       << rhs);

    TEST_FOR_EXCEPTION(nRows != nCols, std::runtime_error,
                       "nonsquare block structure in block triangular "
                       "solver: nRows=" << nRows << " nCols=" << nCols);

    bool isUpper = false;
    bool isLower = false;

    for (int r=0; r<nRows; r++)
      {
        for (int c=0; c<nCols; c++)
          {
            if (op.getBlock(r,c).ptr().get() == 0 ||
                dynamic_cast<const SimpleZeroOp<Scalar>* >(op.getBlock(r,c).ptr().get()))
              {
                TEST_FOR_EXCEPTION(r==c, std::runtime_error,
                                   "zero diagonal block (" << r << ", " << c 
                                   << " detected in block "
                                   "triangular solver. Operator is " << op);
                continue;
              }
            else
              {
                if (r < c) isUpper = true;
                if (c < r) isLower = true;
              }
          }
      }

    TEST_FOR_EXCEPTION(isUpper && isLower, std::runtime_error, 
                       "block triangular solver detected non-triangular operator "
                       << op);

    bool oneSolverFitsAll = false;
    if ((int) solvers_.size() == 1 && nRows != 1) 
      {
        oneSolverFitsAll = true;
      }

    for (int i=0; i<nRows; i++)
      {
        int r = i;
        if (isUpper) r = nRows - 1 - i;
        Vector<Scalar> rhs_r = rhs.getBlock(r);
        for (int j=0; j<i; j++)
          {
            int c = j;
            if (isUpper) c = nCols - 1 - j;
            if (op.getBlock(r,c).ptr().get() != 0)
              {
                rhs_r = rhs_r - op.getBlock(r,c) * soln.getBlock(c);
              }
          }

        SolverState<Scalar> state;
        Vector<Scalar> soln_r;
        if (oneSolverFitsAll)
          {
            state = solvers_[0].solve(op.getBlock(r,r), rhs_r, soln_r);
          }
        else
          {
            state = solvers_[r].solve(op.getBlock(r,r), rhs_r, soln_r);
          }
        if (nRows > 1) soln.setBlock(r, soln_r);
        else soln = soln_r;
        if (state.finalState() != SolveConverged)
          {
            return state;
          }
      }

    return SolverState<Scalar>(SolveConverged, "block solves converged",
                               0, ScalarTraits<Scalar>::zero());
  }