"README.md" did not exist on "216dbb4f19e5100f1a35f462cc806c43783ac485"
Newer
Older
#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>
// 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) );
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.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;
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
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;
//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
//std::cout << "Correction: \n" << corr << std::endl;
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
// 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;
}