Skip to content
Snippets Groups Projects
rod-eoc.cc 8.46 KiB
Newer Older
#include <config.h>

#include <dune/common/bitsetvector.hh>
#include <dune/common/configparser.hh>

#include <dune/grid/onedgrid.hh>

#include <dune/istl/io.hh>

Oliver Sander's avatar
Oliver Sander committed
#include <dune/ag-common/functionspacebases/p1nodalbasis.hh>
#include <dune/ag-common/assemblers/operatorassembler.hh>
#include <dune/ag-common/assemblers/localassemblers/laplaceassembler.hh>
#include <dune/ag-common/assemblers/localassemblers/massassembler.hh>
#include <dune/solvers/solvers/iterativesolver.hh>
#include <dune/solvers/norms/energynorm.hh>
Oliver Sander's avatar
Oliver Sander committed
#include <dune/gfe/rigidbodymotion.hh>
#include <dune/gfe/geodesicdifference.hh>
#include <dune/gfe/rotation.hh>
#include <dune/gfe/rodassembler.hh>
#include <dune/gfe/riemanniantrsolver.hh>
#include <dune/gfe/rodrefine.hh>
#include <dune/gfe/rodwriter.hh>

typedef Dune::OneDGrid GridType;

typedef RigidBodyMotion<3> TargetSpace;
typedef std::vector<RigidBodyMotion<3> > SolutionType;

const int blocksize = TargetSpace::TangentVector::size;

using namespace Dune;
using std::string;

void solve (const GridType& grid,
Oliver Sander's avatar
Oliver Sander committed
            SolutionType& x, 
            int numLevels,
            const TargetSpace& dirichletValue,
            ConfigParser& parameters)
{
    // read solver setting
    const double innerTolerance           = parameters.get<double>("innerTolerance");
    const double tolerance                = parameters.get<double>("tolerance");
    const int maxTrustRegionSteps         = parameters.get<int>("maxTrustRegionSteps");
    const double initialTrustRegionRadius = parameters.get<double>("initialTrustRegionRadius");
    const int multigridIterations         = parameters.get<int>("numIt");

    // read rod parameter settings
    const double A               = parameters.get<double>("A");
    const double J1              = parameters.get<double>("J1");
    const double J2              = parameters.get<double>("J2");
    const double E               = parameters.get<double>("E");
    const double nu              = parameters.get<double>("nu");

    //   Create a local assembler
    RodLocalStiffness<OneDGrid::LeafGridView,double> localStiffness(grid.leafView(),
                                                                    A, J1, J2, E, nu);




    x.resize(grid.size(1));

    // //////////////////////////
    //   Initial solution
    // //////////////////////////

    for (int i=0; i<x.size(); i++) {
        x[i].r[0] = 0;
        x[i].r[1] = 0;
        x[i].r[2] = double(i)/(x.size()-1);
        x[i].q    = Rotation<3,double>::identity();
    }

    //  set Dirichlet value
    x.back() = dirichletValue;

    // Both ends are Dirichlet
    BitSetVector<blocksize> dirichletNodes(grid.size(1));
    dirichletNodes.unsetAll();
        
    dirichletNodes[0] = dirichletNodes.back() = true;
    
    // ///////////////////////////////////////////
    //   Create a solver for the rod problem
    // ///////////////////////////////////////////

    RodAssembler<GridType::LeafGridView,3> rodAssembler(grid.leafView(), &localStiffness);

    RiemannianTrustRegionSolver<GridType,RigidBodyMotion<3> > rodSolver;
Oliver Sander's avatar
Oliver Sander committed
#if 1
    rodSolver.setup(grid, 
                    &rodAssembler,
                    x,
                    dirichletNodes,
                    tolerance,
                    maxTrustRegionSteps,
                    initialTrustRegionRadius,
                    multigridIterations,
                    innerTolerance,
Oliver Sander's avatar
Oliver Sander committed
                    1, 3, 3,
                    100,     // iterations of the base solver
                    1e-8,    // base tolerance
                    false);  // instrumentation
#else
    rodSolver.setupTCG(grid, 
                       &rodAssembler,
                       x,
                       dirichletNodes,
                       tolerance,
                       maxTrustRegionSteps,
                       initialTrustRegionRadius,
                       multigridIterations,
                       innerTolerance,
                       false);  // instrumentation
#endif

    // /////////////////////////////////////////////////////
    //   Solve!
    // /////////////////////////////////////////////////////

    rodSolver.setInitialSolution(x);
    rodSolver.solve();

    x = rodSolver.getSol();
}

int main (int argc, char *argv[]) try
{
    // parse data file
    ConfigParser parameterSet;
    if (argc==2)
        parameterSet.parseFile(argv[1]);
    else
        parameterSet.parseFile("rod-eoc.parset");

    // read solver settings
    const int numLevels        = parameterSet.get<int>("numLevels");
    const int nu1              = parameterSet.get<int>("nu1");
    const int nu2              = parameterSet.get<int>("nu2");
    const int mu               = parameterSet.get<int>("mu");
    const int baseIterations      = parameterSet.get<int>("baseIt");
    const double baseTolerance    = parameterSet.get<double>("baseTolerance");

    const int numRodBaseElements = parameterSet.get<int>("numRodBaseElements");
    
    // /////////////////////////////////////////
    //   Read Dirichlet values
    // /////////////////////////////////////////

    RigidBodyMotion<3> dirichletValue;
    dirichletValue.r[0] = parameterSet.get<double>("dirichletValueX");
    dirichletValue.r[1] = parameterSet.get<double>("dirichletValueY");
    dirichletValue.r[2] = parameterSet.get<double>("dirichletValueZ");

    FieldVector<double,3> axis;
    axis[0] = parameterSet.get<double>("dirichletAxisX");
    axis[1] = parameterSet.get<double>("dirichletAxisY");
    axis[2] = parameterSet.get<double>("dirichletAxisZ");
    double angle = parameterSet.get<double>("dirichletAngle");

    dirichletValue.q = Rotation<3,double>(axis, M_PI*angle/180);

    // ///////////////////////////////////////////////////////////
    //   First compute the 'exact' solution on a very fine grid
    // ///////////////////////////////////////////////////////////

    //    Create the reference grid
    
    GridType referenceGrid(numRodBaseElements, 0, 1);
    
    referenceGrid.globalRefine(numLevels-1);

    //  Solve the rod Dirichlet problem
    SolutionType referenceSolution;
    solve(referenceGrid, referenceSolution, numLevels, dirichletValue, parameterSet);


    // //////////////////////////////////////////////////////////////////////
    //   Compute mass matrix and laplace matrix to emulate L2 and H1 norms
    // //////////////////////////////////////////////////////////////////////

Oliver Sander's avatar
Oliver Sander committed
    typedef P1NodalBasis<GridType::LeafGridView,double> FEBasis;
    FEBasis basis(referenceGrid.leafView());
    OperatorAssembler<FEBasis,FEBasis> operatorAssembler(basis, basis);
Oliver Sander's avatar
Oliver Sander committed
    LaplaceAssembler<GridType, FEBasis::LocalFiniteElement, FEBasis::LocalFiniteElement> laplaceLocalAssembler;
    MassAssembler<GridType, FEBasis::LocalFiniteElement, FEBasis::LocalFiniteElement> massMatrixLocalAssembler;
Oliver Sander's avatar
Oliver Sander committed
    typedef Dune::BCRSMatrix<Dune::FieldMatrix<double,1,1> > ScalarMatrixType;
    ScalarMatrixType laplace, massMatrix;

    operatorAssembler.assemble(laplaceLocalAssembler, laplace);
    operatorAssembler.assemble(massMatrixLocalAssembler, massMatrix);

    // ///////////////////////////////////////////////////////////
    //   Compute on all coarser levels, and compare
    // ///////////////////////////////////////////////////////////
    
    for (int i=1; i<=numLevels; i++) {

        GridType grid(numRodBaseElements, 0, 1);
        grid.globalRefine(i-1);

        // compute again
        SolutionType solution;
        solve(grid, solution, i, dirichletValue, parameterSet);

        // Prolong solution to the very finest grid
        for (int j=i; j<numLevels; j++)
            globalRodRefine(grid, solution);

Oliver Sander's avatar
Oliver Sander committed
        std::stringstream numberAsAscii;
        numberAsAscii << i;
        writeRod(solution, "rodGrid_" + numberAsAscii.str());

        assert(referenceSolution.size() == solution.size());

        BlockVector<TargetSpace::TangentVector> difference = computeGeodesicDifference(solution,referenceSolution);

Oliver Sander's avatar
Oliver Sander committed
        H1SemiNorm< BlockVector<TargetSpace::TangentVector> > h1Norm(laplace);
        H1SemiNorm< BlockVector<TargetSpace::TangentVector> > l2Norm(massMatrix);
        // Compute max-norm difference
        std::cout << "Level: " << i-1 
                  << ",   max-norm error: " << difference.infinity_norm()
                  << std::endl;

        std::cout << "Level: " << i-1 
                  << ",   L2 error: " << l2Norm(difference)
                  << std::endl;

        std::cout << "Level: " << i-1 
                  << ",   H1 error: " << h1Norm(difference)