BlockedBoundaryOperator<BasisFunctionType, ResultType>
modifiedHelmholtz3dInteriorCalderonProjector(
        const shared_ptr<const Context<BasisFunctionType,ResultType> >& context,
        const shared_ptr<const Space<BasisFunctionType> >& hminusSpace,
        const shared_ptr<const Space<BasisFunctionType> >& hplusSpace,
        KernelType waveNumber,
        const std::string& label,
        bool useInterpolation,
        int interpPtsPerWavelength) {

    typedef BoundaryOperator<BasisFunctionType,ResultType> BdOp;

    shared_ptr<const Space<BasisFunctionType> > internalHplusSpace = hplusSpace->discontinuousSpace(hplusSpace);

    BdOp internalSlp = modifiedHelmholtz3dSingleLayerBoundaryOperator(context,internalHplusSpace,internalHplusSpace,internalHplusSpace,waveNumber,label+"_slp",SYMMETRIC,
                                                                          useInterpolation,interpPtsPerWavelength);

    BdOp dlp = modifiedHelmholtz3dDoubleLayerBoundaryOperator(context,hplusSpace,hplusSpace,hminusSpace,waveNumber,label+"_dlp",NO_SYMMETRY,
                                                                                  useInterpolation,interpPtsPerWavelength);

    BdOp adjDlp = adjoint(dlp);

    BdOp hyp = modifiedHelmholtz3dHypersingularBoundaryOperator(context,hplusSpace,hminusSpace,hplusSpace,waveNumber,label+"_hyp",SYMMETRIC,
                                                                        useInterpolation,interpPtsPerWavelength,internalSlp);

    BdOp idSpaceTransformation1 = identityOperator(context,hminusSpace,internalHplusSpace,internalHplusSpace);
    BdOp idSpaceTransformation2 = identityOperator(context,internalHplusSpace,hplusSpace,hminusSpace);
    BdOp idDouble = identityOperator(context,hplusSpace,hplusSpace,hminusSpace);
    BdOp idAdjDouble = identityOperator(context,hminusSpace,hminusSpace,hplusSpace);

    // Now Assemble the entries of the Calderon Projector

    BlockedOperatorStructure<BasisFunctionType,ResultType> structure;

    structure.setBlock(0,0,.5*idDouble-dlp);
    structure.setBlock(0,1,idSpaceTransformation2*internalSlp*idSpaceTransformation1);
    structure.setBlock(1,0,hyp);
    structure.setBlock(1,1,.5*idAdjDouble+adjDlp);

    return BlockedBoundaryOperator<BasisFunctionType,ResultType>(structure);



}
示例#2
0
    // Constructor for non-blocked operators
    Impl(const BoundaryOperator<BasisFunctionType, ResultType>& op_,
         ConvergenceTestMode::Mode mode_) :
        op(op_),
        mode(mode_)
    {
        typedef BoundaryOperator<BasisFunctionType, ResultType> BoundaryOp;
        typedef Solver<BasisFunctionType, ResultType> Solver_;
        const BoundaryOp& boundaryOp = boost::get<BoundaryOp>(op);
        if (!boundaryOp.isInitialized())
            throw std::invalid_argument("DefaultIterativeSolver::Impl::Impl(): "
                                        "boundary operator must be initialized");

        if (mode == ConvergenceTestMode::TEST_CONVERGENCE_IN_DUAL_TO_RANGE) {
            if (boundaryOp.domain()->globalDofCount() !=
                    boundaryOp.dualToRange()->globalDofCount())
                throw std::invalid_argument("DefaultIterativeSolver::Impl::Impl(): "
                                            "non-square system provided");

            solverWrapper.reset(
                        new BelosSolverWrapper<ResultType>(
                            Teuchos::rcp<const Thyra::LinearOpBase<ResultType> >(
                                boundaryOp.weakForm())));
        }
        else if (mode == ConvergenceTestMode::TEST_CONVERGENCE_IN_RANGE) {
            if (boundaryOp.domain()->globalDofCount() !=
                    boundaryOp.range()->globalDofCount())
                throw std::invalid_argument("DefaultIterativeSolver::Impl::Impl(): "
                                            "non-square system provided");

            BoundaryOp id = identityOperator(
                        boundaryOp.context(), boundaryOp.range(), boundaryOp.range(),
                        boundaryOp.dualToRange());
            pinvId = pseudoinverse(id);
            shared_ptr<DiscreteBoundaryOperator<ResultType> > totalBoundaryOp =
                    boost::make_shared<DiscreteBoundaryOperatorComposition<ResultType> >(
                        boost::get<BoundaryOp>(pinvId).weakForm(),
                        boundaryOp.weakForm());
            solverWrapper.reset(
                        new BelosSolverWrapper<ResultType>(
                            Teuchos::rcp<const Thyra::LinearOpBase<ResultType> >(
                                totalBoundaryOp)));
        }
        else
            throw std::invalid_argument(
                    "DefaultIterativeSolver::DefaultIterativeSolver(): "
                    "invalid convergence test mode");
    }
inline bool LinearCombinationTester<Scalar>
::selfModifyingOpTests() const
{
  bool pass = true;

  RandomSparseMatrixBuilder<double> ABuilder(nLocalRows_, nLocalRows_, 
    onProcDensity_, offProcDensity_, 
    vecType_);
  RandomSparseMatrixBuilder<double> BBuilder(nLocalRows_, nLocalRows_, 
    onProcDensity_, offProcDensity_, 
    vecType_);
  RandomSparseMatrixBuilder<double> CBuilder(nLocalRows_, nLocalRows_, 
    onProcDensity_, offProcDensity_, 
    vecType_);


  LinearOperator<double> A = ABuilder.getOp();
  LinearOperator<double> B = BBuilder.getOp();
  LinearOperator<double> C = CBuilder.getOp();

  VectorSpace<Scalar> vs = A.domain();
  A = identityOperator(vs);
  B = identityOperator(vs);
  C = identityOperator(vs);

  Vector<Scalar> x = A.domain().createMember();
  Vector<Scalar> y = A.domain().createMember();
  Vector<Scalar> z = A.domain().createMember();

  this->randomizeVec(x);
  this->randomizeVec(y);
  this->randomizeVec(z);

  Vector<Scalar> a = x.copy();
  Vector<Scalar> b = y.copy();
  Vector<Scalar> c = z.copy();
    

  Out::os() << "starting linear combination tests" << std::endl;

  x = 2.0*A*x;
  Scalar err = (x - 2.0*A*a).norm2();
  if (!this->checkTest(spec_, err, "x=2.0*A*x")) pass = false;

  a = x.copy();
  x = x + y;
  err = (x - (a + y)).norm2();
  if (!this->checkTest(spec_, err, "x=x+y")) pass = false;

  a = x.copy();
  x = y + x;
  err = (x - (y + a)).norm2();
  if (!this->checkTest(spec_, err, "x=y+x")) pass = false;

  a = x.copy();
  x = A*x + B*y;
  err = (x - (A*a + B*y)).norm2();
  if (!this->checkTest(spec_, err, "x=A*x+B*y")) pass = false;

  a = x.copy();
  x = B*y + A*x;
  err = (x - (B*y + A*a)).norm2();
  if (!this->checkTest(spec_, err, "x=B*y+A*x")) pass = false;

  a = x.copy();
  x = A*x + (B*y + C*x);
  err = (x - (A*a + (B*y + C*a))).norm2();
  if (!this->checkTest(spec_, err, "x=A*x + (B*y + C*x)")) pass = false;

  a = x.copy();
  x = (A*x + B*y) + C*x;
  err = (x - ((A*a + B*y) + C*a)).norm2();
  if (!this->checkTest(spec_, err, "x=(A*x + B*y) + C*x")) pass = false;

  /* test assignment of OpTimesLC into empty and non-empty vectors */
  Vector<Scalar> u;
  u = 2.0*A*B*x;
  err = (u - 2.0*A*B*x).norm2();
  if (!this->checkTest(spec_, err, "(empty) u=2*A*B*x")) pass = false;

  u = 2.0*A*B*x;
  err = (u - 2.0*A*B*x).norm2();
  if (!this->checkTest(spec_, err, "(non-empty) u=2*A*B*x")) pass = false;

  /* test assignment of LC2 into empty and non-empty vectors */
  Vector<Scalar> v;
  v = 2.0*x + 3.0*y;
  err = (v - (2.0*x + 3.0*y)).norm2();
  if (!this->checkTest(spec_, err, "(empty) v=2*x + 3*y")) pass = false;

  v = 2.0*x + 3.0*y;
  err = (v - (2.0*x + 3.0*y)).norm2();
  if (!this->checkTest(spec_, err, "(non-empty) v=2*x + 3*y")) pass = false;

  /* test assignment of LC3 into empty and non-empty vectors */
  Vector<Scalar> w;
  w = 2.0*x + 3.0*y + 5.0*z;
  err = (w - (2.0*x + 3.0*y + 5.0*z)).norm2();
  if (!this->checkTest(spec_, err, "(empty) w=2*x + 3*y + 5*z")) pass = false;

  w = 2.0*x + 3.0*y + 5.0*z;
  err = (w - (2.0*x + 3.0*y + 5.0*z)).norm2();
  if (!this->checkTest(spec_, err, "(non-empty) w=2*x + 3*y + 5*z")) pass = false;

  /* test assignment of LC4 into empty and non-empty vectors */
  Vector<Scalar> w2;
  w2 = 2.0*x + 3.0*y + 5.0*z + 7.0*u;
  err = (w2 - (2.0*x + 3.0*y + 5.0*z + 7.0*u)).norm2();
  if (!this->checkTest(spec_, err, 
      "(empty) w2=2*x + 3*y + 5*z + 7*u")) pass = false;

  w2 = 2.0*x + 3.0*y + 5.0*z + 7.0*u;
  err = (w2 - (2.0*x + 3.0*y + 5.0*z + 7.0*u)).norm2();
  if (!this->checkTest(spec_, err, 
      "(non-empty) w2=2*x + 3*y + 5*z + 7*u")) pass = false;

  /* test assignment of LC3 into one of the operands */
  x = 2.0*x + 3.0*y + 5.0*z;
  err = (w - x).norm2(); // Note: w contains 2x + 3y + 5z 
  if (!this->checkTest(spec_, err, "x=2*x + 3*y + 5*z")) pass = false;


  return pass;
}
示例#4
0
    // Constructor for blocked operators
    Impl(const BlockedBoundaryOperator<BasisFunctionType, ResultType>& op_,
         ConvergenceTestMode::Mode mode_) :
        op(op_),
        mode(mode_)
    {
        typedef BlockedBoundaryOperator<BasisFunctionType, ResultType> BoundaryOp;
        typedef Solver<BasisFunctionType, ResultType> Solver_;
        const BoundaryOp& boundaryOp = boost::get<BoundaryOp>(op);

        if (mode == ConvergenceTestMode::TEST_CONVERGENCE_IN_DUAL_TO_RANGE) {
            if (boundaryOp.totalGlobalDofCountInDomains() !=
                    boundaryOp.totalGlobalDofCountInDualsToRanges())
                throw std::invalid_argument("DefaultIterativeSolver::Impl::Impl(): "
                                            "non-square system provided");
            solverWrapper.reset(
                        new BelosSolverWrapper<ResultType>(
                            Teuchos::rcp<const Thyra::LinearOpBase<ResultType> >(
                                boundaryOp.weakForm())));
        }
        else if (mode == ConvergenceTestMode::TEST_CONVERGENCE_IN_RANGE) {
            if (boundaryOp.totalGlobalDofCountInDomains() !=
                    boundaryOp.totalGlobalDofCountInRanges())
                throw std::invalid_argument("DefaultIterativeSolver::Impl::Impl(): "
                                            "non-square system provided");

            // Construct a block-diagonal operator composed of pseudoinverses
            // for appropriate spaces
            BlockedOperatorStructure<BasisFunctionType, ResultType> pinvIdStructure;
            size_t rowCount = boundaryOp.rowCount();
            size_t columnCount = boundaryOp.columnCount();
            for (size_t row = 0; row < rowCount; ++row) {
                // Find the first non-zero block in row #row and retrieve its context
                shared_ptr<const Context<BasisFunctionType, ResultType> > context;
                for (int col = 0; col < columnCount; ++col)
                    if (boundaryOp.block(row, col).context()) {
                        context = boundaryOp.block(row, col).context();
                        break;
                    }
                assert(context);

                BoundaryOperator<BasisFunctionType, ResultType> id = identityOperator(
                    context, boundaryOp.range(row), boundaryOp.range(row),
                    boundaryOp.dualToRange(row));
                pinvIdStructure.setBlock(row, row, pseudoinverse(id));
            }
            pinvId = BlockedBoundaryOperator<BasisFunctionType, ResultType>(
                pinvIdStructure);

            shared_ptr<DiscreteBoundaryOperator<ResultType> > totalBoundaryOp =
                    boost::make_shared<DiscreteBoundaryOperatorComposition<ResultType> >(
                        boost::get<BoundaryOp>(pinvId).weakForm(),
                        boundaryOp.weakForm());
            solverWrapper.reset(
                        new BelosSolverWrapper<ResultType>(
                            Teuchos::rcp<const Thyra::LinearOpBase<ResultType> >(
                                totalBoundaryOp)));
        }
        else
            throw std::invalid_argument(
                    "DefaultIterativeSolver::DefaultIterativeSolver(): "
                    "invalid convergence test mode");
    }