From aa00b09e301d0a3770333b23b9e0b1ccd2c6a70b Mon Sep 17 00:00:00 2001 From: Oliver Sander <sander@igpm.rwth-aachen.de> Date: Wed, 4 Sep 2013 16:08:06 +0000 Subject: [PATCH] Move the dirneucoupling program to dune-gfe-coupling [[Imported from SVN: r9466]] --- Makefile.am | 7 +- dirneucoupling.cc | 670 ---------------------------------------------- 2 files changed, 1 insertion(+), 676 deletions(-) delete mode 100644 dirneucoupling.cc diff --git a/Makefile.am b/Makefile.am index 0fcc60a0..7173245a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -11,7 +11,7 @@ AM_CPPFLAGS += $(IPOPT_CPPFLAGS) ADOLC_LIBS = -ladolc -noinst_PROGRAMS = cosserat-continuum rodobstacle rod3d harmonicmaps harmonicmaps-eoc dirneucoupling rod-eoc +noinst_PROGRAMS = cosserat-continuum rodobstacle rod3d harmonicmaps harmonicmaps-eoc rod-eoc cosserat_continuum_SOURCES = cosserat-continuum.cc cosserat_continuum_CXXFLAGS = $(UG_CPPFLAGS) $(AMIRAMESH_CPPFLAGS) $(IPOPT_CPPFLAGS) $(PSURFACE_CPPFLAGS) @@ -33,11 +33,6 @@ harmonicmaps_eoc_CXXFLAGS = $(UG_CPPFLAGS) $(AMIRAMESH_CPPFLAGS) $(IPOPT_CPPFLAG harmonicmaps_eoc_LDADD = $(UG_LDFLAGS) $(AMIRAMESH_LDFLAGS) $(UG_LIBS) $(AMIRAMESH_LIBS) \ $(IPOPT_LDFLAGS) $(IPOPT_LIBS) $(PSURFACE_LDFLAGS) $(PSURFACE_LIBS) -dirneucoupling_SOURCES = dirneucoupling.cc -dirneucoupling_CXXFLAGS = $(UG_CPPFLAGS) $(AMIRAMESH_CPPFLAGS) $(IPOPT_CPPFLAGS) $(PSURFACE_CPPFLAGS) -dirneucoupling_LDADD = $(UG_LDFLAGS) $(AMIRAMESH_LDFLAGS) $(UG_LIBS) $(AMIRAMESH_LIBS) \ - $(IPOPT_LDFLAGS) $(IPOPT_LIBS) $(PSURFACE_LDFLAGS) $(PSURFACE_LIBS) - # don't follow the full GNU-standard # we need automake 1.5 AUTOMAKE_OPTIONS = foreign 1.5 diff --git a/dirneucoupling.cc b/dirneucoupling.cc deleted file mode 100644 index eed81994..00000000 --- a/dirneucoupling.cc +++ /dev/null @@ -1,670 +0,0 @@ -#include <config.h> - -#include <dune/grid/onedgrid.hh> -#include <dune/grid/uggrid.hh> - -#include <dune/istl/io.hh> -#include <dune/istl/solvers.hh> - -#include <dune/grid/io/file/amirameshreader.hh> -#include <dune/grid/io/file/amirameshwriter.hh> - -#include <dune/common/bitsetvector.hh> -#include <dune/common/parametertree.hh> -#include <dune/common/parametertreeparser.hh> - -#include <dune/solvers/iterationsteps/multigridstep.hh> -#include <dune/solvers/solvers/loopsolver.hh> -#include <dune/solvers/iterationsteps/projectedblockgsstep.hh> -#ifdef HAVE_IPOPT -#include <dune/solvers/solvers/quadraticipopt.hh> -#endif -#include <dune/fufem/readbitfield.hh> -#include <dune/solvers/norms/energynorm.hh> -#include <dune/fufem/boundarypatch.hh> -#include <dune/fufem/boundarypatchprolongator.hh> -#include <dune/fufem/sampleonbitfield.hh> -#include <dune/fufem/computestress.hh> - -#include <dune/fufem/functionspacebases/q1nodalbasis.hh> -#include <dune/fufem/assemblers/operatorassembler.hh> -#include <dune/fufem/assemblers/localassemblers/stvenantkirchhoffassembler.hh> - -#include <dune/gfe/quaternion.hh> -#include <dune/gfe/rodassembler.hh> -#include <dune/gfe/rigidbodymotion.hh> -#include <dune/gfe/averageinterface.hh> -#include <dune/gfe/riemanniantrsolver.hh> -#include <dune/gfe/geodesicdifference.hh> -#include <dune/gfe/rodwriter.hh> -#include <dune/gfe/rodfactory.hh> -#include <dune/gfe/coupling/rodcontinuumcomplex.hh> -#include <dune/gfe/coupling/rodcontinuumfixedpointstep.hh> -#include <dune/gfe/coupling/rodcontinuumsteklovpoincarestep.hh> - -// Space dimension -const int dim = 3; - -using namespace Dune; -using std::string; -using std::vector; - -// Some types that I need -//typedef BCRSMatrix<FieldMatrix<double, dim, dim> > OperatorType; -//typedef BlockVector<FieldVector<double, dim> > VectorType; -typedef vector<RigidBodyMotion<double,dim> > RodSolutionType; -typedef BlockVector<FieldVector<double, 6> > RodDifferenceType; - - -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("dirneucoupling.parset", parameterSet); - - // read solver settings - const int numLevels = parameterSet.get<int>("numLevels"); - string ddType = parameterSet.get<string>("ddType"); - string preconditioner = parameterSet.get<string>("preconditioner"); - const double ddTolerance = parameterSet.get<double>("ddTolerance"); - const int maxDDIterations = parameterSet.get<int>("maxDirichletNeumannSteps"); - const double damping = parameterSet.get<double>("damping"); - - - const double trTolerance = parameterSet.get<double>("trTolerance"); - const int maxTrustRegionSteps = parameterSet.get<int>("maxTrustRegionSteps"); - const int trVerbosity = parameterSet.get<int>("trVerbosity"); - const int multigridIterations = parameterSet.get<int>("numIt"); - 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 initialTrustRegionRadius = parameterSet.get<double>("initialTrustRegionRadius"); - string resultPath = parameterSet.get("resultPath", ""); - - // Problem settings - string path = parameterSet.get<string>("path"); - string objectName = parameterSet.get<string>("gridFile"); - string dirichletNodesFile = parameterSet.get<string>("dirichletNodes"); - string dirichletValuesFile = parameterSet.get<string>("dirichletValues"); - string interfaceNodesFile = parameterSet.get<string>("interfaceNodes"); - const int numRodBaseElements = parameterSet.get<int>("numRodBaseElements"); - - double E = parameterSet.get<double>("E"); - double nu = parameterSet.get<double>("nu"); - - // rod material parameters - double rodA = parameterSet.get<double>("rodA"); - double rodJ1 = parameterSet.get<double>("rodJ1"); - double rodJ2 = parameterSet.get<double>("rodJ2"); - double rodE = parameterSet.get<double>("rodE"); - double rodNu = parameterSet.get<double>("rodNu"); - - Dune::array<FieldVector<double,3>,2> rodRestEndPoint; - rodRestEndPoint[0] = parameterSet.get<FieldVector<double,3> >("rodRestEndPoint0"); - rodRestEndPoint[1] = parameterSet.get<FieldVector<double,3> >("rodRestEndPoint1"); - - ////////////////////////////////////////////////////////////////// - // Print the algorithm type so we have it in the log files - ////////////////////////////////////////////////////////////////// - - std::cout << "Algorithm: " << ddType << std::endl; - if (ddType=="RichardsonIteration") - std::cout << "Preconditioner: " << preconditioner << std::endl; - - // /////////////////////////////////////////////// - // Create the rod grid and continuum grid - // /////////////////////////////////////////////// - - typedef OneDGrid RodGridType; - typedef UGGrid<dim> GridType; - - typedef BoundaryPatch<GridType::LevelGridView> LevelBoundaryPatch; - typedef BoundaryPatch<GridType::LeafGridView> LeafBoundaryPatch; - - RodContinuumComplex<RodGridType,GridType> complex; - - complex.rods_["rod"].grid_ = shared_ptr<RodGridType> - (new RodGridType(numRodBaseElements, 0, (rodRestEndPoint[1]-rodRestEndPoint[0]).two_norm())); - - complex.continua_["continuum"].grid_ = shared_ptr<GridType>(AmiraMeshReader<GridType>::read(path + objectName)); - complex.continua_["continuum"].grid_->setRefinementType(GridType::COPY); - - - - // ////////////////////////////////////// - // Globally refine grids - // ////////////////////////////////////// - - complex.rods_["rod"].grid_->globalRefine(numLevels-1); - complex.continua_["continuum"].grid_->globalRefine(numLevels-1); - - RodSolutionType rodX(complex.rods_["rod"].grid_->size(1)); - - int toplevel = complex.rods_["rod"].grid_->maxLevel(); - - // ////////////////////////// - // Initial solution - // ////////////////////////// - - RodFactory<RodGridType::LeafGridView> rodFactory(complex.rods_["rod"].grid_->leafView()); - rodFactory.create(rodX, rodRestEndPoint[0], rodRestEndPoint[1]); - - // ///////////////////////////////////////// - // Determine rod Dirichlet values - // ///////////////////////////////////////// - rodFactory.create(complex.rods_["rod"].dirichletValues_, - RigidBodyMotion<double,3>(FieldVector<double,3>(0), Rotation<double,3>::identity())); - BitSetVector<1> rodDNodes(complex.rods_["rod"].dirichletValues_.size(), false); - - // we need at least one Dirichlet side - assert(parameterSet.hasKey("dirichletValue0") or parameterSet.hasKey("dirichletValue1")); - - if (parameterSet.hasKey("dirichletValue0")){ - - RigidBodyMotion<double,3> dirichletValue; - dirichletValue.r = parameterSet.get("dirichletValue0", rodRestEndPoint[0]); - FieldVector<double,3> axis = parameterSet.get("dirichletAxis0", FieldVector<double,3>(0)); - double angle = parameterSet.get("dirichletAngle0", double(0)); - dirichletValue.q = Rotation<double,3>(axis, M_PI*angle/180); - - rodX[0] = dirichletValue; - - complex.rods_["rod"].dirichletValues_[0] = dirichletValue; - - rodDNodes[0] = true; - - } - - if (parameterSet.hasKey("dirichletValue1")) { - - RigidBodyMotion<double,3> dirichletValue; - dirichletValue.r = parameterSet.get("dirichletValue1", rodRestEndPoint[1]); - FieldVector<double,3> axis = parameterSet.get("dirichletAxis1", FieldVector<double,3>(0)); - double angle = parameterSet.get("dirichletAngle1", double(0)); - dirichletValue.q = Rotation<double,3>(axis, M_PI*angle/180); - - rodX.back() = dirichletValue; - - complex.rods_["rod"].dirichletValues_.back() = dirichletValue; - - rodDNodes.back() = true; - - } - - complex.rods_["rod"].dirichletBoundary_.setup(complex.rods_["rod"].grid_->leafView(),rodDNodes); - - // Backup initial rod iterate for later reference - RodSolutionType initialIterateRod = rodX; - - // ///////////////////////////////////////////////////// - // Determine the continuum Dirichlet nodes - // ///////////////////////////////////////////////////// - VectorType coarseDirichletValues(complex.continua_["continuum"].grid_->size(0, dim)); - AmiraMeshReader<GridType>::readFunction(coarseDirichletValues, path + dirichletValuesFile); - - LevelBoundaryPatch coarseDirichletBoundary; - coarseDirichletBoundary.setup(complex.continua_["continuum"].grid_->levelView(0)); - readBoundaryPatch<GridType>(coarseDirichletBoundary, path + dirichletNodesFile); - - LeafBoundaryPatch dirichletBoundary(complex.continua_["continuum"].grid_->leafView()); - BoundaryPatchProlongator<GridType>::prolong(coarseDirichletBoundary, dirichletBoundary); - complex.continua_["continuum"].dirichletBoundary_ = dirichletBoundary; - - BitSetVector<dim> dirichletNodes( complex.continua_["continuum"].grid_->size(dim) ); - - for (int i=0; i<dirichletNodes.size(); i++) - dirichletNodes[i] = dirichletBoundary.containsVertex(i); - - sampleOnBitField(*complex.continua_["continuum"].grid_, - coarseDirichletValues, - complex.continua_["continuum"].dirichletValues_, - dirichletNodes); - - ///////////////////////////////////////////////////////////////////// - // Create the two interface boundary patches - ///////////////////////////////////////////////////////////////////// - - std::pair<std::string,std::string> interfaceName = std::make_pair("rod", "continuum"); - - // first for the rod - BitSetVector<1> rodCouplingBitfield(rodX.size(),false); - /** \todo Using that index 0 is always the left boundary for a uniformly refined OneDGrid */ - if (parameterSet.hasKey("dirichletValue1")) { - rodCouplingBitfield[0] = true; - } else - rodCouplingBitfield.back() = true; - - complex.couplings_[interfaceName].rodInterfaceBoundary_.setup(complex.rods_["rod"].grid_->leafView(), rodCouplingBitfield); - - // then for the continuum - LevelBoundaryPatch coarseInterfaceBoundary(complex.continua_["continuum"].grid_->levelView(0)); - readBoundaryPatch<GridType>(coarseInterfaceBoundary, path + interfaceNodesFile); - - BoundaryPatchProlongator<GridType>::prolong(coarseInterfaceBoundary, complex.couplings_[interfaceName].continuumInterfaceBoundary_); - - // ////////////////////////////////////////// - // Assemble 3d linear elasticity problem - // ////////////////////////////////////////// - - typedef P1NodalBasis<GridType::LeafGridView,double> FEBasis; - FEBasis basis(complex.continua_["continuum"].grid_->leafView()); - OperatorAssembler<FEBasis,FEBasis> assembler(basis, basis); - - StVenantKirchhoffAssembler<GridType, FEBasis::LocalFiniteElement, FEBasis::LocalFiniteElement> localAssembler(E, nu); - MatrixType stiffnessMatrix3d; - - assembler.assemble(localAssembler, stiffnessMatrix3d); - - // //////////////////////////////////////////////////////////// - // Create solution and rhs vectors - // //////////////////////////////////////////////////////////// - - VectorType x3d(complex.continua_["continuum"].grid_->size(toplevel,dim)); - VectorType rhs3d(complex.continua_["continuum"].grid_->size(toplevel,dim)); - - // No external forces - rhs3d = 0; - - // Set initial solution - const VectorType& dirichletValues = complex.continua_["continuum"].dirichletValues_; - x3d = 0; - for (int i=0; i<x3d.size(); i++) - for (int j=0; j<dim; j++) - if (dirichletNodes[i][j]) - x3d[i][j] = dirichletValues[i][j]; - - // /////////////////////////////////////////// - // Dirichlet nodes for the rod problem - // /////////////////////////////////////////// - - BitSetVector<6> rodDirichletNodes(complex.rods_["rod"].grid_->size(1)); - rodDirichletNodes.unsetAll(); - - rodDirichletNodes[0] = true; - rodDirichletNodes.back() = true; - - // /////////////////////////////////////////// - // Create a solver for the rod problem - // /////////////////////////////////////////// - - RodLocalStiffness<RodGridType::LeafGridView,double> rodLocalStiffness(complex.rods_["rod"].grid_->leafView(), - rodA, rodJ1, rodJ2, rodE, rodNu); - - RodAssembler<RodGridType::LeafGridView,3> rodAssembler(complex.rods_["rod"].grid_->leafView(), &rodLocalStiffness); - - RiemannianTrustRegionSolver<RodGridType,RigidBodyMotion<double,3> > rodSolver; - rodSolver.setup(*complex.rods_["rod"].grid_, - &rodAssembler, - rodX, - rodDirichletNodes, - trTolerance, - maxTrustRegionSteps, - initialTrustRegionRadius, - multigridIterations, - mgTolerance, - mu, nu1, nu2, - baseIterations, - baseTolerance, - false); - - switch (trVerbosity) { - case 0: - rodSolver.verbosity_ = Solver::QUIET; break; - case 1: - rodSolver.verbosity_ = Solver::REDUCED; break; - default: - rodSolver.verbosity_ = Solver::FULL; break; - } - - - // //////////////////////////////// - // Create a multigrid solver - // //////////////////////////////// - - // First create a gauss-seidel base solver -#ifdef HAVE_IPOPT - QuadraticIPOptSolver<MatrixType,VectorType> baseSolver; -#endif - baseSolver.verbosity_ = NumProc::QUIET; - baseSolver.tolerance_ = baseTolerance; - - // Make pre and postsmoothers - BlockGSStep<MatrixType, VectorType> presmoother, postsmoother; - - MultigridStep<MatrixType, VectorType> multigridStep(stiffnessMatrix3d, x3d, rhs3d, toplevel+1); - - multigridStep.setMGType(mu, nu1, nu2); - multigridStep.ignoreNodes_ = &dirichletNodes; - multigridStep.basesolver_ = &baseSolver; - multigridStep.setSmoother(&presmoother, &postsmoother); - multigridStep.verbosity_ = Solver::QUIET; - - - - EnergyNorm<MatrixType, VectorType> energyNorm(multigridStep); - - shared_ptr< ::LoopSolver<VectorType> > solver = shared_ptr< ::LoopSolver<VectorType> >( new ::LoopSolver<VectorType>(&multigridStep, - // IPOpt doesn't like to be started in the solution - (numLevels!=1) ? multigridIterations : 1, - mgTolerance, - &energyNorm, - Solver::QUIET) ); - - // //////////////////////////////////// - // Create the transfer operators - // //////////////////////////////////// - for (int k=0; k<multigridStep.mgTransfer_.size(); k++) - delete(multigridStep.mgTransfer_[k]); - - multigridStep.mgTransfer_.resize(toplevel); - - for (int i=0; i<multigridStep.mgTransfer_.size(); i++){ - CompressedMultigridTransfer<VectorType>* newTransferOp = new CompressedMultigridTransfer<VectorType>; - newTransferOp->setup(*complex.continua_["continuum"].grid_,i,i+1); - multigridStep.mgTransfer_[i] = newTransferOp; - } - - - // ///////////////////////////////////////////////////// - // Dirichlet-Neumann Solver - // ///////////////////////////////////////////////////// - - RigidBodyMotion<double,3> referenceInterface = (parameterSet.hasKey("dirichletValue1")) - ? rodX[0] - : rodX.back(); - - complex.couplings_[interfaceName].referenceInterface_ = referenceInterface; - - // Init interface value - std::map<std::pair<std::string,std::string>, RigidBodyMotion<double,3> > lambda; - lambda[interfaceName] = referenceInterface; - - ///////////////////////////////////////////////////////////////////////////7 - // make temporary directory for the intermediate iterates - ///////////////////////////////////////////////////////////////////////////7 - char tmpPathBuffer[1000]; - sprintf(tmpPathBuffer, "tmp.XXXXXX"); - char* tmpPathChar = mkdtemp(tmpPathBuffer); - assert(tmpPathChar); - - std::string tmpPath(tmpPathChar);//resultPath + "tmp/"; - tmpPath += "/"; - std::cout << "tmp directory is: " << tmpPath << std::endl; - - - // - double normOfOldCorrection = 1; - int dnStepsActuallyTaken = 0; - for (int i=0; i<maxDDIterations; i++) { - - std::cout << "----------------------------------------------------" << std::endl; - std::cout << " Domain-Decomposition- Step Number: " << i << std::endl; - std::cout << "----------------------------------------------------" << std::endl; - - // Backup of the current iterate for the error computation later on - std::map<std::pair<std::string,std::string>, RigidBodyMotion<double,3> > oldLambda = lambda; - - if (ddType=="FixedPointIteration") { - - RodContinuumFixedPointStep<RodGridType,GridType> rodContinuumFixedPointStep(complex, - damping, - &rodAssembler, - &rodSolver, - &stiffnessMatrix3d, - solver); - - rodContinuumFixedPointStep.rodSubdomainSolutions_["rod"] = rodX; - rodContinuumFixedPointStep.continuumSubdomainSolutions_["continuum"] = x3d; - - rodContinuumFixedPointStep.iterate(lambda); - - // get the subdomain solutions - rodX = rodContinuumFixedPointStep.rodSubdomainSolutions_["rod"]; - x3d = rodContinuumFixedPointStep.continuumSubdomainSolutions_["continuum"]; - - } else if (ddType=="RichardsonIteration") { - - Dune::array<double,2> alpha = parameterSet.get<array<double,2> >("NeumannNeumannDamping"); - - RodContinuumSteklovPoincareStep<RodGridType,GridType> rodContinuumSteklovPoincareStep(complex, - preconditioner, - alpha, - damping, - &rodAssembler, - &rodLocalStiffness, - &rodSolver, - &stiffnessMatrix3d, - solver, - &localAssembler); - - rodContinuumSteklovPoincareStep.iterate(lambda); - - // get the subdomain solutions - rodX = rodContinuumSteklovPoincareStep.rodSubdomainSolutions_["rod"]; - x3d = rodContinuumSteklovPoincareStep.continuumSubdomainSolutions_["continuum"]; - - } else - DUNE_THROW(NotImplemented, ddType << " is not a known domain decomposition algorithm"); - - std::cout << "Lambda: " << lambda[interfaceName] << std::endl; - - // //////////////////////////////////////////////////////////////////////// - // Write the two iterates to disk for later convergence rate measurement - // //////////////////////////////////////////////////////////////////////// - - // First the 3d body - std::stringstream iAsAscii; - iAsAscii << i; - - std::string iSolFilename = tmpPath + "intermediate3dSolution_" + iAsAscii.str(); - - LeafAmiraMeshWriter<GridType> amiraMeshWriter; - amiraMeshWriter.addVertexData(x3d, complex.continua_["continuum"].grid_->leafView()); - amiraMeshWriter.write(iSolFilename); - - // Then the rod - iSolFilename = tmpPath + "intermediateRodSolution_" + iAsAscii.str(); - - RodWriter::writeBinary(rodX, iSolFilename); - - // //////////////////////////////////////////// - // Compute error in the energy norm - // //////////////////////////////////////////// - - double lengthOfCorrection = RigidBodyMotion<double,3>::distance(oldLambda[interfaceName], lambda[interfaceName]); - - double convRate = lengthOfCorrection / normOfOldCorrection; - - normOfOldCorrection = lengthOfCorrection; - - // Output - std::cout << "DD iteration: " << i << ", " - << "interface correction: " << lengthOfCorrection << ", " - << "convrate " << convRate << "\n"; - - dnStepsActuallyTaken = i; - - if (lengthOfCorrection < ddTolerance) - break; - - } - - - - // ////////////////////////////////////////////////////////// - // Recompute and compare against exact solution - // ////////////////////////////////////////////////////////// - VectorType exactSol3d = x3d; - RodSolutionType exactSolRod = rodX; - - // ////////////////////////////////////////////////////////// - // Compute hessian of the rod functional at the exact solution - // for use of the energy norm it creates. - // ////////////////////////////////////////////////////////// - - BCRSMatrix<FieldMatrix<double, 6, 6> > hessianRod; - MatrixIndexSet indices(exactSolRod.size(), exactSolRod.size()); - rodAssembler.getNeighborsPerVertex(indices); - indices.exportIdx(hessianRod); - rodAssembler.assembleMatrix(exactSolRod, hessianRod); - - - double error = std::numeric_limits<double>::max(); - double oldError = 0; - - VectorType intermediateSol3d(x3d.size()); - RodSolutionType intermediateSolRod(rodX.size()); - - // Compute error of the initial 3d solution - - // This should really be exactSol-initialSol, but we're starting - // from zero anyways - oldError += EnergyNorm<MatrixType,VectorType>::normSquared(exactSol3d, stiffnessMatrix3d); - - // Error of the initial rod iterate - RodDifferenceType rodDifference = computeGeodesicDifference(initialIterateRod, exactSolRod); - oldError += EnergyNorm<BCRSMatrix<FieldMatrix<double,6,6> >,RodDifferenceType>::normSquared(rodDifference, hessianRod); - - oldError = std::sqrt(oldError); - - // Store the history of total conv rates so we can filter out numerical - // dirt in the end. - std::vector<double> totalConvRate(maxDDIterations+1); - totalConvRate[0] = 1; - - - double oldConvRate = 100; - bool firstTime = true; - std::stringstream levelAsAscii, dampingAsAscii; - levelAsAscii << numLevels; - dampingAsAscii << damping; - std::string filename = resultPath + "convrate_" + levelAsAscii.str() + "_" + dampingAsAscii.str(); - - int i; - for (i=0; i<dnStepsActuallyTaken; i++) { - - // ///////////////////////////////////////////////////// - // Read iteration from file - // ///////////////////////////////////////////////////// - - // Read 3d solution from file - std::stringstream iAsAscii; - iAsAscii << i; - std::string iSolFilename = tmpPath + "intermediate3dSolution_" + iAsAscii.str(); - - AmiraMeshReader<GridType>::readFunction(intermediateSol3d, iSolFilename); - - // Read rod solution from file - iSolFilename = tmpPath + "intermediateRodSolution_" + iAsAscii.str(); - - FILE* fpInt = fopen(iSolFilename.c_str(), "rb"); - if (!fpInt) - DUNE_THROW(IOError, "Couldn't open intermediate solution '" << iSolFilename << "'"); - for (int j=0; j<intermediateSolRod.size(); j++) { - fread(&intermediateSolRod[j].r, sizeof(double), dim, fpInt); - fread(&intermediateSolRod[j].q, sizeof(double), 4, fpInt); - } - - fclose(fpInt); - - - - // ///////////////////////////////////////////////////// - // Compute error - // ///////////////////////////////////////////////////// - - VectorType solBackup0 = intermediateSol3d; - solBackup0 -= exactSol3d; - - RodDifferenceType rodDifference = computeGeodesicDifference(exactSolRod, intermediateSolRod); - - error = std::sqrt(EnergyNorm<MatrixType,VectorType>::normSquared(solBackup0, stiffnessMatrix3d) - + - EnergyNorm<BCRSMatrix<FieldMatrix<double,6,6> >,RodDifferenceType>::normSquared(rodDifference, hessianRod)); - - - double convRate = error / oldError; - totalConvRate[i+1] = totalConvRate[i] * convRate; - - // Output - std::cout << "DD iteration: " << i << " error : " << error << ", " - << "convrate " << convRate - << " total conv rate " << std::pow(totalConvRate[i+1], 1/((double)i+1)) << std::endl; - - // Convergence rates tend to stay fairly constant after a few initial iterates. - // Only when we hit numerical dirt are they starting to wiggle around wildly. - // We use this to detect 'the' convergence rate as the last averaged rate before - // we hit the dirt. - if (convRate > oldConvRate + 0.15 && i > 5 && firstTime) { - - std::cout << "Damping: " << damping - << " convRate: " << std::pow(totalConvRate[i], 1/((double)i)) - << std::endl; - - std::ofstream convRateFile(filename.c_str()); - convRateFile << damping << " " - << std::pow(totalConvRate[i], 1/((double)i)) - << std::endl; - - firstTime = false; - } - - if (error < 1e-12) - break; - - oldError = error; - oldConvRate = convRate; - - } - - // Convergence without dirt: write the overall convergence rate now - if (firstTime) { - int backTrace = std::min(size_t(4),totalConvRate.size()); - std::cout << "Damping: " << damping - << " convRate: " << std::pow(totalConvRate[i+1-backTrace], 1/((double)i+1-backTrace)) - << std::endl; - - std::ofstream convRateFile(filename.c_str()); - convRateFile << damping << " " - << std::pow(totalConvRate[i+1-backTrace], 1/((double)i+1-backTrace)) - << std::endl; - } - - - // ////////////////////////////// - // Delete temporary memory - // ////////////////////////////// - std::string removeTmpCommand = "rm -rf " + tmpPath; - system(removeTmpCommand.c_str()); - - // ////////////////////////////// - // Output result - // ////////////////////////////// - LeafAmiraMeshWriter<GridType> amiraMeshWriter(*complex.continua_["continuum"].grid_); - amiraMeshWriter.addVertexData(x3d, complex.continua_["continuum"].grid_->leafView()); - - BlockVector<FieldVector<double,1> > stress; - Stress<GridType>::getStress(*complex.continua_["continuum"].grid_, x3d, stress, E, nu); - amiraMeshWriter.addCellData(stress, complex.continua_["continuum"].grid_->leafView()); - - amiraMeshWriter.write(resultPath + "grid.result"); - - - - writeRod(rodX, resultPath + "rod3d.result"); - - } catch (Exception e) { - - std::cout << e << std::endl; - - } -- GitLab