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); }
// 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; }
// 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"); }