Exemplo n.º 1
0
int main()
{
    int nbComputations = 6;
    int nbNodes = 5;

    #pragma omp parallel for collapse(2), schedule(dynamic,1)

    for ( int iNodes = 0; iNodes < nbNodes; iNodes++ )
    {
        for ( int iComputation = 0; iComputation < nbComputations; iComputation++ )
        {
            unsigned int nbNodes = iNodes + 1;
            unsigned int nbTimeSteps = std::pow( 2, iComputation );

            std::shared_ptr<sdc::TimeIntegrationScheme> timeIntegrationScheme;
            std::shared_ptr<tubeflow::SDCTubeFlowFluidSolver> fluid;
            std::shared_ptr<tubeflow::SDCTubeFlowBDFLinearizedSolidSolver> solid;
            std::shared_ptr<MultiLevelFsiSolver> fsi;

            {
                scalar r0 = 0.2;
                scalar a0 = M_PI * r0 * r0;
                scalar u0 = 0.1;
                scalar p0 = 0;
                scalar L = 1;
                scalar T = 1;
                scalar dt = T / nbTimeSteps;
                scalar rho_f = 1.225;
                scalar rho_s = 1.225;
                scalar E0 = 490;
                scalar G = 490;
                scalar h = 1.0e-3;
                scalar nu = 0.5;
                scalar cmk = std::sqrt( E0 * h / (2 * rho_f * r0) );

                int N = 250;
                bool parallel = false;
                int extrapolation = 0;
                int maxIter = 100;
                scalar initialRelaxation = 1.0e-3;
                int maxUsedIterations = 50;
                int nbReuse = 0;
                scalar tol = 1.0e-5;
                scalar absoluteTol = 1.0e-13;

                scalar singularityLimit = 1.0e-13;
                int reuseInformationStartingFromTimeIndex = 0;
                bool scaling = false;
                bool updateJacobian = false;
                scalar beta = 0.1;

                int timeOrder = 1;

                if ( nbNodes > 1 )
                    timeOrder = 2;

                fluid = std::shared_ptr<tubeflow::SDCTubeFlowFluidSolver> ( new tubeflow::SDCTubeFlowFluidSolver( a0, u0, p0, dt, cmk, N, L, T, rho_f ) );
                solid = std::shared_ptr<tubeflow::SDCTubeFlowBDFLinearizedSolidSolver>( new tubeflow::SDCTubeFlowBDFLinearizedSolidSolver( N, nu, rho_s, h, L, dt, G, E0, r0, T, timeOrder ) );

                shared_ptr<MultiLevelSolver> fluidSolver( new MultiLevelSolver( fluid, fluid, 0, 0 ) );
                shared_ptr<MultiLevelSolver> solidSolver( new MultiLevelSolver( solid, fluid, 1, 0 ) );

                std::shared_ptr< std::list<std::shared_ptr<ConvergenceMeasure> > > convergenceMeasures;
                convergenceMeasures = std::shared_ptr<std::list<std::shared_ptr<ConvergenceMeasure> > >( new std::list<std::shared_ptr<ConvergenceMeasure> > );

                convergenceMeasures->push_back( std::shared_ptr<ConvergenceMeasure>( new ResidualRelativeConvergenceMeasure( 0, true, tol ) ) );
                convergenceMeasures->push_back( std::shared_ptr<ConvergenceMeasure>( new AbsoluteConvergenceMeasure( 0, true, 0.1 * absoluteTol ) ) );

                fsi = shared_ptr<MultiLevelFsiSolver> ( new MultiLevelFsiSolver( fluidSolver, solidSolver, convergenceMeasures, parallel, extrapolation ) );

                shared_ptr<PostProcessing> postProcessing( new AndersonPostProcessing( fsi, maxIter, initialRelaxation, maxUsedIterations, nbReuse, singularityLimit, reuseInformationStartingFromTimeIndex, scaling, beta, updateJacobian ) );

                std::shared_ptr<sdc::SDCFsiSolverInterface> sdcFluidSolver = std::dynamic_pointer_cast<sdc::SDCFsiSolverInterface>( fluid );
                std::shared_ptr<sdc::SDCFsiSolverInterface> sdcSolidSolver = std::dynamic_pointer_cast<sdc::SDCFsiSolverInterface>( solid );

                assert( sdcFluidSolver );
                assert( sdcSolidSolver );

                std::shared_ptr<fsi::SDCFsiSolver> fsiSolver( new fsi::SDCFsiSolver( sdcFluidSolver, sdcSolidSolver, postProcessing ) );

                std::shared_ptr<fsi::quadrature::IQuadrature<scalar> > quadrature;
                quadrature = std::shared_ptr<fsi::quadrature::IQuadrature<scalar> >( new fsi::quadrature::Uniform<scalar>( nbNodes ) );

                timeIntegrationScheme = std::shared_ptr<sdc::TimeIntegrationScheme> ( new sdc::SDC( fsiSolver, quadrature, absoluteTol, nbNodes, 50 ) );
            }

            assert( timeIntegrationScheme );
            assert( fluid );
            assert( solid );
            assert( fsi );

            std::chrono::time_point<std::chrono::high_resolution_clock> start, end;
            start = std::chrono::high_resolution_clock::now();

            timeIntegrationScheme->run();

            end = std::chrono::high_resolution_clock::now();

            std::chrono::duration<double> elapsed_seconds = end - start;

            std::string label = "IDC_BDF";
            label += "_nbNodes_" + std::to_string( nbNodes );
            label += "_nbTimeSteps_" + std::to_string( nbTimeSteps );

            ofstream log_file( label + ".log" );
            ofstream data_fluid_u( label + "_data_fluid_u.log" );
            ofstream data_fluid_a( label + "_data_fluid_a.log" );
            ofstream data_fluid_p( label + "_data_fluid_p.log" );
            ofstream data_solid_u( label + "_data_solid_u.log" );
            ofstream data_solid_r( label + "_data_solid_r.log" );

            log_file << "label = " << label << std::endl;
            log_file << "nbNodes = " << nbNodes << std::endl;
            log_file << "nbTimeSteps = " << nbTimeSteps << std::endl;
            log_file << "nbIterations = " << fsi->nbIter << std::endl;
            log_file << "timing = " << elapsed_seconds.count() << std::endl;

            data_fluid_u << std::setprecision( 20 ) << fluid->u << std::endl;
            data_fluid_a << std::setprecision( 20 ) << fluid->a << std::endl;
            data_fluid_p << std::setprecision( 20 ) << fluid->p << std::endl;
            data_solid_u << std::setprecision( 20 ) << solid->u << std::endl;
            data_solid_r << std::setprecision( 20 ) << solid->r << std::endl;

            log_file.close();
            data_fluid_u.close();
            data_fluid_a.close();
            data_fluid_p.close();
            data_solid_u.close();
            data_solid_r.close();
        }
    }
}
TEST( SDIRKFsiSolidTest, linearized )
{
    scalar r0 = 3.0e-3;
    scalar h = 3.0e-4;
    scalar L = 0.126;
    scalar rho_s = 1000;
    scalar E0 = 4.0e5;
    scalar G = 4.0e5;
    scalar nu = 0.5;

    scalar a0 = M_PI * r0 * r0;
    scalar u0 = 0.26;
    scalar p0 = 0;
    int N = 5;
    scalar T = 1;
    scalar rho_f = 1060;
    scalar E = 490;
    scalar cmk = std::sqrt( E * h / (2 * rho_f * r0) );

    bool parallel = false;
    int extrapolation = 0;
    scalar tol = 1.0e-8;
    int maxIter = 50;
    scalar initialRelaxation = 1.0e-3;
    int maxUsedIterations = 50;
    int nbReuse = 0;
    scalar singularityLimit = 1.0e-13;
    int reuseInformationStartingFromTimeIndex = 0;
    bool scaling = false;
    scalar beta = 0.01;
    bool updateJacobian = false;
    int minIter = 5;

    int nbComputations = 3;

    std::deque<std::shared_ptr<tubeflow::SDCTubeFlowFluidSolver> > fluidSolvers;
    std::deque<std::shared_ptr<tubeflow::SDCTubeFlowLinearizedSolidSolver> > solidSolvers;
    std::deque<int> nbTimeStepsList;

    for ( int iComputation = 0; iComputation < nbComputations; iComputation++ )
    {
        int nbTimeSteps = 120 * std::pow( 2, iComputation );
        std::cout << "nbTimeSteps = " << nbTimeSteps << std::endl;
        scalar dt = T / nbTimeSteps;

        std::shared_ptr<tubeflow::SDCTubeFlowFluidSolver> fluid( new tubeflow::SDCTubeFlowFluidSolver( a0, u0, p0, dt, cmk, N, L, T, rho_f ) );
        std::shared_ptr<tubeflow::SDCTubeFlowLinearizedSolidSolver> solid( new tubeflow::SDCTubeFlowLinearizedSolidSolver( N, nu, rho_s, h, L, dt, G, E0, r0, T ) );

        shared_ptr<RBFFunctionInterface> rbfFunction;
        shared_ptr<RBFInterpolation> rbfInterpolator;
        shared_ptr<RBFCoarsening> rbfInterpToCouplingMesh;
        shared_ptr<RBFCoarsening> rbfInterpToMesh;

        rbfFunction = shared_ptr<RBFFunctionInterface>( new TPSFunction() );
        rbfInterpolator = shared_ptr<RBFInterpolation>( new RBFInterpolation( rbfFunction ) );
        rbfInterpToCouplingMesh = shared_ptr<RBFCoarsening> ( new RBFCoarsening( rbfInterpolator ) );

        rbfFunction = shared_ptr<RBFFunctionInterface>( new TPSFunction() );
        rbfInterpolator = shared_ptr<RBFInterpolation>( new RBFInterpolation( rbfFunction ) );
        rbfInterpToMesh = shared_ptr<RBFCoarsening> ( new RBFCoarsening( rbfInterpolator ) );

        shared_ptr<MultiLevelSolver> fluidSolver( new MultiLevelSolver( fluid, fluid, rbfInterpToCouplingMesh, rbfInterpToMesh, 0, 0 ) );

        rbfFunction = shared_ptr<RBFFunctionInterface>( new TPSFunction() );
        rbfInterpolator = shared_ptr<RBFInterpolation>( new RBFInterpolation( rbfFunction ) );
        rbfInterpToCouplingMesh = shared_ptr<RBFCoarsening> ( new RBFCoarsening( rbfInterpolator ) );

        rbfFunction = shared_ptr<RBFFunctionInterface>( new TPSFunction() );
        rbfInterpolator = shared_ptr<RBFInterpolation>( new RBFInterpolation( rbfFunction ) );
        rbfInterpToMesh = shared_ptr<RBFCoarsening> ( new RBFCoarsening( rbfInterpolator ) );

        shared_ptr<MultiLevelSolver> solidSolver( new MultiLevelSolver( solid, fluid, rbfInterpToCouplingMesh, rbfInterpToMesh, 1, 0 ) );

        std::shared_ptr< std::list<std::shared_ptr<ConvergenceMeasure> > > convergenceMeasures;
        convergenceMeasures = std::shared_ptr<std::list<std::shared_ptr<ConvergenceMeasure> > >( new std::list<std::shared_ptr<ConvergenceMeasure> >() );

        convergenceMeasures->push_back( std::shared_ptr<ConvergenceMeasure>( new RelativeConvergenceMeasure( 0, true, tol ) ) );
        convergenceMeasures->push_back( std::shared_ptr<ConvergenceMeasure>( new MinIterationConvergenceMeasure( 0, false, minIter ) ) );

        shared_ptr<MultiLevelFsiSolver> fsi( new MultiLevelFsiSolver( fluidSolver, solidSolver, convergenceMeasures, parallel, extrapolation ) );

        shared_ptr<PostProcessing> postProcessing( new AndersonPostProcessing( fsi, maxIter, initialRelaxation, maxUsedIterations, nbReuse, singularityLimit, reuseInformationStartingFromTimeIndex, scaling, beta, updateJacobian ) );

        std::shared_ptr<sdc::SDCFsiSolverInterface> sdcFluidSolver = std::dynamic_pointer_cast<sdc::SDCFsiSolverInterface>( fluid );
        std::shared_ptr<sdc::SDCFsiSolverInterface> sdcSolidSolver = std::dynamic_pointer_cast<sdc::SDCFsiSolverInterface>( solid );

        assert( sdcFluidSolver );
        assert( sdcSolidSolver );

        std::shared_ptr<fsi::SDCFsiSolver> fsiSolver( new fsi::SDCFsiSolver( sdcFluidSolver, sdcSolidSolver, postProcessing, extrapolation ) );

        std::shared_ptr<sdc::AdaptiveTimeStepper> adaptiveTimeStepper( new sdc::AdaptiveTimeStepper( false ) );

        std::string method = "ESDIRK53PR";

        std::shared_ptr<sdc::ESDIRK> esdirk( new sdc::ESDIRK( fsiSolver, method, adaptiveTimeStepper ) );

        esdirk->run();

        fluidSolvers.push_back( fluid );
        solidSolvers.push_back( solid );
        nbTimeStepsList.push_back( nbTimeSteps );
    }

    std::cout << "solid" << std::endl;

    for ( int i = 0; i < 2; i++ )
    {
        fsi::vector ref;

        if ( i == 0 )
            ref = solidSolvers.back()->r;
        else
            ref = solidSolvers.back()->u;

        std::deque<scalar> errors;

        for ( int iComputation = 0; iComputation < nbComputations - 1; iComputation++ )
        {
            fsi::vector data;

            if ( i == 0 )
                data = solidSolvers.at( iComputation )->r;
            else
                data = solidSolvers.at( iComputation )->u;

            scalar error = (ref - data).norm() / ref.norm();
            errors.push_back( error );
        }

        for ( int iComputation = 0; iComputation < nbComputations - 2; iComputation++ )
        {
            scalar order = ( std::log10( errors.at( iComputation ) ) - std::log10( errors.at( iComputation + 1 ) ) ) / ( std::log10( nbTimeStepsList.at( iComputation + 1 ) ) - std::log10( nbTimeStepsList.at( iComputation ) ) );
            std::cout << "order = " << order << std::endl;

            if ( i == 0 )
                ASSERT_NEAR( order, 3, 0.1 );
        }
    }

    std::cout << "fluid" << std::endl;

    for ( int i = 0; i < 3; i++ )
    {
        fsi::vector ref;

        if ( i == 0 )
            ref = fluidSolvers.back()->u;

        if ( i == 1 )
            ref = fluidSolvers.back()->a;

        if ( i == 2 )
            ref = fluidSolvers.back()->p;

        std::deque<scalar> errors;

        for ( int iComputation = 0; iComputation < nbComputations - 1; iComputation++ )
        {
            fsi::vector data;

            if ( i == 0 )
                data = fluidSolvers.at( iComputation )->u;

            if ( i == 1 )
                data = fluidSolvers.at( iComputation )->a;

            if ( i == 2 )
                data = fluidSolvers.at( iComputation )->p;

            scalar error = (ref - data).norm() / ref.norm();
            errors.push_back( error );
        }

        for ( int iComputation = 0; iComputation < nbComputations - 2; iComputation++ )
        {
            scalar order = ( std::log10( errors.at( iComputation ) ) - std::log10( errors.at( iComputation + 1 ) ) ) / ( std::log10( nbTimeStepsList.at( iComputation + 1 ) ) - std::log10( nbTimeStepsList.at( iComputation ) ) );
            std::cout << "order = " << order << std::endl;

            if ( i == 1 || i == 2 )
                ASSERT_NEAR( order, 3, 0.1 );
        }
    }
}
TEST( SDCFsiTest, reuse )
{
    std::vector<int> nbIter;

    for ( int nbReuse = 0; nbReuse < 3; nbReuse++ )
    {
        scalar r0 = 0.2;
        scalar a0 = M_PI * r0 * r0;
        scalar u0 = 0.1;
        scalar p0 = 0;
        scalar dt = 0.01;
        int N = 20;
        scalar L = 1;
        scalar T = 1;
        scalar dx = L / N;
        scalar rho = 1.225;
        scalar E = 490;
        scalar h = 1.0e-3;
        scalar cmk = std::sqrt( E * h / (2 * rho * r0) );
        scalar c0 = std::sqrt( cmk * cmk - p0 / (2 * rho) );
        scalar kappa = c0 / u0;

        bool parallel = false;
        int extrapolation = 0;
        scalar tol = 1.0e-5;
        int maxIter = 50;
        scalar initialRelaxation = 1.0e-3;
        int maxUsedIterations = 50;

        scalar singularityLimit = 1.0e-13;
        int reuseInformationStartingFromTimeIndex = 0;
        bool scaling = false;
        bool updateJacobian = false;
        scalar beta = 0.1;
        int minIter = 5;

        ASSERT_NEAR( kappa, 10, 1.0e-13 );
        ASSERT_TRUE( dx > 0 );

        std::shared_ptr<tubeflow::SDCTubeFlowFluidSolver> fluid( new tubeflow::SDCTubeFlowFluidSolver( a0, u0, p0, dt, cmk, N, L, T, rho ) );
        std::shared_ptr<tubeflow::SDCTubeFlowSolidSolver> solid( new tubeflow::SDCTubeFlowSolidSolver( a0, cmk, p0, rho, L, N ) );

        shared_ptr<RBFFunctionInterface> rbfFunction;
        shared_ptr<RBFInterpolation> rbfInterpolator;
        shared_ptr<RBFCoarsening> rbfInterpToCouplingMesh;
        shared_ptr<RBFCoarsening> rbfInterpToMesh;

        rbfFunction = shared_ptr<RBFFunctionInterface>( new TPSFunction() );
        rbfInterpolator = shared_ptr<RBFInterpolation>( new RBFInterpolation( rbfFunction ) );
        rbfInterpToCouplingMesh = shared_ptr<RBFCoarsening> ( new RBFCoarsening( rbfInterpolator ) );

        rbfFunction = shared_ptr<RBFFunctionInterface>( new TPSFunction() );
        rbfInterpolator = shared_ptr<RBFInterpolation>( new RBFInterpolation( rbfFunction ) );
        rbfInterpToMesh = shared_ptr<RBFCoarsening> ( new RBFCoarsening( rbfInterpolator ) );

        shared_ptr<MultiLevelSolver> fluidSolver( new MultiLevelSolver( fluid, fluid, rbfInterpToCouplingMesh, rbfInterpToMesh, 0, 0 ) );

        rbfFunction = shared_ptr<RBFFunctionInterface>( new TPSFunction() );
        rbfInterpolator = shared_ptr<RBFInterpolation>( new RBFInterpolation( rbfFunction ) );
        rbfInterpToCouplingMesh = shared_ptr<RBFCoarsening> ( new RBFCoarsening( rbfInterpolator ) );

        rbfFunction = shared_ptr<RBFFunctionInterface>( new TPSFunction() );
        rbfInterpolator = shared_ptr<RBFInterpolation>( new RBFInterpolation( rbfFunction ) );
        rbfInterpToMesh = shared_ptr<RBFCoarsening> ( new RBFCoarsening( rbfInterpolator ) );

        shared_ptr<MultiLevelSolver> solidSolver( new MultiLevelSolver( solid, fluid, rbfInterpToCouplingMesh, rbfInterpToMesh, 1, 0 ) );

        std::shared_ptr< std::list<std::shared_ptr<ConvergenceMeasure> > > convergenceMeasures;
        convergenceMeasures = std::shared_ptr<std::list<std::shared_ptr<ConvergenceMeasure> > >( new std::list<std::shared_ptr<ConvergenceMeasure> > );

        convergenceMeasures->push_back( std::shared_ptr<ConvergenceMeasure>( new RelativeConvergenceMeasure( 0, false, tol ) ) );
        convergenceMeasures->push_back( std::shared_ptr<ConvergenceMeasure>( new MinIterationConvergenceMeasure( 0, false, minIter ) ) );

        shared_ptr<MultiLevelFsiSolver> fsi( new MultiLevelFsiSolver( fluidSolver, solidSolver, convergenceMeasures, parallel, extrapolation ) );

        shared_ptr<PostProcessing> postProcessing( new AndersonPostProcessing( fsi, maxIter, initialRelaxation, maxUsedIterations, nbReuse, singularityLimit, reuseInformationStartingFromTimeIndex, scaling, beta, updateJacobian ) );

        std::shared_ptr<sdc::SDCFsiSolverInterface> sdcFluidSolver = std::dynamic_pointer_cast<sdc::SDCFsiSolverInterface>( fluid );
        std::shared_ptr<sdc::SDCFsiSolverInterface> sdcSolidSolver = std::dynamic_pointer_cast<sdc::SDCFsiSolverInterface>( solid );

        assert( sdcFluidSolver );
        assert( sdcSolidSolver );

        std::shared_ptr<fsi::SDCFsiSolver> fsiSolver( new fsi::SDCFsiSolver( sdcFluidSolver, sdcSolidSolver, postProcessing, extrapolation ) );

        int nbNodes = 3;

        std::shared_ptr<fsi::quadrature::IQuadrature<scalar> > quadrature;
        quadrature = std::shared_ptr<fsi::quadrature::IQuadrature<scalar> >( new fsi::quadrature::Uniform<scalar>( nbNodes ) );

        std::shared_ptr<sdc::SDC> sdc( new sdc::SDC( fsiSolver, quadrature, 1.0e-10, nbNodes, nbNodes ) );

        sdc->run();

        nbIter.push_back( fsi->nbIter );
    }

    int iprev;
    int index = 0;

    for ( int i : nbIter )
    {
        std::cout << "nbIter = " << i << std::endl;

        if ( index > 0 )
            ASSERT_LE( i, iprev );

        iprev = i;
        index++;
    }
}
        virtual void SetUp()
        {
            scalar r0 = 3.0e-3;
            scalar h = 3.0e-4;
            scalar L = 0.126;
            scalar rho_s = 1000;
            scalar E0 = 4.0e5;
            scalar G = 4.0e5;
            scalar nu = 0.5;

            scalar a0 = M_PI * r0 * r0;
            scalar u0 = 0.26;
            scalar p0 = 0;
            scalar dt = 1;
            int N = 5;
            scalar T = 1;
            scalar rho_f = 1060;
            scalar E = 490;
            scalar cmk = std::sqrt( E * h / (2 * rho_f * r0) );

            bool parallel = false;
            int extrapolation = 0;
            scalar tol = 1.0e-3;
            int maxIter = 20;
            scalar initialRelaxation = 1.0e-3;
            int maxUsedIterations = 50;
            int nbReuse = 0;

            scalar singularityLimit = 1.0e-13;
            int reuseInformationStartingFromTimeIndex = 0;
            bool scaling = false;
            bool updateJacobian = false;
            scalar beta = 0.5;
            int minIter = 5;

            std::shared_ptr<tubeflow::SDCTubeFlowFluidSolver> fluid( new tubeflow::SDCTubeFlowFluidSolver( a0, u0, p0, dt, cmk, N, L, T, rho_f ) );

            std::shared_ptr<fsi::BaseMultiLevelSolver> solid;
            solid = std::shared_ptr<fsi::BaseMultiLevelSolver>( new tubeflow::SDCTubeFlowLinearizedSolidSolver( N, nu, rho_s, h, L, dt, G, E0, r0, T ) );

            assert( solid );

            shared_ptr<RBFFunctionInterface> rbfFunction;
            shared_ptr<RBFInterpolation> rbfInterpolator;
            shared_ptr<RBFCoarsening> rbfInterpToCouplingMesh;
            shared_ptr<RBFCoarsening> rbfInterpToMesh;

            rbfFunction = shared_ptr<RBFFunctionInterface>( new TPSFunction() );
            rbfInterpolator = shared_ptr<RBFInterpolation>( new RBFInterpolation( rbfFunction ) );
            rbfInterpToCouplingMesh = shared_ptr<RBFCoarsening> ( new RBFCoarsening( rbfInterpolator ) );

            rbfFunction = shared_ptr<RBFFunctionInterface>( new TPSFunction() );
            rbfInterpolator = shared_ptr<RBFInterpolation>( new RBFInterpolation( rbfFunction ) );
            rbfInterpToMesh = shared_ptr<RBFCoarsening> ( new RBFCoarsening( rbfInterpolator ) );

            shared_ptr<MultiLevelSolver> fluidSolver( new MultiLevelSolver( fluid, fluid, rbfInterpToCouplingMesh, rbfInterpToMesh, 0, 0 ) );

            rbfFunction = shared_ptr<RBFFunctionInterface>( new TPSFunction() );
            rbfInterpolator = shared_ptr<RBFInterpolation>( new RBFInterpolation( rbfFunction ) );
            rbfInterpToCouplingMesh = shared_ptr<RBFCoarsening> ( new RBFCoarsening( rbfInterpolator ) );

            rbfFunction = shared_ptr<RBFFunctionInterface>( new TPSFunction() );
            rbfInterpolator = shared_ptr<RBFInterpolation>( new RBFInterpolation( rbfFunction ) );
            rbfInterpToMesh = shared_ptr<RBFCoarsening> ( new RBFCoarsening( rbfInterpolator ) );

            shared_ptr<MultiLevelSolver> solidSolver( new MultiLevelSolver( solid, fluid, rbfInterpToCouplingMesh, rbfInterpToMesh, 1, 0 ) );

            std::shared_ptr< std::list<std::shared_ptr<ConvergenceMeasure> > > convergenceMeasures;
            convergenceMeasures = std::shared_ptr<std::list<std::shared_ptr<ConvergenceMeasure> > >( new std::list<std::shared_ptr<ConvergenceMeasure> >() );

            convergenceMeasures->push_back( std::shared_ptr<ConvergenceMeasure>( new RelativeConvergenceMeasure( 0, true, tol ) ) );
            convergenceMeasures->push_back( std::shared_ptr<ConvergenceMeasure>( new MinIterationConvergenceMeasure( 0, false, minIter ) ) );

            shared_ptr<MultiLevelFsiSolver> fsi( new MultiLevelFsiSolver( fluidSolver, solidSolver, convergenceMeasures, parallel, extrapolation ) );

            shared_ptr<PostProcessing> postProcessing( new AndersonPostProcessing( fsi, maxIter, initialRelaxation, maxUsedIterations, nbReuse, singularityLimit, reuseInformationStartingFromTimeIndex, scaling, beta, updateJacobian ) );

            std::shared_ptr<sdc::SDCFsiSolverInterface> sdcFluidSolver = std::dynamic_pointer_cast<sdc::SDCFsiSolverInterface>( fluid );
            std::shared_ptr<sdc::SDCFsiSolverInterface> sdcSolidSolver = std::dynamic_pointer_cast<sdc::SDCFsiSolverInterface>( solid );

            assert( sdcFluidSolver );
            assert( sdcSolidSolver );

            std::shared_ptr<fsi::SDCFsiSolver> fsiSolver( new fsi::SDCFsiSolver( sdcFluidSolver, sdcSolidSolver, postProcessing, extrapolation ) );

            std::shared_ptr<sdc::AdaptiveTimeStepper> adaptiveTimeStepper( new sdc::AdaptiveTimeStepper( false ) );

            std::string method = "ESDIRK53PR";

            esdirk = std::shared_ptr<sdc::ESDIRK> ( new sdc::ESDIRK( fsiSolver, method, adaptiveTimeStepper ) );
        }
TEST( SDCFsiTest, order )
{
    int N = 5;
    scalar r0 = 0.2;
    scalar a0 = M_PI * r0 * r0;
    scalar u0 = 0.1;
    scalar p0 = 0;
    scalar L = 1;
    scalar T = 1;
    scalar dx = L / N;
    scalar rho = 1.225;
    scalar E = 490;
    scalar h = 1.0e-3;
    scalar cmk = std::sqrt( E * h / (2 * rho * r0) );
    scalar c0 = std::sqrt( cmk * cmk - p0 / (2 * rho) );
    scalar kappa = c0 / u0;

    bool parallel = false;
    int extrapolation = 0;
    scalar tol = 1.0e-5;
    int maxIter = 20;
    scalar initialRelaxation = 1.0e-3;
    int maxUsedIterations = 50;
    int nbReuse = 0;
    scalar singularityLimit = 1.0e-13;
    int reuseInformationStartingFromTimeIndex = 0;
    bool scaling = false;
    scalar beta = 0.01;
    bool updateJacobian = false;
    int minIter = 5;

    ASSERT_NEAR( kappa, 10, 1.0e-13 );
    ASSERT_TRUE( dx > 0 );

    int nbComputations = 5;

    std::deque<std::shared_ptr<tubeflow::SDCTubeFlowFluidSolver> > fluidSolvers;
    std::deque<int> nbTimeStepsList;

    for ( int iComputation = 0; iComputation < nbComputations; iComputation++ )
    {
        int nbTimeSteps = 4 * std::pow( 2, iComputation );
        std::cout << "nbTimeSteps = " << nbTimeSteps << std::endl;
        scalar dt = T / nbTimeSteps;

        std::shared_ptr<tubeflow::SDCTubeFlowFluidSolver> fluid( new tubeflow::SDCTubeFlowFluidSolver( a0, u0, p0, dt, cmk, N, L, T, rho ) );
        std::shared_ptr<tubeflow::SDCTubeFlowSolidSolver> solid( new tubeflow::SDCTubeFlowSolidSolver( a0, cmk, p0, rho, L, N ) );

        shared_ptr<RBFFunctionInterface> rbfFunction;
        shared_ptr<RBFInterpolation> rbfInterpolator;
        shared_ptr<RBFCoarsening> rbfInterpToCouplingMesh;
        shared_ptr<RBFCoarsening> rbfInterpToMesh;

        rbfFunction = shared_ptr<RBFFunctionInterface>( new TPSFunction() );
        rbfInterpolator = shared_ptr<RBFInterpolation>( new RBFInterpolation( rbfFunction ) );
        rbfInterpToCouplingMesh = shared_ptr<RBFCoarsening> ( new RBFCoarsening( rbfInterpolator ) );

        rbfFunction = shared_ptr<RBFFunctionInterface>( new TPSFunction() );
        rbfInterpolator = shared_ptr<RBFInterpolation>( new RBFInterpolation( rbfFunction ) );
        rbfInterpToMesh = shared_ptr<RBFCoarsening> ( new RBFCoarsening( rbfInterpolator ) );

        shared_ptr<MultiLevelSolver> fluidSolver( new MultiLevelSolver( fluid, fluid, rbfInterpToCouplingMesh, rbfInterpToMesh, 0, 0 ) );

        rbfFunction = shared_ptr<RBFFunctionInterface>( new TPSFunction() );
        rbfInterpolator = shared_ptr<RBFInterpolation>( new RBFInterpolation( rbfFunction ) );
        rbfInterpToCouplingMesh = shared_ptr<RBFCoarsening> ( new RBFCoarsening( rbfInterpolator ) );

        rbfFunction = shared_ptr<RBFFunctionInterface>( new TPSFunction() );
        rbfInterpolator = shared_ptr<RBFInterpolation>( new RBFInterpolation( rbfFunction ) );
        rbfInterpToMesh = shared_ptr<RBFCoarsening> ( new RBFCoarsening( rbfInterpolator ) );

        shared_ptr<MultiLevelSolver> solidSolver( new MultiLevelSolver( solid, fluid, rbfInterpToCouplingMesh, rbfInterpToMesh, 1, 0 ) );

        std::shared_ptr< std::list<std::shared_ptr<ConvergenceMeasure> > > convergenceMeasures;
        convergenceMeasures = std::shared_ptr<std::list<std::shared_ptr<ConvergenceMeasure> > >( new std::list<std::shared_ptr<ConvergenceMeasure> > );

        convergenceMeasures->push_back( std::shared_ptr<ConvergenceMeasure>( new ResidualRelativeConvergenceMeasure( 0, false, tol ) ) );
        convergenceMeasures->push_back( std::shared_ptr<ConvergenceMeasure>( new MinIterationConvergenceMeasure( 0, false, minIter ) ) );

        shared_ptr<MultiLevelFsiSolver> fsi( new MultiLevelFsiSolver( fluidSolver, solidSolver, convergenceMeasures, parallel, extrapolation ) );

        shared_ptr<PostProcessing> postProcessing( new AndersonPostProcessing( fsi, maxIter, initialRelaxation, maxUsedIterations, nbReuse, singularityLimit, reuseInformationStartingFromTimeIndex, scaling, beta, updateJacobian ) );

        std::shared_ptr<sdc::SDCFsiSolverInterface> sdcFluidSolver = std::dynamic_pointer_cast<sdc::SDCFsiSolverInterface>( fluid );
        std::shared_ptr<sdc::SDCFsiSolverInterface> sdcSolidSolver = std::dynamic_pointer_cast<sdc::SDCFsiSolverInterface>( solid );

        assert( sdcFluidSolver );
        assert( sdcSolidSolver );

        std::shared_ptr<fsi::SDCFsiSolver> fsiSolver( new fsi::SDCFsiSolver( sdcFluidSolver, sdcSolidSolver, postProcessing, extrapolation ) );

        int nbNodes = 3;

        std::shared_ptr<fsi::quadrature::IQuadrature<scalar> > quadrature;
        quadrature = std::shared_ptr<fsi::quadrature::IQuadrature<scalar> >( new fsi::quadrature::GaussLobatto<scalar>( nbNodes ) );

        std::shared_ptr<sdc::SDC> sdc( new sdc::SDC( fsiSolver, quadrature, 1.0e-13, 10, 200 ) );

        sdc->run();
        ASSERT_TRUE( sdc->isConverged() );

        fluidSolvers.push_back( fluid );
        nbTimeStepsList.push_back( nbTimeSteps );
    }

    for ( int i = 0; i < 2; i++ )
    {
        fsi::vector ref;

        if ( i == 0 )
            ref = fluidSolvers.back()->u;
        else
            ref = fluidSolvers.back()->a;

        std::deque<scalar> errors;

        for ( int iComputation = 0; iComputation < nbComputations - 1; iComputation++ )
        {
            fsi::vector data;

            if ( i == 0 )
                data = fluidSolvers.at( iComputation )->u;
            else
                data = fluidSolvers.at( iComputation )->a;

            scalar error = (ref - data).norm() / data.norm();
            std::cout << "error = " << error << std::endl;
            errors.push_back( error );
        }

        for ( int iComputation = 0; iComputation < nbComputations - 2; iComputation++ )
        {
            scalar order = ( std::log10( errors.at( iComputation ) ) - std::log10( errors.at( iComputation + 1 ) ) ) / ( std::log10( nbTimeStepsList.at( iComputation + 1 ) ) - std::log10( nbTimeStepsList.at( iComputation ) ) );
            std::cout << "order = " << order << std::endl;
            ASSERT_GE( order, 3.8 );
        }
    }
}