コード例 #1
0
BOOST_AUTO_TEST_CASE_TEMPLATE(boundary_operator_agrees_with_2x2_blocked_boundary_operator,
                              ValueType, result_types)
{
    typedef ValueType RT;
    typedef typename ScalarTraits<ValueType>::RealType RealType;
    typedef RealType BFT;

    typedef Bempp::DefaultDirectSolver<BFT, RT> DirectSolver;
    const RealType solverTol = 1e-5;

    Laplace3dDirichletFixture<BFT, RT> fixture;

    arma::Col<RT> solutionVectorNonblocked;

    // Solve using nonblocked operator
    {
        DirectSolver solver(fixture.lhsOp);       
        Solution<BFT, RT> solution = solver.solve(fixture.rhs);
        solutionVectorNonblocked = solution.gridFunction().coefficients();
    }

    // Solve using 2x2 ([A, 0 * A; 0, A]) blocked operator
    {
        BlockedOperatorStructure<BFT, RT> structure;
        structure.setBlock(0, 0, fixture.lhsOp);
        structure.setBlock(0, 1, 0. * fixture.lhsOp);
        structure.setBlock(1, 1, fixture.lhsOp);
        
        BlockedBoundaryOperator<BFT, RT> lhsBlockedOp(structure);
        std::vector<GridFunction<BFT, RT> > blockedRhs(2);
        blockedRhs[0] = fixture.rhs;
        blockedRhs[1] = 2. * fixture.rhs;

        DirectSolver solver(lhsBlockedOp);       
        BlockedSolution<BFT, RT> solution = solver.solve(blockedRhs);
        arma::Col<RT> solutionVectorBlock0 = solution.gridFunction(0).coefficients();
        arma::Col<RT> solutionVectorBlock1 = solution.gridFunction(1).coefficients() / 2.;

        BOOST_CHECK(check_arrays_are_close<ValueType>(
                        solutionVectorNonblocked, solutionVectorBlock0, solverTol * 10));
        BOOST_CHECK(check_arrays_are_close<ValueType>(
                        solutionVectorNonblocked, solutionVectorBlock1, solverTol * 10));
    }
}
コード例 #2
0
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);



}
コード例 #3
0
ファイル: dot_two_layers.cpp プロジェクト: UCL/bempp
int main(int argc, char* argv[])
{
    // Physical parameters, general
    const BFT c0 = 0.3;      // speed of light in vacuum [mm/ps]
    BFT refind = 1.4; // refractive index
    BFT alpha = A_Keijzer(refind); // boundary term
    BFT c = c0/refind;       // speed of light in medium [mm/ps]
    BFT freq = 100*1e6; // modulation frequency [Hz]
    BFT omega = 2.0*M_PI * freq*1e-12; // modulation frequency [cycles/ps]

    // Physical parameters, outer region
    BFT mua1 = 0.01; // absorption coefficient
    BFT mus1 = 1.0;  // scattering coefficient
    BFT kappa1 = 1.0/(3.0*(mua1+mus1));   // diffusion coefficient
    RT waveNumber1 = sqrt (RT(mua1/kappa1, omega/(c*kappa1))); // outer region

    // Physical parameters, inner region
    BFT mua2 = 0.02; // absorption coefficient
    BFT mus2 = 0.5;  // scattering coefficient
    BFT kappa2 = 1.0/(3.0*(mua2+mus2));   // diffusion coefficient
    RT waveNumber2 = sqrt (RT(mua2/kappa2, omega/(c*kappa2))); // outer region

    // Create sphere meshes on the fly
    shared_ptr<Grid> grid1 = CreateSphere(25.0, 1.0);
    shared_ptr<Grid> grid2 = CreateSphere(15.0, 1.0);

    // Initialize the spaces

    PiecewiseLinearContinuousScalarSpace<BFT> HplusHalfSpace1(grid1);
    PiecewiseLinearContinuousScalarSpace<BFT> HplusHalfSpace2(grid2);

    // Define some default options.

    AssemblyOptions assemblyOptions;

    // We want to use ACA

    AcaOptions acaOptions; // Default parameters for ACA
    acaOptions.eps = 1e-5;
    assemblyOptions.switchToAcaMode(acaOptions);

    // Define the standard integration factory

    AccuracyOptions accuracyOptions;
    accuracyOptions.doubleRegular.setRelativeQuadratureOrder(2);
    accuracyOptions.singleRegular.setRelativeQuadratureOrder(1);
    NumericalQuadratureStrategy<BFT, RT> quadStrategy(accuracyOptions);
    Context<BFT, RT> context(make_shared_from_ref(quadStrategy), assemblyOptions);

    // We need the single layer, double layer, and the identity operator

    // mesh1 x mesh1
    BoundaryOperator<BFT, RT> slp11 =
            modifiedHelmholtz3dSingleLayerBoundaryOperator<BFT, RT, RT>(
                SHARED(context), SHARED(HplusHalfSpace1),
                SHARED(HplusHalfSpace1), SHARED(HplusHalfSpace1), waveNumber1);
    BoundaryOperator<BFT, RT> dlp11 =
            modifiedHelmholtz3dDoubleLayerBoundaryOperator<BFT, RT, RT>(
                SHARED(context), SHARED(HplusHalfSpace1),
                SHARED(HplusHalfSpace1), SHARED(HplusHalfSpace1), waveNumber1);
    BoundaryOperator<BFT, RT> id11 =
            identityOperator<BFT, RT>(
                SHARED(context), SHARED(HplusHalfSpace1),
                SHARED(HplusHalfSpace1), SHARED(HplusHalfSpace1));

    // mesh2 x mesh2, wavenumber 1
    BoundaryOperator<BFT, RT> slp22_w1 =
            modifiedHelmholtz3dSingleLayerBoundaryOperator<BFT, RT, RT>(
                SHARED(context), SHARED(HplusHalfSpace2),
                SHARED(HplusHalfSpace2), SHARED(HplusHalfSpace2), waveNumber1);
    BoundaryOperator<BFT, RT> dlp22_w1 =
            modifiedHelmholtz3dDoubleLayerBoundaryOperator<BFT, RT, RT>(
                SHARED(context), SHARED(HplusHalfSpace2),
                SHARED(HplusHalfSpace2), SHARED(HplusHalfSpace2), waveNumber1);
    BoundaryOperator<BFT, RT> id22 =
            identityOperator<BFT, RT>(
                SHARED(context), SHARED(HplusHalfSpace2),
                SHARED(HplusHalfSpace2), SHARED(HplusHalfSpace2));

    // mesh2 x mesh2, wavenumber 2
    BoundaryOperator<BFT, RT> slp22_w2 =
            modifiedHelmholtz3dSingleLayerBoundaryOperator<BFT, RT, RT>(
                SHARED(context), SHARED(HplusHalfSpace2),
                SHARED(HplusHalfSpace2), SHARED(HplusHalfSpace2), waveNumber2);
    BoundaryOperator<BFT, RT> dlp22_w2 =
            modifiedHelmholtz3dDoubleLayerBoundaryOperator<BFT, RT, RT>(
                SHARED(context), SHARED(HplusHalfSpace2),
                SHARED(HplusHalfSpace2), SHARED(HplusHalfSpace2), waveNumber2);

    // mesh1 x mesh2
    BoundaryOperator<BFT, RT> slp12 =
            modifiedHelmholtz3dSingleLayerBoundaryOperator<BFT, RT, RT>(
                SHARED(context), SHARED(HplusHalfSpace2),
                SHARED(HplusHalfSpace1), SHARED(HplusHalfSpace1), waveNumber1);
    BoundaryOperator<BFT, RT> dlp12 =
            modifiedHelmholtz3dDoubleLayerBoundaryOperator<BFT, RT, RT>(
                SHARED(context), SHARED(HplusHalfSpace2),
                SHARED(HplusHalfSpace1), SHARED(HplusHalfSpace1), waveNumber1);

    // mesh2 x mesh1
    BoundaryOperator<BFT, RT> slp21 =
            modifiedHelmholtz3dSingleLayerBoundaryOperator<BFT, RT, RT>(
                SHARED(context), SHARED(HplusHalfSpace1),
                SHARED(HplusHalfSpace2), SHARED(HplusHalfSpace2), waveNumber1);
    BoundaryOperator<BFT, RT> dlp21 =
            modifiedHelmholtz3dDoubleLayerBoundaryOperator<BFT, RT, RT>(
                SHARED(context), SHARED(HplusHalfSpace1),
                SHARED(HplusHalfSpace2), SHARED(HplusHalfSpace2), waveNumber1);

    BFT scale = 1.0/(2.0*alpha*kappa1);
    BoundaryOperator<BFT, RT> lhs_k11 = 0.5*id11 + dlp11 + scale*slp11;
    BoundaryOperator<BFT, RT> lhs_k12 = -1.0*dlp12; // sign flipped to accommodate normal direction
    BoundaryOperator<BFT, RT> lhs_k13 = -(1.0/kappa1)*slp12;
    BoundaryOperator<BFT, RT> lhs_k21 = dlp21 + scale*slp21;
    BoundaryOperator<BFT, RT> lhs_k22 = 0.5*id22 - dlp22_w1; // sign flipped to accommodate normal direction
    BoundaryOperator<BFT, RT> lhs_k23 = -(1.0/kappa1)*slp22_w1;
    // BoundaryOperator<BFT, RT> lhs_k31 -- empty
    BoundaryOperator<BFT, RT> lhs_k32 = 0.5*id22 + dlp22_w2;
    BoundaryOperator<BFT, RT> lhs_k33 = (1.0/kappa2) * slp22_w2;

    BlockedOperatorStructure<BFT, RT> structure;
    structure.setBlock(0, 0, lhs_k11);
    structure.setBlock(0, 1, lhs_k12);
    structure.setBlock(0, 2, lhs_k13);
    structure.setBlock(1, 0, lhs_k21);
    structure.setBlock(1, 1, lhs_k22);
    structure.setBlock(1, 2, lhs_k23);
    // structure.setBlock(2, 0, ...); -- empty
    structure.setBlock(2, 1, lhs_k32);
    structure.setBlock(2, 2, lhs_k33);
    BlockedBoundaryOperator<BFT, RT> blockedOp(structure);

    // Grid functions for the RHS

    // TODO: remove the necessity of creating "dummy" functions
    // corresponding to zero blocks.
    BoundaryOperator<BFT, RT> rhs1 = scale*slp11;
    BoundaryOperator<BFT, RT> rhs2 = scale*slp21;

    std::vector<GridFunction<BFT, RT> > blockedRhs(3);
    blockedRhs[0] = rhs1 * GridFunction<BFT, RT>(
                SHARED(context),
                SHARED(HplusHalfSpace1), SHARED(HplusHalfSpace1),
                //surfaceNormalIndependentFunction(NullFunctor()));
                surfaceNormalIndependentFunction(MyFunctor(waveNumber1)));
    blockedRhs[1] = rhs2 * GridFunction<BFT, RT>(
                SHARED(context),
                SHARED(HplusHalfSpace1), SHARED(HplusHalfSpace1),
                //surfaceNormalIndependentFunction(NullFunctor()));
                surfaceNormalIndependentFunction(MyFunctor(waveNumber1)));
    blockedRhs[2] = GridFunction<BFT, RT>(
                SHARED(context),
                SHARED(HplusHalfSpace2), SHARED(HplusHalfSpace2),
                //surfaceNormalIndependentFunction(MyFunctor(waveNumber2)));
                surfaceNormalIndependentFunction(NullFunctor()));

    // Initialize the solver

    const double solverTol = 1e-10;
    DefaultIterativeSolver<BFT, RT> solver(blockedOp);
    solver.initializeSolver(defaultGmresParameterList(solverTol));

    // Solve

    BlockedSolution<BFT, RT> solution = solver.solve(blockedRhs);

    std::cout << solution.solverMessage() << std::endl;
    arma::Col<RT> solutionVectorBlock1 = solution.gridFunction(0).coefficients();
    arma::Col<RT> solutionVectorBlock2 = solution.gridFunction(1).coefficients();
    arma::Col<RT> solutionVectorBlock3 = solution.gridFunction(2).coefficients();

    arma::diskio::save_raw_ascii(solutionVectorBlock1, "sol1.txt");
    arma::diskio::save_raw_ascii(solutionVectorBlock2, "sol2.txt");
    arma::diskio::save_raw_ascii(solutionVectorBlock3, "sol3.txt");

    solution.gridFunction(0).exportToVtk(VtkWriter::VERTEX_DATA, "gf1", "gf1");
    solution.gridFunction(1).exportToVtk(VtkWriter::VERTEX_DATA, "gf2", "gf2");
    solution.gridFunction(2).exportToVtk(VtkWriter::VERTEX_DATA, "gf3", "gf3");
}
コード例 #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");
    }