Skip to content
Snippets Groups Projects
Select Git revision
  • dune-tkr-article
  • master default protected
  • patrizio-convexity-test
  • releases/2.6-1
  • releases/2.5-1
  • releases/2.4-1
  • releases/2.3-1
  • releases/2.2-1
  • releases/2.1-1
  • releases/2.0-1
  • dune-tkr-article-base
  • dune-tkr-article-patched
  • subversion->git
13 results

nonlinelast.cc

Blame
  • Forked from agnumpde / dune-elasticity
    206 commits behind the upstream repository.
    Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    nonlinelast.cc 12.61 KiB
    #include <config.h>
    
    #include <dune/common/parametertreeparser.hh>
    #include <dune/common/bitsetvector.hh>
    
    #include <dune/grid/uggrid.hh>
    #include <dune/grid/io/file/amirameshwriter.hh>
    #include <dune/grid/io/file/amirameshreader.hh>
    
    #include <dune/istl/io.hh>
    
    #include <dune/fufem/functionspacebases/p2nodalbasis.hh>
    #include <dune/fufem/functionspacebases/p1nodalbasis.hh>
    #include <dune/fufem/functiontools/gridfunctionadaptor.hh>
    #include <dune/fufem/estimators/hierarchicalestimator.hh>
    #include <dune/fufem/assemblers/localassemblers/laplaceassembler.hh>
    #include <dune/fufem/estimators/fractionalmarking.hh>
    #include <dune/fufem/estimators/refinementindicator.hh>
    #include <dune/fufem/utilities/dirichletbcassembler.hh>
    
    #ifdef HAVE_IPOPT
    #include <dune/solvers/solvers/quadraticipopt.hh>
    #endif
    
    #include <dune/solvers/solvers/loopsolver.hh>
    #include <dune/solvers/norms/energynorm.hh>
    #include <dune/solvers/iterationsteps/mmgstep.hh>
    #include <dune/solvers/transferoperators/mandelobsrestrictor.hh>
    #include <dune/solvers/transferoperators/truncatedcompressedmgtransfer.hh>
    #include <dune/solvers/iterationsteps/trustregiongsstep.hh>
    #include <dune/solvers/solvers/trustregionsolver.hh>
    
    #include <dune/elasticity/common/nonlinearelasticityproblem.hh>
    #define LAURSEN
    #include <dune/elasticity/materials/neohookeanmaterial.hh>
    
    // The grid dimension
    const int dim = 3;
    typedef double field_type;
    using namespace Dune;
    
    int main (int argc, char *argv[]) try
    {
        // Some types that I need
        typedef BCRSMatrix<FieldMatrix<double, dim, dim> > MatrixType;
        typedef BlockVector<FieldVector<double, dim> >     VectorType;
    
        // parse data file
        ParameterTree parameterSet;
        if (argc==2)
            ParameterTreeParser::readINITree(argv[1], parameterSet);
        else
            ParameterTreeParser::readINITree("nonlinelast.parset", parameterSet);
    
        // read solver settings
        const int minLevel         = parameterSet.get<int>("minLevel");
        const int maxLevel         = parameterSet.get<int>("maxLevel");
        const bool useH1SemiNorm   = parameterSet.get<bool>("useH1SemiNorm");
    
        // read problem settings
        std::string path           = parameterSet.get<std::string>("path");
        std::string resultPath     = parameterSet.get<std::string>("resultPath");
        std::string gridFile       = parameterSet.get<std::string>("gridFile");
    
        // /////////////////////////////
        //   Generate the grid
        // /////////////////////////////
        typedef UGGrid<dim> GridType;
        GridType* grid = new GridType;
    
        if (parameterSet.hasKey("parFile")) {
            std::string parFile = parameterSet.get<std::string>("parFile");
            grid = AmiraMeshReader<GridType>::read(path + gridFile, PSurfaceBoundary<dim-1>::read(path + parFile));
        } else
            AmiraMeshReader<GridType>::read(*grid, path + gridFile);
    
        // Read coarse Dirichlet boundary values
        BitSetVector<dim> coarseDirichletNodes;
        VectorType coarseDirichletValues;
        DirichletBCAssembler<GridType>::assembleDirichletBC(*grid, parameterSet,
                                        coarseDirichletNodes, coarseDirichletValues,
                                        path);
        const double scaling       = parameterSet.get<double>("scaling");
        coarseDirichletValues *= scaling;
    
    
        //  //////////////////////
        //  Uniform refine grid
        //  /////////////////////
    
        grid->setRefinementType(GridType::COPY);
        for (int i=0; i<minLevel; i++)
            grid->globalRefine(1);
    
        // Initial solution
        VectorType x(grid->size(dim));
        x = 0;
    
        // /////////////////////////////////////
        //setup the monotone multigrid step
        // /////////////////////////////////////
    
    
        MonotoneMGStep<MatrixType,VectorType> mmgStep;
        mmgStep.setMGType(parameterSet.get("mu",1),
                parameterSet.get("preSmoothingSteps",3),
                parameterSet.get("postSmoothingSteps",3));
    
        TrustRegionGSStep<MatrixType, VectorType> presmoother,postsmoother;
        mmgStep.setSmoother(&presmoother, &postsmoother);
    
        mmgStep.setObstacleRestrictor(MandelObstacleRestrictor<VectorType>());
        mmgStep.setVerbosity(parameterSet.get<NumProc::VerbosityMode>("verbosity"));
    
        // Create a base solver
    #ifdef HAVE_IPOPT
    
        QuadraticIPOptSolver<MatrixType,VectorType> baseSolver(parameterSet.get<field_type>("baseTolerance"),
                                                               100, NumProc::QUIET);
    #endif
        mmgStep.setBaseSolver(baseSolver);
    
        EnergyNorm<MatrixType, VectorType> h1SemiNorm;
        EnergyNorm<MatrixType, VectorType  > energyNorm(mmgStep);
    
        ::LoopSolver<VectorType> solver(mmgStep,
                parameterSet.get<int>("mgIterations"),
                parameterSet.get<field_type>("mgTolerance"),
                (useH1SemiNorm) ? h1SemiNorm : energyNorm,
                Solver::FULL);
    
    
        // /////////////////////////////////
        // Setup the nonlinear material
        // ////////////////////////////////
        //
        typedef P1NodalBasis<GridType::LeafGridView> P1Basis;
        P1Basis p1Basis(grid->leafGridView());
        typedef NeoHookeanMaterial<P1Basis> MaterialType;
        MaterialType material(p1Basis,
                              parameterSet.get<double>("E"),
                              parameterSet.get<double>("nu"));
    
    
        // ///////////////////////////////////////////////////
        //   Do a homotopy of the Dirichlet boundary data
        // ///////////////////////////////////////////////////
    
        field_type loadFactor    = 0;
        field_type loadIncrement = parameterSet.get<double>("loadIncrement");
    
        for (int level=minLevel; level<=maxLevel; level++) {
    
    
            VectorType extForces(grid->size(dim));
            extForces = 0;
    
            // Dirichlet values on the fine grid
            Dune::BitSetVector<dim> dirichletNodes;
            VectorType dirichletValues;
    
            DirichletBCAssembler<GridType>::assembleDirichletBC(*grid,
                                    coarseDirichletNodes,coarseDirichletValues,
                                    dirichletNodes, dirichletValues);
    
            mmgStep.setIgnore(dirichletNodes);
    
            //////////////////////////////////
            //  Create the transfer operator
            //////////////////////////////////
    
            std::vector<std::shared_ptr<TruncatedCompressedMGTransfer<VectorType> > > mgTransfers(grid->maxLevel());
            for (size_t i=0; i<mgTransfers.size(); i++) {
    
                mgTransfers[i] = std::make_shared<TruncatedCompressedMGTransfer<VectorType> >();
                mgTransfers[i]->setup(*grid,i,i+1);
            }
    
            mmgStep.setTransferOperators(mgTransfers);
    
            // //////////////////////////////////////////////////////////
            //   Create obstacles
            // //////////////////////////////////////////////////////////
    
            mmgStep.setHasObstacles(BitSetVector<dim>(dirichletNodes.size(), true));
    
            LaplaceAssembler<GridType, P1Basis::LocalFiniteElement, P1Basis::LocalFiniteElement,MatrixType::block_type> laplace;
            OperatorAssembler<P1Basis, P1Basis> operatorAssembler(p1Basis, p1Basis);
    
            MatrixType laplaceMatrix;
            operatorAssembler.assemble(laplace, laplaceMatrix);
            h1SemiNorm.setMatrix(&laplaceMatrix);
    
    
            //////////////////////////////////////////////////////////////
            //  Create the nonlinear elasticity problem
            /////////////////////////////////////////////////////////////
    
            // Make static contact problem
            typedef NonlinearElasticityProblem<VectorType,MatrixType, P1Basis> ElasticityProblem;
            ElasticityProblem elasticProblem(material, extForces);
    
            // Create trust-region step
            TrustRegionSolver<ElasticityProblem, VectorType, MatrixType> trustRegionSolver;
            //TODO Allow a different norm here
            const ParameterTree& trConfig = parameterSet.sub("trConfig");
            trustRegionSolver.setup(trConfig, h1SemiNorm, elasticProblem, solver);
    
    
            typedef BasisGridFunction<P1Basis,VectorType> BasisGridFunction;
            VectorType deformedX;
    
            do {
    
                deformedX = x;
    
                if (loadFactor < 1) {
    
                    // ////////////////////////////////////////////////////
                    //   Compute new feasible load increment
                    // ////////////////////////////////////////////////////
    
    
                    loadIncrement *= 2;  // double it once, cause we're going to half it at least once, too!
                    bool isNan;
                    do {
    
                        loadIncrement /= 2;
    
                        // Set new Dirichlet values in solution
                        for (size_t k=0; k<dirichletNodes.size(); k++)
                            for (int j=0; j<dim; j++)
                                if (dirichletNodes[k][j])
                                    deformedX[k][j] = dirichletValues[k][j] * (loadFactor + loadIncrement);
    
                        isNan = false;
    
                        auto disp = std::make_shared<BasisGridFunction>(p1Basis,deformedX);
                        field_type eng = material.energy(disp);
                        std::cout<<"Energy "<<eng<<std::endl;
                        isNan |= std::isnan(eng);
                    } while (isNan);
    
                    loadFactor += loadIncrement;
    
                    std::cout << "####################################################" << std::endl;
                    std::cout << "New load factor: " << loadFactor
                        << "    new load increment: " << loadIncrement << std::endl;
                    std::cout << "####################################################" << std::endl;
    
                }
    
                // add Dirichlet values
                trustRegionSolver.setInitialIterate(deformedX);
                trustRegionSolver.solve();
                x = trustRegionSolver.getSol();
    
            } while (loadFactor < 1);
    
    
            // /////////////////////////////////////////////////////////////////////
            //   Refinement Loop
            // /////////////////////////////////////////////////////////////////////
    
            if (level==maxLevel)
                break;
    
            // ////////////////////////////////////////////////////////////////////////////
            //    Refine locally and transfer the current solution to the new leaf level
            // ////////////////////////////////////////////////////////////////////////////
    
            std::cout<<"Estimating error on  refinement level "<<level<<std::endl;
    
            // Create the materials
            typedef P2NodalBasis<GridType::LeafGridView> P2Basis;
            P2Basis p2Basis(grid->leafGridView());
    
            typedef NeoHookeanMaterial<P2Basis> MaterialTypeP2;
            MaterialTypeP2 p2Material(p2Basis, parameterSet.get<field_type>("E"),
                                       parameterSet.get<field_type>("nu"));
    
            // P2 Forces
            VectorType p2ExtForces(p2Basis.size());
            p2ExtForces = 0;
    
            typedef NonlinearElasticityProblem<VectorType,MatrixType, P2Basis> ElasticityProblemP2;
            ElasticityProblemP2 elasticProblemP2(p2Material, p2ExtForces);
    
    
            RefinementIndicator<GridType> refinementIndicator(*grid);
    
            BitSetVector<1> scalarDirichletField;
            DirichletBCAssembler<GridType>::inflateBitField(dirichletNodes, scalarDirichletField);
            BoundaryPatch<GridType::LeafGridView> dirichletBoundary(grid->leafGridView(),scalarDirichletField);
    
            HierarchicalEstimator<P2Basis,dim> estimator(*grid);
            estimator.estimate(x, dirichletBoundary, refinementIndicator,elasticProblemP2);
    
    
            // ////////////////////////////////////////////////////
            //   Refine grids
            // ////////////////////////////////////////////////////
    
            std::cout<<"Mark elements"<<std::endl;
            FractionalMarkingStrategy<GridType>::mark(refinementIndicator, *grid,
                                        parameterSet.get<field_type>("refinementFraction"));
    
    
            GridFunctionAdaptor<P1Basis> adaptor(p1Basis,true,true);
    
            grid->preAdapt();
            grid->adapt();
            grid->postAdapt();
    
            p1Basis.update();
            adaptor.adapt(x);
    
    
            std::cout << "########################################################" << std::endl;
            std::cout << "  Grid refined," <<" max level: " << grid->maxLevel()
                    << "   vertices: " << grid->size(dim)
                    << "   elements: " << grid->size(0)<<std::endl;
            std::cout << "####################################################" << std::endl;
    
            Dune::LeafAmiraMeshWriter<GridType> amiramesh2;
            amiramesh2.addLeafGrid(*grid,true);
            amiramesh2.addVertexData(x,grid->leafGridView(),true);
            std::ostringstream name;
            name << "nonlinelastRefined" << std::setw(6) << std::setfill('0') <<level ;
            amiramesh2.write(resultPath +name.str(),1);
    
    
        }
    
        LeafAmiraMeshWriter<GridType> amiramesh;
        amiramesh.addLeafGrid(*grid,true);
        amiramesh.addVertexData(x, grid->leafGridView(),true);
        amiramesh.write(resultPath +"nonlineast.result",1);
    
    } catch (Exception e) {
    
        std::cout << e << std::endl;
    
    }