Skip to content
Snippets Groups Projects
staticrod.cc 12.2 KiB
Newer Older
  • Learn to ignore specific revisions
  • #include <config.h>
    
    #include <dune/grid/onedgrid.hh>
    
    #include <dune/fem/lagrangebase.hh>
    
    Oliver Sander's avatar
    .  
    Oliver Sander committed
    #include <dune/grid/common/gridpart.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;
    
    Oliver Sander's avatar
    .  
    Oliver Sander committed
        typedef LevelGridPart<RodGridType> RodGridPartType;
        typedef LagrangeDiscreteFunctionSpace < RodFuncSpace, RodGridPartType, 1> RodFuncSpaceType;
    
    Oliver Sander's avatar
    .  
    Oliver Sander committed
        Array<RodGridPartType*> rodGridPart(maxlevel+1);
    
        Array<const RodFuncSpaceType*> rodFuncSpace(maxlevel+1);
    
        for (int i=0; i<maxlevel+1; i++) {
    
    Oliver Sander's avatar
    .  
    Oliver Sander committed
            rodGridPart[i]  = new RodGridPartType(rod, i);
            rodFuncSpace[i] = new RodFuncSpaceType(*rodGridPart[i]);
    
        }
    
    
        // ////////////////////////////////////////////////////////////
        //    Create solution and rhs vectors
        // ////////////////////////////////////////////////////////////
    
        VectorType rhs;
        VectorType x;
        VectorType corr;
    
        MatrixType hessianMatrix;
    
        RodAssembler<RodFuncSpaceType, 4> rodAssembler(*rodFuncSpace[maxlevel]);
        rodAssembler.setParameters(1, 100, 100);
    
    
        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();
    
    Oliver Sander's avatar
    .  
    Oliver Sander committed
            obstacles[maxlevel][i].val[0] =     - x[i][0];
    
            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::QUIET;
    
        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;
    
    
            // The continuation variable determines the material parameters
            double A1 = loadFactor * 1000;
            double A3 = loadFactor * 1000;
            rodAssembler.setParameters(1, A1, A3);
    
    
            // /////////////////////////////////////////////////////
            //   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: %e\n", factor, energy);
    
                 }
    
                 std::cout << "Damping factor: " << smallestFactor << std::endl;
    
                 //exit(0);
    
                 //  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;
                 }
    
    
            // Write Lagrange multiplyers
            std::stringstream a1AsAscii, a3AsAscii;
            a1AsAscii << A1;
            a3AsAscii << A3;
            std::string lagrangeFilename = "pressure/lagrange_" + a1AsAscii.str() + "_" + a3AsAscii.str();
            std::ofstream lagrangeFile(lagrangeFilename.c_str());
    
            VectorType lagrangeMultipliers;
            rodAssembler.assembleGradient(x, lagrangeMultipliers);
            lagrangeFile << lagrangeMultipliers << std::endl;
            
            // Write result grid
            std::string solutionFilename = "solutions/rod_" + a1AsAscii.str() 
                + "_" + a3AsAscii.str() + ".result";
            writeRod(x, solutionFilename);
    
        } while (loadFactor < 1);
    
    
    
     } catch (Exception e) {
    
        std::cout << e << std::endl;
    
     }