Skip to content
Snippets Groups Projects
staticrod.cc 11.6 KiB
Newer Older
  • Learn to ignore specific revisions
  • #include <config.h>
    
    #include <dune/grid/onedgrid.hh>
    
    #include <dune/fem/lagrangebase.hh>
    
    #include <dune/istl/io.hh>
    
    //#include "../common/boundarytreatment.hh"
    #include "../common/boundarypatch.hh"
    #include <dune/common/bitfield.hh>
    //#include "../common/readbitfield.hh"
    
    #include "src/rodassembler.hh"
    //#include "../common/linearipopt.hh"
    
    #include "../common/projectedblockgsstep.hh"
    
    #include "../contact/src/contactmmgstep.hh"
    
    
    #include <dune/solver/iterativesolver.hh>
    
    #include "../common/geomestimator.hh"
    #include "../common/energynorm.hh"
    #include <dune/common/configparser.hh>
    
    #include "src/rodwriter.hh"
    
    
    // Choose a solver
    //#define IPOPT
    
    //#define GAUSS_SEIDEL
    #define MULTIGRID
    
    
    // Number of degrees of freedom: 
    // 3 (x, y, theta) for a planar rod
    const int blocksize = 3;
    
    using namespace Dune;
    using std::string;
    
    int main (int argc, char *argv[]) try
    {
        // Some types that I need
        typedef BCRSMatrix<FieldMatrix<double, blocksize, blocksize> > MatrixType;
        typedef BlockVector<FieldVector<double, blocksize> >     VectorType;
    
        // parse data file
        ConfigParser parameterSet;
        parameterSet.parseFile("staticrod.parset");
    
        // read solver settings
        const int maxLevel         = parameterSet.get("maxLevel", int(0));
        double loadIncrement       = parameterSet.get("loadIncrement", double(0));
        const int maxNewtonSteps   = parameterSet.get("maxNewtonSteps", int(0));
        const int numIt            = parameterSet.get("numIt", int(0));
        const int nu1              = parameterSet.get("nu1", int(0));
        const int nu2              = parameterSet.get("nu2", int(0));
        const int mu               = parameterSet.get("mu", int(0));
        const int baseIt           = parameterSet.get("baseIt", int(0));
        const double tolerance     = parameterSet.get("tolerance", double(0));
        const double baseTolerance = parameterSet.get("baseTolerance", double(0));
        
        // Problem settings
    
        const int numRodBaseElements = parameterSet.get("numRodBaseElements", int(0));
    
    
        // ///////////////////////////////////////
        //    Create the two grids
        // ///////////////////////////////////////
        typedef OneDGrid<1,1> RodGridType;
    
        RodGridType rod(numRodBaseElements, 0, 1);
    
        // refine uniformly until maxLevel
        for (int i=0; i<maxLevel; i++)
    
            rod.globalRefine(1);
    
        int maxlevel = rod.maxlevel();
    
        int numRodElements = rod.size(maxlevel, 0);
    
        
        Array<BitField> dirichletNodes;
        dirichletNodes.resize(maxLevel+1);
        for (int i=0; i<=maxlevel; i++) {
    
            dirichletNodes[i].resize( blocksize * rod.size(i,1) );
    
            dirichletNodes[i].unsetAll();
    
            for (int j=0; j<blocksize; j++) {
                dirichletNodes[i][j] = true;
                dirichletNodes[i][dirichletNodes[i].size()-1-j] = true;
            }
        }
    
    
        // //////////////////////////////////////////////////////////
        //    Create discrete function spaces
        // //////////////////////////////////////////////////////////
    
        typedef FunctionSpace < double , double, 1, 1 > RodFuncSpace;
        typedef DefaultGridIndexSet<RodGridType,LevelIndex> RodIndexSet;
        typedef LagrangeDiscreteFunctionSpace < RodFuncSpace, RodGridType,RodIndexSet,  1> RodFuncSpaceType;
    
        Array<RodIndexSet*> rodIndexSet(maxlevel+1);
        Array<const RodFuncSpaceType*> rodFuncSpace(maxlevel+1);
    
        for (int i=0; i<maxlevel+1; i++) {
            rodIndexSet[i]  = new RodIndexSet(rod, i);
            rodFuncSpace[i] = new RodFuncSpaceType(rod, *rodIndexSet[i], i);
        }
    
    
        // ////////////////////////////////////////////////////////////
        //    Create solution and rhs vectors
        // ////////////////////////////////////////////////////////////
    
        VectorType rhs;
        VectorType x;
        VectorType corr;
    
        MatrixType hessianMatrix;
    
        RodAssembler<RodFuncSpaceType, 2> rodAssembler(*rodFuncSpace[maxlevel]);
        rodAssembler.setParameters(1, 10, 10);
    
        MatrixIndexSet indices(numRodElements+1, numRodElements+1);
        rodAssembler.getNeighborsPerVertex(indices);
        indices.exportIdx(hessianMatrix);
    
    
    
        rhs.resize(rodFuncSpace[maxlevel]->size());
        x.resize(rodFuncSpace[maxlevel]->size());
        corr.resize(rodFuncSpace[maxlevel]->size());
        
        // Initial solution
        x = 0;
    
        for (int i=0; i<numRodElements+1; i++) {
            x[i][0] = i/((double)numRodElements);
            x[i][1] = 0;
            x[i][2] = M_PI/2;
        }
    
    
        x[0][0] = x[numRodElements][0] = 0;
        x[0][1] = x[numRodElements][1] = 0;
    
        x[0][2] = 0;
        x[numRodElements][2] = 2*M_PI;
    
        // //////////////////////////////////////////////////////////
        //   Create obstacles
        // //////////////////////////////////////////////////////////
    
        Array<BitField> hasObstacle;
        hasObstacle.resize(maxLevel+1);
        for (int i=0; i<hasObstacle.size(); i++) {
            hasObstacle[i].resize(rod.size(i, 1));
            hasObstacle[i].setAll();
        }
    
        Array<SimpleVector<BoxConstraint<3> > > obstacles(maxlevel+1);
    
        for (int i=0; i<obstacles.size(); i++)
            obstacles[i].resize(rod.size(i,1));
    
        for (int i=0; i<obstacles[maxlevel].size(); i++) {
            obstacles[maxlevel][i].clear();
            obstacles[maxlevel][i].val[1] = 0.1 - x[i][0];
        }
    
    
        // Create a solver
    #if defined IPOPT
    
        typedef LinearIPOptSolver<VectorType> SolverType;
        
        SolverType solver;
        solver.dirichletNodes_ = &totalDirichletNodes[maxlevel];
        solver.hasObstacle_    = &contactAssembler.hasObstacle_[maxlevel];
        solver.obstacles_      = &contactAssembler.obstacles_[maxlevel];
        solver.verbosity_      = Solver::FULL;
    
    #elif defined GAUSS_SEIDEL
    
        typedef ProjectedBlockGSStep<MatrixType, VectorType> SmootherType;
        SmootherType projectedBlockGSStep(hessianMatrix, corr, rhs);
        projectedBlockGSStep.dirichletNodes_ = &dirichletNodes[maxlevel];
        projectedBlockGSStep.hasObstacle_    = &hasObstacle[maxlevel];
    
        projectedBlockGSStep.obstacles_      = &obstacles;
    
    
        EnergyNorm<MatrixType, VectorType> energyNorm(projectedBlockGSStep);
    
        IterativeSolver<MatrixType, VectorType> solver;
        solver.iterationStep = &projectedBlockGSStep;
        solver.numIt = numIt;
    
        solver.verbosity_ = Solver::FULL;
    
        solver.errorNorm_ = &energyNorm;
        solver.tolerance_ = tolerance;
        
    #elif defined MULTIGRID
    
    
        // First create a gauss-seidel base solver
        ProjectedBlockGSStep<MatrixType, VectorType> baseSolverStep;
    
        EnergyNorm<MatrixType, VectorType> baseEnergyNorm(baseSolverStep);
    
        IterativeSolver<MatrixType, VectorType> baseSolver;
    
        baseSolver.iterationStep = &baseSolverStep;
        baseSolver.numIt = baseIt;
        baseSolver.verbosity_ = Solver::QUIET;
        baseSolver.errorNorm_ = &baseEnergyNorm;
        baseSolver.tolerance_ = baseTolerance;
    
        // Make pre and postsmoothers
    
        ProjectedBlockGSStep<MatrixType, VectorType> presmoother;
        ProjectedBlockGSStep<MatrixType, VectorType> postsmoother;
    
        ContactMMGStep<MatrixType, VectorType, RodFuncSpaceType > contactMMGStep(maxlevel+1);
    
        contactMMGStep.setMGType(mu, nu1, nu2);
        contactMMGStep.dirichletNodes_    = &dirichletNodes;
    
        contactMMGStep.basesolver_        = &baseSolver;
        contactMMGStep.presmoother_       = &presmoother;
        contactMMGStep.postsmoother_      = &postsmoother;    
        contactMMGStep.hasObstacle_       = &hasObstacle;
    
        contactMMGStep.obstacles_         = &obstacles;
    
    
        // Create the transfer operators
        contactMMGStep.mgTransfer_.resize(maxlevel);
    
        for (int i=0; i<contactMMGStep.mgTransfer_.size(); i++){
            TruncatedMGTransfer<VectorType>* newTransferOp = new TruncatedMGTransfer<VectorType>;
            newTransferOp->setup(*rodFuncSpace[i], *rodFuncSpace[i+1]);
            contactMMGStep.mgTransfer_[i] = newTransferOp;
        }
    
    
        EnergyNorm<MatrixType, VectorType> energyNorm(contactMMGStep);
    
    
        IterativeSolver<MatrixType, VectorType> solver;
    
        solver.iterationStep = &contactMMGStep;
        solver.numIt = numIt;
        solver.verbosity_ = Solver::FULL;
        solver.errorNorm_ = &energyNorm;
        solver.tolerance_ = tolerance;
    
    #else
        #warning You have to specify a solver!
    #endif
    
        // ///////////////////////////////////////////////////
        //   Do a homotopy of the Dirichlet boundary data
        // ///////////////////////////////////////////////////
        double loadFactor = 0;
    
        do {
    
            loadFactor += loadIncrement;
    
            std::cout << "####################################################" << std::endl;
            std::cout << "New load factor: " << loadFactor 
                      << "    new load increment: " << loadIncrement << std::endl;
            std::cout << "####################################################" << std::endl;
    
            // /////////////////////////////////////////////////////
            //   Newton Solver
            // /////////////////////////////////////////////////////
    
            for (int j=0; j<maxNewtonSteps; j++) {
    
    
                std::cout << "----------------------------------------------------" << std::endl;
                std::cout << "      Newton Step Number: " << j << std::endl;
                std::cout << "----------------------------------------------------" << std::endl;
    
    
                rhs = 0;
                corr = 0;
    
    
                //std::cout <<"Solution: " << x << std::endl;
    
                rodAssembler.assembleGradient(x, rhs);
                rodAssembler.assembleMatrix(x, hessianMatrix);
    
                rhs *= -1;
    
    
                //std::cout << "rhs: " << std::endl << rhs << std::endl;
    
    
    #ifndef IPOPT
                solver.iterationStep->setProblem(hessianMatrix, corr, rhs);
    #else
                solver.setProblem(hessianMatrix, corr, rhs);
    #endif
    
                solver.preprocess();
    #ifdef MULTIGRID
    
                contactMMGStep.preprocess();
    #endif
    
                // /////////////////////////////
                //    Solve !
                // /////////////////////////////
                 solver.solve();
    
    #ifdef MULTIGRID
    
                 corr = contactMMGStep.getSol();
    
                 //std::cout << "Correction: \n" << corr << std::endl;
    
    
                 // line search
                 printf("------  Line Search ---------\n");
                 int lSSteps = 10;
                 double smallestEnergy = std::numeric_limits<double>::max();
                 double smallestFactor = 1;
                 for (int k=0; k<lSSteps; k++) {
    
                     double factor = double(k)/(lSSteps-1);
                     VectorType sCorr = corr;
                     sCorr *= factor;
                     sCorr += x;
    
                     double energy = rodAssembler.computeEnergy(sCorr);
    
                     if (energy < smallestEnergy) {
                         smallestEnergy = energy;
                         smallestFactor = factor;
                     }
                     //printf("factor: %g,  energy: %g\n", factor, energy);
                 }
    
                 std::cout << "Damping factor: " << smallestFactor << std::endl;
    
                 //  Add correction to the current solution
                 x.axpy(smallestFactor, corr);
    
                 // Output result
    
                 //std::cout << "Solution:" << std::endl << x << std::endl;
    
                 printf("infinity norm of the correction: %g\n", smallestFactor*corr.infinity_norm());
                 if (smallestFactor*corr.infinity_norm() < 1e-8)
    
                 // Subtract correction from the current obstacle
                 for (int k=0; k<corr.size(); k++) {
                     FieldVector<double, blocksize> tmp = corr[k];
                     tmp *= smallestFactor;
                     obstacles[maxlevel][k] -= tmp;
                 }
    
    
            }
            
            
        } while (loadFactor < 1);
    
    
        // Write result grid
        writeRod(x, "rod.result");
    
        // Write Lagrange multiplyers
        std::ofstream lagrangeFile("lagrange");
    
        VectorType lagrangeMultipliers;
        rodAssembler.assembleGradient(x, lagrangeMultipliers);
        lagrangeFile << lagrangeMultipliers << std::endl;
    
    
    
     } catch (Exception e) {
    
        std::cout << e << std::endl;
    
     }