From e8570c8e6ab699a64b7d4bbe63ea084bf2a5f9bf Mon Sep 17 00:00:00 2001
From: Jonathan Youett <youett@math.fu-berlin.de>
Date: Mon, 12 Nov 2018 10:44:50 +0100
Subject: [PATCH] One body large deformation contact solver, might need major
 cleanup

---
 1bnbnonlincontact.cc | 1017 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 1017 insertions(+)
 create mode 100644 1bnbnonlincontact.cc

diff --git a/1bnbnonlincontact.cc b/1bnbnonlincontact.cc
new file mode 100644
index 00000000..7b3af24f
--- /dev/null
+++ b/1bnbnonlincontact.cc
@@ -0,0 +1,1017 @@
+#include <config.h>
+
+#include <sys/stat.h>
+
+#include <dune/common/bitsetvector.hh>
+#include <dune/common/parametertree.hh>
+#include <dune/common/parametertreeparser.hh>
+
+#include <dune/grid/uggrid.hh>
+#include <dune/grid/sgrid.hh>
+#include <dune/grid/geometrygrid/grid.hh>
+#include <dune/grid/io/file/amirameshwriter.hh>
+#include <dune/grid/io/file/amirameshreader.hh>
+
+#include <dune/istl/io.hh>
+
+#include <dune/fufem/sampleonbitfield.hh>
+#include <dune/fufem/boundarypatchprolongator.hh>
+#include <dune/fufem/readbitfield.hh>
+#include <dune/fufem/estimators/fractionalmarking.hh>
+#include <dune/fufem/assemblers/localassemblers/stvenantkirchhoffassembler.hh>
+#include <dune/fufem/assemblers/operatorassembler.hh>
+#include <dune/fufem/functiontools/gridfunctionadaptor.hh>
+#include <dune/fufem/functionspacebases/p1nodalbasis.hh>
+
+#include <dune/solvers/iterationsteps/mmgstep.hh>
+
+#ifdef HAVE_IPOPT
+#include <dune/solvers/solvers/quadraticipopt.hh>
+#endif
+#include <dune/solvers/iterationsteps/trustregiongsstep.hh>
+#include <dune/solvers/solvers/iterativesolver.hh>
+#include <dune/solvers/norms/energynorm.hh>
+
+
+// from the 'dune-contact module
+#include <dune/contact/estimators/hierarchiccontactestimator.hh>
+#include <dune/contact/assemblers/onebodyassembler.hh>
+#include <dune/contact/solvers/trustregionstep.hh>
+#include <dune/contact/solvers/contacttransfer.hh>
+#include <dune/contact/solvers/contactobsrestrict.hh>
+#include <dune/contact/solvers/nonlinearcontacttnnmgstep.hh>
+#include <dune/contact/common/onebodystaticcontactproblem.hh>
+
+#include <dune/elasticity/materials/neohookeanmaterial.hh>
+#include <dune/elasticity/assemblers/neohookeassembler.hh>
+#include <dune/elasticity/materials/geomexactstvenantkirchhoffmaterial.hh>
+
+#include "../dune-biomech/dune/biomech/amirameshfilehandler.hh"
+
+// The grid dimension
+const int dim = 3;
+
+typedef double field_type;
+
+using namespace Dune;
+using std::string;
+using std::vector;
+using std::map;
+
+// Some types that I need
+typedef BCRSMatrix<FieldMatrix<double, dim, dim> > MatrixType;
+typedef BlockVector<FieldVector<double, dim> >     VectorType;
+
+
+double obs(const FieldVector<double, dim>& x) {return 1.00667 + x[dim-1];}
+
+
+class ConstantFunc: public  Dune::VirtualFunction<FieldVector<double,dim>,FieldVector<double,dim> >
+{
+public:
+
+    ConstantFunc(FieldVector<double,dim> vec) :
+        vec_(vec)
+    {}
+
+    virtual void evaluate(const FieldVector<double,dim>& x, FieldVector<double,dim>& y) const
+    {
+         y = vec_;
+
+    }
+
+private:
+    FieldVector<double,dim> vec_;
+};
+
+
+
+
+// Concatenate a string and a number
+string makeName(const std::string& name, int number)
+{
+    std::stringstream numberAsAscii;
+    numberAsAscii << number;
+    return name + numberAsAscii.str();
+}
+
+/** \todo The need for the method really is a symptom of bad design */
+size_t index(const std::string& name, const vector<string>& gridNames)
+{
+    for (size_t i=0; i<gridNames.size(); i++)
+        if (name == gridNames[i])
+            return i;
+
+    DUNE_THROW(RangeError, "Grid '" << name << "' not found!");
+}
+
+
+
+int main (int argc, char *argv[]) try
+{
+    // parse data file
+    ParameterTree parameterSet;
+    if (argc==2)
+        ParameterTreeParser::readINITree(argv[1], parameterSet);
+    else
+        ParameterTreeParser::readINITree("1bnbnonlincontact.parset", parameterSet);
+
+    // Some problem settings
+    const int minLevel         = parameterSet.get<int>("minLevel");
+    const int maxLevel         = parameterSet.get<int>("maxLevel");
+    const bool paramBoundaries = parameterSet.get<bool>("paramBoundaries");
+
+    // Read solver settings
+
+    // _Both_ multigrid solvers
+    const int multigridIterations = parameterSet.get<int>("mgIterations");
+    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 mgTolerance      = parameterSet.get<double>("mgTolerance");
+    const double baseTolerance    = parameterSet.get<double>("baseTolerance");
+    const double refinementFraction = parameterSet.get("refinementFraction", double(1));
+
+    const bool writeStresses        = parameterSet.get<bool>("writeStresses");
+
+    // Trust region parameter
+    const int trustRegionNumIt      = parameterSet.get<int>("trustRegionIterations");
+    const double trustRegionTol      = parameterSet.get<double>("trustRegionTolerance");
+    double trustRegionRadius  = parameterSet.get<double>("trustRegionRadius");
+    const double maxTRRadius  = parameterSet.get<double>("maxTRRadius");
+
+    /////////////////////////////////////////////////////////////////////////////////////
+    //   Read the actual problem configuration, i.e., grids, and how they are coupled
+    /////////////////////////////////////////////////////////////////////////////////////
+
+    ParameterTree problemConfiguration;
+    ParameterTreeParser::readINITree(parameterSet.get<string>("configurationFile"), problemConfiguration);
+
+    // simulate gravity
+    const bool simulateGravity        = problemConfiguration.get<bool>("simulateGravity");
+    const bool useElasticityNorm        = problemConfiguration.get<bool>("useLinearElasticityNorm");
+
+    // in which coordinate direction does gravity act
+    const int heightCoord        = problemConfiguration.get<int>("heightCoord");
+    // scaling for the Dirichlet values
+    double scaling            = parameterSet.get<double>("scaling");
+
+    // read bone-related problem settings
+    string path               = problemConfiguration.get<string>("path");
+    string resultPath         = problemConfiguration.get<string>("resultPath");
+
+    // Get names of the grids
+    int numGrids = problemConfiguration.get<int>("numGrids");
+    std::vector<string> gridName(numGrids);
+    for (int i=0; i<numGrids; i++) {
+        gridName[i] = problemConfiguration.get<string>(makeName("gridName", i));
+    }
+
+    string gridFile[numGrids];
+    string parFile[numGrids];
+    string dnFile[numGrids];
+    string dvFile[numGrids];
+
+    for (int i=0; i<numGrids; i++) {
+        if (not problemConfiguration.hasSub(gridName[i]))
+            DUNE_THROW(Exception, "No data for '" << gridName[i] << "' is found in the configuration file!");
+        const ParameterTree& gridParameters = problemConfiguration.sub(gridName[i]);
+        gridFile[i]      = gridParameters.get<string>("gridFile");
+        parFile[i]       = gridParameters.get<string>("parFile");
+        dnFile[i]        = gridParameters.get<string>("dnFile");
+        dvFile[i]        = gridParameters.get<string>("dvFile");
+    }
+
+    // Read material properties
+    map<string, double> E;
+    map<string, double> Nu;
+    map<string, double> density;
+    map<string, double> D;
+
+    // Read general properties(which will be used if not specified individually)
+    const double gridE_default       = problemConfiguration.get("gridE", 1e5);
+    const double gridNu_default      = problemConfiguration.get("gridNu", 0.3);
+    const double gridDensity_default      = problemConfiguration.get("gridDensity", 1);
+    const double gridD_default      = problemConfiguration.get("gridD", 0);
+
+    for (int i=0; i<numGrids; i++) {
+    	const ParameterTree& gridParameters = problemConfiguration.sub(gridName[i]);
+    	E[gridName[i]] = gridParameters.get("E", gridE_default);
+    	Nu[gridName[i]] = gridParameters.get("Nu", gridNu_default);
+        density[gridName[i]] = gridParameters.get("density", gridDensity_default);
+        D[gridName[i]] = gridParameters.get("D", gridD_default);
+    }
+
+   // ////////////////////////////////////////////
+    //    Create the various bone grids
+    // ////////////////////////////////////////////
+
+
+    typedef UGGrid<dim> GridType;
+    typedef DeformationFunction<GridType::LeafGridView,VectorType> DeformationFunction;
+    typedef GeometryGrid<GridType,DeformationFunction> DeformedGridType;
+
+
+    typedef BoundaryPatch<GridType::LevelGridView> LevelBoundaryPatch;
+    typedef BoundaryPatch<GridType::LeafGridView> LeafBoundaryPatch;
+
+    map<string,DeformedGridType*> deformedGrids;
+    map<string,GridType*> grids;
+
+   for (int i=0; i<numGrids; i++) {
+
+        grids[gridName[i]] = new GridType;
+
+        if (paramBoundaries)
+            grids[gridName[i]] = AmiraMeshReader<GridType>::read(path + gridFile[i], path + parFile[i]);
+        else
+            grids[gridName[i]] = AmiraMeshReader<GridType>::read(path + gridFile[i]);
+    }
+
+      // initialize the deformed grids with zero displacements
+    std::vector<VectorType> displace(numGrids);
+    std::vector<DeformationFunction*> deformation(numGrids);
+    for (int i=0;i<numGrids;i++) {
+        displace[i].resize(grids[gridName[i]]->size(dim));
+        displace[i]=0;
+        deformation[i]=new DeformationFunction(grids[gridName[i]]->leafView(),displace[i]);
+        deformedGrids[gridName[i]]= new DeformedGridType(grids[gridName[i]],deformation[i]);
+    }
+
+    for (int i=0;i<numGrids;i++)
+        grids[gridName[i]]->setRefinementType(GridType::COPY);
+
+    // ////////////////////////////////////////////////////////////////////
+    //   Initial uniform refinement, if requested
+    // ////////////////////////////////////////////////////////////////////
+
+    for (int j=0;j<numGrids;j++) {
+
+        const ParameterTree& gridParameters = problemConfiguration.sub(gridName[j]);
+        // allow different refinement levels for each grid
+        int nRefine = gridParameters.get("nRefines",minLevel);
+
+        for (int i=0; i<nRefine; i++)
+            grids[gridName[j]]->globalRefine(1);
+    }
+
+    // adapt deformed grids
+    for (int i=0;i<numGrids;i++) {
+        displace[i].resize(grids[gridName[i]]->size(dim));
+        displace[i]=0;
+        deformation[i]->setDeformation(displace[i]);
+        deformedGrids[gridName[i]]->update();
+    }
+
+    //////////////////////////////////////////////////////////////////////////
+    //   Set up hierarchy of bitfields containing the Dirichlet flags
+    //////////////////////////////////////////////////////////////////////////
+    vector<VectorType> coarseDirichletValues(numGrids);
+
+    for (int i=0; i<numGrids; i++) {
+
+        coarseDirichletValues[i].resize(grids[gridName[i]]->size(0, dim));
+        coarseDirichletValues[i] = 0;
+
+        AmiraMeshReader<GridType>::readFunction(coarseDirichletValues[i], path + dvFile[i]);
+
+        // Scale Dirichlet values
+        coarseDirichletValues[i] *= scaling;
+    }
+
+    // Set up hierarchy of bitfields containing the Dirichlet flags
+    vector<LevelBoundaryPatch> coarseDirichletBoundary(numGrids);
+    vector<LeafBoundaryPatch> leafDirichletBoundary(numGrids);
+
+    for (int i=0; i<numGrids; i++) {
+        coarseDirichletBoundary[i].setup(grids[gridName[i]]->levelView(0));
+        leafDirichletBoundary[i].setup(grids[gridName[i]]->leafView());
+        readBoundaryPatch<GridType>(coarseDirichletBoundary[i],  path + dnFile[i]);
+    }
+
+    vector<BitSetVector<dim> > dirichletNodes(numGrids);
+
+    // Get overall top level
+    int toplevel = 0;
+    for (int i=0;i<numGrids;i++)
+        toplevel = std::max(toplevel, grids[gridName[i]]->maxLevel());
+
+    std::vector<VectorType> dirichletValues(numGrids);
+
+    for (int i=0; i<numGrids; i++) {
+
+        // Extend the dirichlet information to all grid levels
+        BoundaryPatchProlongator<GridType>::prolong(coarseDirichletBoundary[i], leafDirichletBoundary[i]);
+
+        // Copy vertices into bitfield
+        int fSSize = grids[gridName[i]]->size(dim);
+        dirichletNodes[i].resize(fSSize, false);
+        for (int k=0; k<fSSize; k++)
+            dirichletNodes[i][k] = leafDirichletBoundary[i].containsVertex(k);
+
+        sampleOnBitField(*grids[gridName[i]], coarseDirichletValues[i], dirichletValues[i], dirichletNodes[i]);
+        std::cout<<dirichletNodes[i].count()<<" Dirichlet nodes for grid "<<i<<std::endl;
+    }
+
+    // displacements of continua
+    vector<VectorType> u(numGrids),dirVals(numGrids), extForces(numGrids);
+
+    // add Dirichlet values
+    for (int i=0; i<numGrids; i++) {
+        u[i].resize(grids[gridName[i]]->size(dim));
+        u[i] = 0;
+        extForces[i] = u[i];
+        dirVals[i] = u[i];
+        for (size_t j=0; j<dirVals[i].size(); j++)
+            for (int k=0; k<dim; k++)
+                if (dirichletNodes[i][j][k])
+                    dirVals[i][j][k] = dirichletValues[i][j][k];
+    }
+
+    if (problemConfiguration.get<bool>("restart")) {
+        int loadStep = problemConfiguration.get<int>("loadingStep");
+
+        for (int i=0; i<numGrids; i++) {
+
+            std::string restartFile = genFilename(resultPath, makeName("grid",i) + "loading", loadStep);
+            AmiraMeshReader<GridType>::readFunction(u[i], restartFile);
+
+        }
+    }
+
+
+    // make dirichlet bitfields containing dirichlet information for all grids
+    int size = 0;
+    int offset = 0;
+
+    for (int i=0; i<numGrids; i++)
+        size += dirichletValues[i].size();
+
+    BitSetVector<dim> totalDirichletNodes(size);
+
+    for (int i=0; i<numGrids; i++) {
+        for (size_t j=0; j<dirichletValues[i].size(); j++)
+            totalDirichletNodes[offset + j] = dirichletNodes[i][j];
+        offset += dirichletValues[i].size();
+    }
+
+    // ///////////////////////////////////
+    //   Create contact assembler
+    // ///////////////////////////////////
+
+     // Set mortar couplings.  Currently not more than one for each grid
+    BoundaryPatch<DeformedGridType::LevelGridView> nonmortarPatch;
+    const ParameterTree& couplingParameters = problemConfiguration.sub(makeName("coupling",0));
+
+    // the involved grids
+    string nonMortarGrid = couplingParameters.get<string>("nonmortarGrid");
+
+    // read field describing the nonmortar boundary
+    nonmortarPatch.setup(deformedGrids[gridName[0]]->levelView(0),true);
+    readBoundaryPatch<DeformedGridType>(nonmortarPatch, path + couplingParameters.get<string>("nonmortarPatch"));
+
+    OneBodyAssembler<DeformedGridType,VectorType> contactAssembler(*deformedGrids[gridName[0]], obs, nonmortarPatch, couplingParameters.get<double>("couplingDistance"));
+
+
+    std::vector<BitSetVector<1> > allHasObs(toplevel+1);
+    allHasObs.back().resize(size,true);
+
+    for (size_t i=0; i<totalDirichletNodes.size(); i++)
+        if (totalDirichletNodes[i][0])
+            allHasObs.back()[i].flip();
+
+    for (size_t i=0; i<grids[gridName[0]]->maxLevel()+1; i++)
+        allHasObs[i].resize(grids[gridName[0]]->size(i,dim),true);
+
+    // ////////////////////////////////////////////////////
+    //   Create a multigrid solver and trust region solver
+    // ////////////////////////////////////////////////////
+
+    EnergyNorm<MatrixType, VectorType> elastNorm;
+
+    // First create a base solver
+#ifndef HAVE_IPOPT
+#error "You need IpOpt!"
+#endif
+    /*
+    TrustRegionGSStep<MatrixType, VectorType> baseSolverStep;
+
+    ::LoopSolver<VectorType> baseSolver(&baseSolverStep,
+            baseIterations,
+            baseTolerance,
+            &elastNorm,
+            Solver::REDUCED);
+    */
+
+
+    QuadraticIPOptSolver<MatrixType,VectorType> baseSolver;
+    baseSolver.verbosity_ = Solver::QUIET;
+    baseSolver.tolerance_ = baseTolerance;
+
+
+
+    // Make pre and postsmoothers
+    TrustRegionGSStep<MatrixType, VectorType> presmoother, postsmoother;
+
+    MonotoneMGStep<MatrixType, VectorType> multigridStep;
+
+    multigridStep.setMGType(mu, nu1, nu2);
+    multigridStep.basesolver_        = &baseSolver;
+    multigridStep.setSmoother(&presmoother, &postsmoother);
+    multigridStep.obstacleRestrictor_ = new ContactObsRestriction<VectorType>;
+    multigridStep.hasObstacle_ = &allHasObs;
+
+    multigridStep.ignoreNodes_       = &totalDirichletNodes;
+
+    // transfer operator need to be set every Newton iteration
+    std::vector<ContactMGTransfer<VectorType>* > mgTransfers(toplevel);
+    for (size_t i=0; i<mgTransfers.size(); i++)
+        mgTransfers[i] = new ContactMGTransfer<VectorType>;
+
+    multigridStep.setTransferOperators(mgTransfers);
+
+    EnergyNorm<MatrixType, VectorType  > energyNorm(multigridStep);
+
+    ::LoopSolver<VectorType> solver(&multigridStep,
+            multigridIterations,
+            mgTolerance,
+            (useElasticityNorm) ? &elastNorm : &energyNorm,
+            Solver::FULL);
+
+    // Create the materials
+    typedef P1NodalBasis<GridType::LeafGridView> P1Basis;
+    std::vector<P1Basis*> coarseP1Bases(numGrids);
+    for (int j=0; j<numGrids; j++)
+        coarseP1Bases[j] = new P1Basis(grids[gridName[j]]->leafView());
+
+    typedef NeoHookeMaterial<P1Basis> MaterialType;
+    //typedef GeomExactStVenantMaterial<P1Basis> MaterialType;
+    std::vector<MaterialType> materials(numGrids);
+    for (int i=0; i<numGrids;i++)
+        materials[i].setup(E[gridName[i]],Nu[gridName[i]],*coarseP1Bases[i]);
+
+    // Make static contact problem
+    typedef OneBodyStaticContactProblem<VectorType,MatrixType, MaterialType> ContactProblem;
+    ContactProblem contactProblem(contactAssembler, materials, extForces);
+
+    // Create trust-region step
+    TrustRegionStep<ContactProblem> trustRegionStep(contactProblem, solver, trustRegionRadius, maxTRRadius);
+
+    // ///////////////////////////////////////////////////
+    //   Do a homotopy of the Dirichlet boundary data
+    // ///////////////////////////////////////////////////
+
+    // //////////////////////////////////////////////////////////
+    //   Assemble linear elasticity matrix for the energy norm
+    //   used by the MMG termination criterion
+    // //////////////////////////////////////////////////////////
+
+    std::vector<MatrixType*> elast(numGrids);
+    MatrixType bigElastMatrix;
+
+    if (useElasticityNorm) {
+        for (int i=0; i<numGrids; i++) {
+
+            OperatorAssembler<P1Basis,P1Basis> globalAssembler(*coarseP1Bases[i],*coarseP1Bases[i]);
+
+            StVenantKirchhoffAssembler<GridType, P1Basis::LocalFiniteElement, P1Basis::LocalFiniteElement> localAssembler(E[gridName[i]],Nu[gridName[i]]);
+
+            elast[i] = new MatrixType;
+            globalAssembler.assemble(localAssembler, *elast[i]);
+        }
+
+
+        MatrixIndexSet matInd(size,size);
+        size_t matOffSet = 0;
+        for (int i=0; i<numGrids; i++) {
+
+            for (size_t iRow = 0; iRow<elast[i]->N(); iRow++) {
+
+                const MatrixType::row_type& row = (*elast[i])[iRow];
+
+                // Loop over all columns of the stiffness matrix
+                MatrixType::row_type::const_iterator j   = row.begin();
+                MatrixType::row_type::const_iterator jEnd = row.end();
+
+                for (; j!=jEnd; ++j)
+                    matInd.add(iRow+matOffSet, matOffSet+j.index());
+            }
+
+            matOffSet += u[i].size();
+        }
+
+        matInd.exportIdx(bigElastMatrix);
+        bigElastMatrix = 0;
+        matOffSet = 0;
+
+        for (int i=0; i<numGrids; i++) {
+
+            for (size_t iRow = 0; iRow<elast[i]->N(); iRow++) {
+
+                const MatrixType::row_type& row = (*elast[i])[iRow];
+
+                // Loop over all columns of the stiffness matrix
+                MatrixType::row_type::const_iterator j   = row.begin();
+                MatrixType::row_type::const_iterator jEnd = row.end();
+
+                for (; j!=jEnd; ++j)
+                    bigElastMatrix[iRow+matOffSet][matOffSet+j.index()] = *j;
+            }
+
+            matOffSet += u[i].size();
+        }
+
+        elastNorm.setMatrix(&bigElastMatrix);
+    }
+
+
+    double loadFactor    = 0;
+    double loadIncrement = problemConfiguration.get<double>("loadIncrement");
+
+    int counter  =0;
+
+    if (problemConfiguration.get<bool>("restart")) {
+        counter = problemConfiguration.get<int>("loadingStep") +1;
+        loadFactor = problemConfiguration.get<double>("loadFactor");
+        loadIncrement = problemConfiguration.get<double>("loadIncrement");
+    }
+
+    double avMgIt = 0;  double infeasibility = 1;
+    double nonlinInfeasibility = 1;
+    do {
+        /*
+        if (loadFactor < 1) {
+
+            // ////////////////////////////////////////////////////
+            //   Compute new feasible load increment
+            // ////////////////////////////////////////////////////
+
+            std::vector<VectorType> uSave=u;
+            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 (int j=0; j<numGrids; j++)
+                    for (int k=0; k<u[j].size(); k++)
+                        for (int l=0; l<dim; l++)
+                            if (dirichletNodes[j][k][l])
+                                uSave[j][k][l] = dirichletValues[j][k][l] * (loadFactor + loadIncrement);
+
+                isNan = false;
+                for (int i=0; i<numGrids; i++) {
+                    double eng = materials[i].energy(uSave[i]);
+                    std::cout<<"energy "<<eng<<std::endl;
+                   isNan |= 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;
+
+        } */
+        loadFactor += loadIncrement;
+
+            std::vector<VectorType> uSave=u;
+                // Set new Dirichlet values in solution
+                for (int j=0; j<numGrids; j++)
+                    for (int k=0; k<u[j].size(); k++)
+                        for (int l=0; l<dim; l++)
+                            if (dirichletNodes[j][k][l])
+                                uSave[j][k][l] = dirichletValues[j][k][l] * (loadFactor);
+
+                for (int i=0; i<numGrids; i++) {
+                    double eng = materials[i].energy(uSave[i]);
+                    std::cout<<"energy "<<eng<<std::endl;
+                }
+            std::cout << "####################################################" << std::endl;
+            std::cout << "New load factor: " << loadFactor
+                << "    new load increment: " << loadIncrement << std::endl;
+            std::cout << "####################################################" << std::endl;
+
+
+
+                // Set new Dirichlet values in solution
+                for (int j=0; j<numGrids; j++)
+                    for (int k=0; k<u[j].size(); k++)
+                        for (int l=0; l<dim; l++)
+                            if (dirichletNodes[j][k][l])
+                                //dirVals[j][k][l] = dirichletValues[j][k][l] * (loadFactor);
+                                dirVals[j][k][l] = dirichletValues[j][k][l] * (loadIncrement);
+
+        // /////////////////////////////////////////////////////
+        //   Solve coarse problem
+        // /////////////////////////////////////////////////////
+
+        for (int j=0; j<numGrids; j++)
+            for (int k=0; k<u[j].size(); k++)
+                    if (dirichletNodes[j][k][0]) {
+                        std::cout<<"Dir "<<dirVals[j][k]<<std::endl;
+                        break;
+                    }
+
+        std::ostringstream s;
+        int zer(0);
+        s << counter;
+
+        std::string itepath = resultPath + "mergedGrids";
+        int new_dir2 = mkdir(itepath.c_str(), 0744);
+        itepath += "/"+s.str()+"/";
+        //Create loging files for several entities
+        // new folder for results
+        new_dir2 = mkdir(itepath.c_str(), 0744);
+        if (new_dir2 != -1)
+            printf("Created new folder for results\n");
+        else
+            printf("Error while creating folder!\n");
+        // Newton iteration for linearized equation
+
+
+        // actual trust region iteration and error
+        int trIt = 0;
+        double error = trustRegionTol+1;
+        double relError = trustRegionTol+1;
+
+        LeafBoundaryPatch allBound(grids[gridName[0]]->leafView(),true);
+        std::vector<int> allGloToLo;
+        allBound.makeGlobalToLocal(allGloToLo);
+
+        while ((relError >= trustRegionTol) && trIt < trustRegionNumIt) {
+            ++trIt;
+
+            // Deform grids with actual displacement iterate
+            for (int i=0;i<numGrids;i++)
+                deformation[i]->setDeformation(u[i]);
+
+
+                // compute obstacles and setup the MMG solver
+                contactAssembler.setObstacles();
+                multigridStep.obstacles_      = &contactAssembler.obstacles_;
+
+                std::vector<int> gl;
+                nonmortarPatch.makeGlobalToLocal(gl);
+
+                std::cout<<"obstacles \n";
+                for (int i=0; i<u[0].size();i++)
+                    if (gl[i]>-1)
+                        std::cout<<contactAssembler.obstacles_.back()[i].lower(dim-1)<<std::endl;
+
+                for (size_t i=0; i<mgTransfers.size(); i++) {
+                    mgTransfers[i]->setup(*deformedGrids[gridName[0]], i, i+1,
+                                 contactAssembler.localCoordSystems_[i],
+                                 contactAssembler.localCoordSystems_[i+1]);
+                }
+
+                //transform iterate into mortar basis coordinates
+                VectorType totalIterate = u[0];
+                VectorType newTotalIterate = totalIterate;
+                contactAssembler.rotateVector(newTotalIterate);
+                // setup trust region problem
+                if (trIt==1)
+                    trustRegionStep.setProblem(newTotalIterate, contactProblem, dirVals, true);
+                else
+                    trustRegionStep.setProblem(newTotalIterate, contactProblem, extForces, false);
+
+                trustRegionStep.iterate();
+                avMgIt += solver.ite_;
+
+                // get new iterate
+                newTotalIterate = trustRegionStep.getSol();
+
+                // transform back into nodal coordinates
+                contactAssembler.rotateVector(newTotalIterate);
+                u[0] = newTotalIterate;
+
+                for (int i=0; i<numGrids; i++) {
+
+                std::string filme2 = genFilename(itepath, makeName("grid",i) + "iteration", trIt);
+
+                LeafAmiraMeshWriter<GridType> amiramesh;
+                amiramesh.addLeafGrid(*grids[gridName[i]],true);
+                amiramesh.addVertexData(u[i], grids[gridName[i]]->leafView());
+                amiramesh.write(filme2);
+                }
+
+
+                // get the correction
+                newTotalIterate -= totalIterate;
+                std::vector<VectorType> correction(numGrids);
+                correction[0] = newTotalIterate;
+
+                // compute error estimate
+                error = 0;
+                double error2 = 0;
+
+                for (int i=0;i<numGrids;i++) {
+                    if (useElasticityNorm)
+                        error += EnergyNorm<MatrixType,VectorType>::normSquared(correction[i], *elast[i]);
+                    else
+                        error += EnergyNorm<MatrixType,VectorType>::normSquared(correction[i], *contactProblem.stiffMat_[i]);
+                    if (useElasticityNorm)
+                        error2 += EnergyNorm<MatrixType,VectorType>::normSquared(u[i], *elast[i]);
+                    else
+                        error2 += EnergyNorm<MatrixType,VectorType>::normSquared(u[i], *contactProblem.stiffMat_[i]);
+                }
+
+                relError = error/error2;
+
+                std::cout << "In Trust Region iteration "<<trIt<<" , absolut norm of correction : "<<error<<
+                    " relative error "<<relError<<"\n";
+
+            }
+
+            avMgIt /= trIt;
+
+            // Output result
+            for (int i=0; i<numGrids; i++) {
+
+                std::string filename = genFilename(resultPath, makeName("grid",i) + "loading", counter);
+                LeafAmiraMeshWriter<GridType>::writeBlockVector(*grids[gridName[i]], u[i], filename,true);
+            }
+
+            counter++;
+
+    } while (loadFactor < 1);
+
+            std::cout<<"--------------------------------------------------- \n";
+            std::cout<<"|               Finished Loading phase              \n";
+            std::cout<<"--------------------------------------------------- \n";
+
+            std::cout<<"average multigrid iterations are "<<avMgIt<<std::endl;
+
+            // /////////////////////////////////////////////////////////////////////
+            //   Refinement Loop
+            // /////////////////////////////////////////////////////////////////////
+/*
+            for (int level=1; level<=maxLevel; level++) {
+
+                // ////////////////////////////////////////////////////////////////////////////
+                //    Refine locally and transfer the current solution to the new leaf level
+                // ////////////////////////////////////////////////////////////////////////////
+
+                //         GeometricEstimator<GridType> estimator;
+
+                //         estimator.estimate(grid[0], (toplevel<=minLevel) ? refineAll : refineCondition, x[0]);
+                //         estimator.estimate(grid[1], (toplevel<=minLevel) ? refineAll : refineCondition, x[1]);
+
+                HierarchicContactEstimator<GridType> estimator(grid[0], grid[1]);
+
+                estimator.couplings_[0].obsPatch_    = &untransfObsPatch;
+                estimator.couplings_[0].obsDistance_ = obsDistance;
+                estimator.couplings_[0].type_        = CouplingPairBase::CONTACT;
+
+                array<LeafBoundaryPatch, 2> leafDirichletBoundary;
+                for (int j=0; j<grid.size(); j++)
+                    BoundaryPatchProlongator<GridType>::prolong(coarseDirichletBoundary[j], leafDirichletBoundary[j]);
+
+                OgdenMaterialLocalStiffness<GridType, P1Basis::LocalFiniteElement, P1Basis::LocalFiniteElement> localOgdenStiffness(E, nu, d);
+
+                std::vector<RefinementIndicator<GridType>*> refinementIndicator(2);
+                refinementIndicator[0] = new RefinementIndicator<GridType>(grid[0]);
+                refinementIndicator[1] = new RefinementIndicator<GridType>(grid[1]);
+
+                estimator.estimate(x[0], x[1],
+                        &leafDirichletBoundary[0],
+                        &leafDirichletBoundary[1],
+                        refinementIndicator,
+                        &localOgdenStiffness, &localOgdenStiffness);
+
+                // ////////////////////////////////////////////////////
+                //   Refine grids
+                // ////////////////////////////////////////////////////
+
+                std::vector<GridType*> adaptiveGridVector(2);
+                adaptiveGridVector[0] = &grid[0];
+                adaptiveGridVector[1] = &grid[1];
+                FractionalMarkingStrategy<GridType>::mark(refinementIndicator, adaptiveGridVector, refinementFraction);
+
+                for (int i=0; i<2; i++) {
+
+                    P1Basis p1Basis(grid[i].leafView());
+                    GridFunctionAdaptor<P1Basis> adaptor(p1Basis,true,true);
+
+                    grid[i].preAdapt();
+                    grid[i].adapt();
+                    grid[i].postAdapt();
+
+                    p1Basis.update();
+                    adaptor.adapt(x[i]);
+
+                    deform[i]->updateDeformation(x[i],grid[i].maxLevel());
+                    defGrid[i]->update();
+
+                }
+
+                std::cout << "########################################################" << std::endl;
+                std::cout << "  Grids refined" << std::endl;
+                std::cout << "  Grid: 0   Level: " << grid[0].maxLevel()
+                    << "   vertices: " << grid[0].size(grid[0].maxLevel(), dim)
+                    << "   elements: " << grid[0].size(grid[0].maxLevel(), 0) << std::endl;
+                std::cout << "  Grid: 1   Level: " << grid[1].maxLevel()
+                    << "   vertices: " << grid[1].size(grid[1].maxLevel(), dim)
+                    << "   elements: " << grid[1].size(grid[1].maxLevel(), 0) << std::endl;
+                std::cout << "########################################################" << std::endl;
+
+                std::cout << "####################################################" << std::endl;
+                std::cout << "      Solving on level: " << toplevel << std::endl;
+                std::cout << "####################################################" << std::endl;
+
+                // does this keep the level 0 entries?
+                dirichletBoundary[0].resize(toplevel+1);
+                dirichletBoundary[1].resize(toplevel+1);
+                dirichletBoundary[0][0] = coarseDirichletBoundary[0];
+                dirichletBoundary[1][0] = coarseDirichletBoundary[1];
+
+
+                dirichletNodes[0].resize(toplevel+1);
+                dirichletNodes[1].resize(toplevel+1);
+
+                BoundaryPatchProlongator<GridType>::prolong(dirichletBoundary[0]);
+                BoundaryPatchProlongator<GridType>::prolong(dirichletBoundary[1]);
+
+                for (int i=0; i<=toplevel; i++) {
+
+                    int fSSize0 = grid[0].size(i,dim);
+                    dirichletNodes[0][i].resize(fSSize0*dim);
+                    for (int j=0; j<fSSize0; j++)
+                        for (int k=0; k<dim; k++)
+                            dirichletNodes[0][i][j*dim+k] = dirichletBoundary[0][i].containsVertex(j);
+
+                    int fSSize1 = grid[1].size(i,dim);
+                    dirichletNodes[1][i].resize(fSSize1 * dim);
+                    for (int j=0; j<fSSize1; j++)
+                        for (int k=0; k<dim; k++)
+                            dirichletNodes[1][i][j*dim+k] = dirichletBoundary[1][i].containsVertex(j);
+
+                }
+
+                dirichletValues[0].resize(toplevel+1);
+                dirichletValues[1].resize(toplevel+1);
+                dirichletValues[0][0] = coarseDirichletValues[0];
+                dirichletValues[1][0] = coarseDirichletValues[1];
+
+                sampleOnBitField(grid[0], dirichletValues[0], dirichletNodes[0]);
+                sampleOnBitField(grid[1], dirichletValues[1], dirichletNodes[1]);
+
+                // ///////////////////////////////////////////////
+                //   Create new rhs vectors
+                // ///////////////////////////////////////////////
+
+                rhs[0].resize(grid[0].size(toplevel,dim));
+                rhs[1].resize(grid[1].size(toplevel,dim));
+
+                // Set right hand side vectors
+                for (int i=0; i<2; i++) {
+
+                    rhs[i] = 0;
+
+                    for (int j=0; j<rhs[i].size(); j++)
+                        for (int k=0; k<dim; k++) {
+                            if (dirichletNodes[i][toplevel][j][k])
+                                x[i][j][k] = dirichletValues[i][toplevel][j][k];
+
+                        }
+
+                }
+
+                // /////////////////////////////////////////////////////////////////////////////
+                //   Make dirichlet bitfields containing dirichlet information for both grids
+                // /////////////////////////////////////////////////////////////////////////////
+                totalDirichletNodes.resize(toplevel+1);
+
+                for (int i=0; i<=toplevel; i++) {
+
+                    int offset = dirichletValues[0][i].size();
+
+                    totalDirichletNodes[i].resize(dirichletNodes[0][i].size() + dirichletNodes[1][i].size());
+
+                    for (int j=0; j<dirichletNodes[0][i].size(); j++)
+                        totalDirichletNodes[i][j] = dirichletNodes[0][i][j];
+
+                    for (int j=0; j<dirichletNodes[1][i].size(); j++)
+                        totalDirichletNodes[i][offset + j]  = dirichletNodes[1][i][j];
+
+
+                }
+
+                trustRegionObstacles.resize(toplevel+1);
+                for (int i=0; i<=toplevel; i++)
+                    trustRegionObstacles[i].resize(grid[0].size(i, dim) + grid[1].size(i, dim));
+
+
+                // /////////////////////////////////////////////////////
+                //   Assemble the obstacle and the transfer operator
+                // /////////////////////////////////////////////////////
+
+                //update the deformed grids!
+                for (int j=0;j<2;j++)
+                    deform[j]->updateDeformation(x[j],grid[j].maxLevel());
+
+                contactAssembler.assembleObstacle();
+                contactAssembler.assembleTransferOperator();
+
+                // //////////////////////////////////////////////////////
+                //    Lengthen obstacle vector, to formally account for both
+                //    bodies, even though the second one doesn't actually have obstacles
+                // //////////////////////////////////////////////////////
+
+                hasObstacle.resize(toplevel+1);
+                for (int j=0; j<=toplevel; j++)
+                    hasObstacle[j].resize(grid[0].size(j, dim) + grid[1].size(j,dim), true);
+
+                // //////////////////////////////////////////////////////////////////////
+                //   The MG transfer operators involve the mortar coupling
+                //   coupling operator and have to be reassembled at each loading step
+                // //////////////////////////////////////////////////////////////////////
+                for (int k=0; k<multigridStep.mgTransfer_.size(); k++)
+                    delete(multigridStep.mgTransfer_[k]);
+
+                multigridStep.mgTransfer_.resize(toplevel);
+
+                for (int k=0; k<multigridStep.mgTransfer_.size(); k++) {
+
+                    ContactMGTransfer<VectorType>* newTransferOp = new ContactMGTransfer<VectorType>;
+                    newTransferOp->setup(grid[0], grid[1], k, k+1,
+                            contactAssembler.contactCoupling_.mortarLagrangeMatrix(k),
+                            contactAssembler.localCoordSystems_[k],
+                            contactAssembler.localCoordSystems_[k+1],
+                            *contactAssembler.nonmortarBoundary_[0][k].getVertices(),
+                            *contactAssembler.nonmortarBoundary_[0][k+1].getVertices());
+
+                    multigridStep.mgTransfer_[k] = newTransferOp;
+
+
+                }
+
+                // //////////////////////////////////////////////////////////
+                //   Assemble linear elasticity matrix for the energy norm
+                //   used by the MMG termination criterion
+                // //////////////////////////////////////////////////////////
+                // Assemble separate linear elasticity problems
+                P1Basis p1Basis0(grid[0].leafView());
+                P1Basis p1Basis1(grid[1].leafView());
+
+                OperatorAssembler<P1Basis,P1Basis> globalAssembler0(p1Basis0,p1Basis0);
+                OperatorAssembler<P1Basis,P1Basis> globalAssembler1(p1Basis1,p1Basis1);
+
+                StVenantKirchhoffAssembler<GridType, P1Basis::LocalFiniteElement, P1Basis::LocalFiniteElement> localAssembler(2.5e5, 0.3);
+
+                MatrixType stiffnessMatrix0, stiffnessMatrix1;
+                globalAssembler0.assemble(localAssembler, stiffnessMatrix0);
+                globalAssembler1.assemble(localAssembler, stiffnessMatrix1);
+
+                array<const MatrixType*, 2> submat;
+                submat[0] = &stiffnessMatrix0;
+                submat[1] = &stiffnessMatrix1;
+
+                MatrixType transformedLinearMatrix;
+                contactAssembler.assemble(submat, transformedLinearMatrix);
+
+                dynamic_cast<EnergyNorm<MatrixType,VectorType>*>(solver.errorNorm_)->setMatrix(&transformedLinearMatrix);
+
+                // /////////////////////////////////////////////////////
+                //   Trust-Region Solver
+                // /////////////////////////////////////////////////////
+
+                solveTrustRegionProblem<DefGridType, MatrixType, VectorType, P1Basis, P1Basis>(ogdenAssembler,
+                        contactAssembler,
+                        x, rhs, grid[0].maxLevel(),
+                        trustRegionRadius,
+                        trustRegionObstacles,
+                        totalDirichletNodes,
+                        solver,
+                        multigridStep,
+                        maxNewtonStepsII);
+
+
+                // ///////////////////////
+                //   Output result
+                // ///////////////////////
+                LeafAmiraMeshWriter<GridType> amiramesh0;
+                amiramesh0.addLeafGrid(grid[0],true);
+                amiramesh0.addVertexData(x[0], grid[0].leafView());
+                amiramesh0.write("0resultGrid");
+
+                LeafAmiraMeshWriter<GridType> amiramesh1;
+                amiramesh1.addLeafGrid(grid[1],true);
+                amiramesh1.addVertexData(x[1], grid[1].leafView());
+                amiramesh1.write("1resultGrid");
+
+            }
+    */
+} catch (Exception e) {
+
+    std::cout << e << std::endl;
+
+}
+
+
+
+
-- 
GitLab