From b7610622dabf3729e526529b6b5e336d54f62da3 Mon Sep 17 00:00:00 2001
From: Oliver Sander <sander@igpm.rwth-aachen.de>
Date: Wed, 14 Jun 2006 15:54:44 +0000
Subject: [PATCH] a 2-orthonormal-directors rod in 3d space

[[Imported from SVN: r839]]
---
 rod3d.cc | 383 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 383 insertions(+)
 create mode 100644 rod3d.cc

diff --git a/rod3d.cc b/rod3d.cc
new file mode 100644
index 00000000..85e51b62
--- /dev/null
+++ b/rod3d.cc
@@ -0,0 +1,383 @@
+#include <config.h>
+
+//#define DUNE_EXPRESSIONTEMPLATES
+#include <dune/grid/onedgrid.hh>
+
+#include <dune/istl/io.hh>
+
+#include <dune/common/bitfield.hh>
+#include "src/quaternion.hh"
+
+#include "src/rodassembler.hh"
+#include "../common/trustregiongsstep.hh"
+#include "../contact/src/contactmmgstep.hh"
+
+#include "../solver/iterativesolver.hh"
+
+#include "../common/geomestimator.hh"
+#include "../common/refinegrid.hh"
+#include "../common/energynorm.hh"
+
+#include <dune/common/configparser.hh>
+#include "src/configuration.hh"
+#include "src/rodwriter.hh"
+
+// Number of degrees of freedom: 
+// 7 (x, y, z, q_1, q_2, q_3, q_4) for a spatial rod
+const int blocksize = 6;
+
+using namespace Dune;
+using std::string;
+
+
+void setTrustRegionObstacles(double trustRegionRadius,
+                             SimpleVector<BoxConstraint<blocksize> >& trustRegionObstacles)
+{
+    for (int j=0; j<trustRegionObstacles.size(); j++) {
+
+        for (int k=0; k<blocksize; k++) {
+
+//             if (totalDirichletNodes[j*dim+k])
+//                 continue;
+
+            trustRegionObstacles[j].val[2*k]   = -trustRegionRadius;
+            trustRegionObstacles[j].val[2*k+1] =  trustRegionRadius;
+
+        }
+        
+    }
+
+    //std::cout << trustRegionObstacles << std::endl;
+//     exit(0);
+}
+
+
+int main (int argc, char *argv[]) try
+{
+    // Some types that I need
+    typedef BCRSMatrix<FieldMatrix<double, blocksize, blocksize> > MatrixType;
+    typedef BlockVector<FieldVector<double, blocksize> >           CorrectionType;
+    typedef std::vector<Configuration>                              SolutionType;
+
+    // parse data file
+    ConfigParser parameterSet;
+    parameterSet.parseFile("rod3d.parset");
+
+    // read solver settings
+    const int minLevel         = parameterSet.get("minLevel", int(0));
+    const int maxLevel         = parameterSet.get("maxLevel", int(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 grid
+    // ///////////////////////////////////////
+    typedef OneDGrid<1,1> GridType;
+    GridType grid(numRodBaseElements, 0, 1);
+
+    grid.globalRefine(minLevel);
+
+    Array<SimpleVector<BoxConstraint<blocksize> > > trustRegionObstacles(1);
+    Array<BitField> hasObstacle(1);
+    Array<BitField> dirichletNodes(1);
+
+    // ////////////////////////////////
+    //   Create a multigrid solver
+    // ////////////////////////////////
+
+    // First create a gauss-seidel base solver
+    TrustRegionGSStep<MatrixType, CorrectionType> baseSolverStep;
+
+    EnergyNorm<MatrixType, CorrectionType> baseEnergyNorm(baseSolverStep);
+
+    IterativeSolver<MatrixType, CorrectionType> baseSolver;
+    baseSolver.iterationStep = &baseSolverStep;
+    baseSolver.numIt = baseIt;
+    baseSolver.verbosity_ = Solver::QUIET;
+    baseSolver.errorNorm_ = &baseEnergyNorm;
+    baseSolver.tolerance_ = baseTolerance;
+
+    // Make pre and postsmoothers
+    TrustRegionGSStep<MatrixType, CorrectionType> presmoother;
+    TrustRegionGSStep<MatrixType, CorrectionType> postsmoother;
+
+    ContactMMGStep<MatrixType, CorrectionType> contactMMGStep(1);
+
+    contactMMGStep.setMGType(mu, nu1, nu2);
+    contactMMGStep.dirichletNodes_    = &dirichletNodes;
+    contactMMGStep.basesolver_        = &baseSolver;
+    contactMMGStep.presmoother_       = &presmoother;
+    contactMMGStep.postsmoother_      = &postsmoother;    
+    contactMMGStep.hasObstacle_       = &hasObstacle;
+    contactMMGStep.obstacles_         = &trustRegionObstacles;
+    contactMMGStep.verbosity_         = Solver::FULL;
+
+
+
+    EnergyNorm<MatrixType, CorrectionType> energyNorm(contactMMGStep);
+
+    IterativeSolver<MatrixType, CorrectionType> solver;
+    solver.iterationStep = &contactMMGStep;
+    solver.numIt = numIt;
+    solver.verbosity_ = Solver::FULL;
+    solver.errorNorm_ = &energyNorm;
+    solver.tolerance_ = tolerance;
+
+    double trustRegionRadius = 1;
+
+    SolutionType x(grid.size(grid.maxLevel(),1));
+
+    // //////////////////////////
+    //   Initial solution
+    // //////////////////////////
+
+    for (int i=0; i<x.size(); i++) {
+        x[i].r[0] = 0;    // x
+        x[i].r[1] = 0;                 // y
+        x[i].r[2] = double(i)/(x.size()-1);                 // z
+        //x[i].r[2] = i+5;
+        x[i].q = Quaternion<double>::identity();
+    }
+
+    x[x.size()-1].r[0] = 0;
+    x[x.size()-1].r[1] = 0.1;
+    x[x.size()-1].r[2] = 0;
+#if 0
+    x[x.size()-1].q[0] = 0;
+    x[x.size()-1].q[1] = 0;
+    x[x.size()-1].q[2] = 1/sqrt(2);
+    x[x.size()-1].q[3] = 1/sqrt(2);
+#endif
+
+    std::cout << "Left boundary orientation:" << std::endl;
+    std::cout << "director 0:  " << x[0].q.director(0) << std::endl;
+    std::cout << "director 1:  " << x[0].q.director(1) << std::endl;
+    std::cout << "director 2:  " << x[0].q.director(2) << std::endl;
+    std::cout << std::endl;
+    std::cout << "Right boundary orientation:" << std::endl;
+    std::cout << "director 0:  " << x[x.size()-1].q.director(0) << std::endl;
+    std::cout << "director 1:  " << x[x.size()-1].q.director(1) << std::endl;
+    std::cout << "director 2:  " << x[x.size()-1].q.director(2) << std::endl;
+//     exit(0);
+
+    //x[0].r[2] = -1;
+
+    // /////////////////////////////////////////////////////////////////////
+    //   Refinement Loop
+    // /////////////////////////////////////////////////////////////////////
+    
+    for (int toplevel=minLevel; toplevel<=maxLevel; toplevel++) {
+        
+        std::cout << "####################################################" << std::endl;
+        std::cout << "      Solving on level: " << toplevel << std::endl;
+        std::cout << "####################################################" << std::endl;
+    
+        dirichletNodes.resize(toplevel+1);
+        for (int i=0; i<=toplevel; i++) {
+            
+            dirichletNodes[i].resize( blocksize * grid.size(i,1), false );
+            
+            for (int j=0; j<blocksize; j++) {
+                dirichletNodes[i][j] = true;
+                dirichletNodes[i][dirichletNodes[i].size()-1-j] = true;
+            }
+        }
+        
+        // ////////////////////////////////////////////////////////////
+        //    Create solution and rhs vectors
+        // ////////////////////////////////////////////////////////////
+
+
+        MatrixType hessianMatrix;
+        RodAssembler<GridType> rodAssembler(grid);
+        rodAssembler.setShapeAndMaterial(0.01, 0.0001, 0.0001, 2.5e5, 0.3);
+
+        std::cout << "Energy: " << rodAssembler.computeEnergy(x) << std::endl;
+
+        MatrixIndexSet indices(grid.size(toplevel,1), grid.size(toplevel,1));
+        rodAssembler.getNeighborsPerVertex(indices);
+        indices.exportIdx(hessianMatrix);
+
+        CorrectionType rhs, corr;
+        rhs.resize(grid.size(toplevel,1));
+        corr.resize(grid.size(toplevel,1));
+    
+
+        // //////////////////////////////////////////////////////////
+        //   Create obstacles
+        // //////////////////////////////////////////////////////////
+        
+        hasObstacle.resize(toplevel+1);
+        for (int i=0; i<hasObstacle.size(); i++) {
+            hasObstacle[i].resize(grid.size(i, 1));
+            hasObstacle[i].setAll();
+        }
+        
+        trustRegionObstacles.resize(toplevel+1);
+        
+        for (int i=0; i<toplevel+1; i++) {
+            trustRegionObstacles[i].resize(grid.size(i,1));
+        }
+        
+        trustRegionObstacles.resize(toplevel+1);
+        for (int i=0; i<=toplevel; i++)
+            trustRegionObstacles[i].resize(grid.size(i, 1));
+
+        // ////////////////////////////////////
+        //   Create the transfer operators
+        // ////////////////////////////////////
+        for (int k=0; k<contactMMGStep.mgTransfer_.size(); k++)
+            delete(contactMMGStep.mgTransfer_[k]);
+
+        contactMMGStep.mgTransfer_.resize(toplevel);
+
+        for (int i=0; i<contactMMGStep.mgTransfer_.size(); i++){
+            TruncatedMGTransfer<CorrectionType>* newTransferOp = new TruncatedMGTransfer<CorrectionType>;
+            newTransferOp->setup(grid,i,i+1);
+            contactMMGStep.mgTransfer_[i] = newTransferOp;
+        }
+
+        // /////////////////////////////////////////////////////
+        //   Trust-Region Solver
+        // /////////////////////////////////////////////////////
+        for (int i=0; i<maxNewtonSteps; i++) {
+
+            std::cout << "----------------------------------------------------" << std::endl;
+            std::cout << "      Trust-Region Step Number: " << i << std::endl;
+            std::cout << "----------------------------------------------------" << std::endl;
+
+            std::cout << "### Trust-Region Radius: " << trustRegionRadius << " ###" << std::endl;
+
+            rhs = 0;
+            corr = 0;
+            
+            rodAssembler.assembleGradient(x, rhs);
+            rodAssembler.assembleMatrix(x, hessianMatrix);
+            
+            rhs *= -1;
+
+            // Create trust-region obstacle on maxlevel
+            setTrustRegionObstacles(trustRegionRadius,
+                                    trustRegionObstacles[toplevel]);
+
+            dynamic_cast<MultigridStep<MatrixType,CorrectionType>*>(solver.iterationStep)->setProblem(hessianMatrix, corr, rhs, toplevel+1);
+
+            solver.preprocess();
+
+            contactMMGStep.preprocess();
+
+
+            // /////////////////////////////
+            //    Solve !
+            // /////////////////////////////
+             solver.solve();
+
+             corr = contactMMGStep.getSol();
+
+             //std::cout << "Correction: " << std::endl << corr << std::endl;
+
+             printf("infinity norm of the correction: %g\n", corr.infinity_norm());
+             if (corr.infinity_norm() < 1e-5) {
+                 std::cout << "CORRECTION IS SMALL ENOUGH" << std::endl;
+                 break;
+             }
+
+             // ////////////////////////////////////////////////////
+             //   Check whether trust-region step can be accepted
+             // ////////////////////////////////////////////////////
+             
+             SolutionType newIterate = x;
+             for (int j=0; j<newIterate.size(); j++) {
+
+                 // Add translational correction
+                 for (int k=0; k<3; k++)
+                     newIterate[j].r[k] += corr[j][k];
+
+                 // Add rotational correction
+                 Quaternion<double> qCorr = Quaternion<double>::exp(corr[j][3], corr[j][4], corr[j][5]);
+                 newIterate[j].q = newIterate[j].q.mult(qCorr);
+
+             }
+
+#if 0
+             std::cout << "newIterate: \n";
+             for (int j=0; j<newIterate.size(); j++)
+                 printf("%d:  (%g %g %g)  (%g %g %g %g)\n", j,
+                        newIterate[j].r[0],newIterate[j].r[1],newIterate[j].r[2],
+                        newIterate[j].q[0],newIterate[j].q[1],newIterate[j].q[2],newIterate[j].q[3]);
+#endif     
+            
+             /** \todo Don't always recompute oldEnergy */
+             double oldEnergy = rodAssembler.computeEnergy(x); 
+             double energy    = rodAssembler.computeEnergy(newIterate); 
+
+             // compute the model decrease
+             // It is $ m(x) - m(x+s) = -<g,s> - 0.5 <s, Hs>
+             // Note that rhs = -g
+             CorrectionType tmp(corr.size());
+             tmp = 0;
+             hessianMatrix.mmv(corr, tmp);
+             double modelDecrease = (rhs*corr) - 0.5 * (corr*tmp);
+             
+             std::cout << "Model decrease: " << modelDecrease 
+                       << ",  functional decrease: " << oldEnergy - energy << std::endl;
+
+             assert(modelDecrease >= 0);
+
+             if (energy >= oldEnergy) {
+                 printf("Richtung ist keine Abstiegsrichtung!\n");
+//                  std::cout << "corr[0]\n" << corr[0] << std::endl;
+                 //exit(0);
+             }
+              
+             // //////////////////////////////////////////////
+             //   Check for acceptance of the step
+             // //////////////////////////////////////////////
+             if ( (oldEnergy-energy) / modelDecrease > 0.9) {
+                 // very successful iteration
+
+                  x = newIterate;
+                  trustRegionRadius *= 2;
+
+             } else if ( (oldEnergy-energy) / modelDecrease > 0.01) {
+                 // successful iteration
+                  x = newIterate;
+
+             } else {
+                 // unsuccessful iteration
+                 trustRegionRadius /= 2;
+                 std::cout << "Unsuccessful iteration!" << std::endl;
+             }
+
+             //  Write current energy
+             std::cout << "--- Current energy: " << energy << " ---" << std::endl;
+        }
+        
+        // //////////////////////////////
+        //   Output result
+        // //////////////////////////////
+        writeRod(x, "rod3d.result");
+        BlockVector<FieldVector<double, 6> > strain(x.size()-1);
+        rodAssembler.getStrain(x,strain);
+        //std::cout << strain << std::endl;
+        //exit(0);
+
+        writeRod(x, strain, "rod3d.strain");
+
+    }
+
+
+ } catch (Exception e) {
+
+    std::cout << e << std::endl;
+
+ }
-- 
GitLab