diff --git a/Makefile.am b/Makefile.am index 91b69b52530cd434ed2b769f7a43b19934193d08..2c0fae94bdefff84c4c0869bf043b7d74e554558 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,11 +4,15 @@ LDADD = $(IPOPT_LDFLAGS) $(IPOPT_LIBS) AM_CPPFLAGS += $(IPOPT_CPPFLAGS) -noinst_PROGRAMS = staticrod staticrod2 rod3d dirneucoupling +noinst_PROGRAMS = staticrod staticrod2 rod3d harmonicmaps dirneucoupling staticrod_SOURCES = staticrod.cc staticrod2_SOURCES = staticrod2.cc rod3d_SOURCES = rod3d.cc +harmonicmaps_SOURCES = harmonicmaps.cc +harmonicmaps_CXXFLAGS = $(UG_CPPFLAGS) $(AMIRAMESH_CPPFLAGS) $(IPOPT_CPPFLAGS) $(PSURFACE_CPPFLAGS) +harmonicmaps_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) diff --git a/harmonicmaps.cc b/harmonicmaps.cc new file mode 100644 index 0000000000000000000000000000000000000000..06356b9b30ecc03182922bb95a9f1fe81b7b59d8 --- /dev/null +++ b/harmonicmaps.cc @@ -0,0 +1,215 @@ +#include <config.h> + +#include <dune/common/bitsetvector.hh> +#include <dune/common/configparser.hh> + +#include <dune/grid/uggrid.hh> +#include <dune/grid/io/file/amirameshreader.hh> + +#include <dune-solvers/solvers/iterativesolver.hh> +#include <dune-solvers/norms/energynorm.hh> + +#include "src/roddifference.hh" +#include "src/rodwriter.hh" +#include "src/rotation.hh" +#include "src/geodesicfeassembler.hh" +#include "src/rodsolver.hh" + +// grid dimension +const int dim = 3; + +// Image space of the geodesic fe functions +typedef Rotation<3,double> TargetSpace; + +// Tangent vector of the image space +const int blocksize = TargetSpace::TangentVector::size; + +using namespace Dune; + +int main (int argc, char *argv[]) try +{ + typedef std::vector<TargetSpace> SolutionType; + + // parse data file + ConfigParser parameterSet; + if (argc==2) + parameterSet.parseFile(argv[1]); + else + parameterSet.parseFile("harmonicmaps.parset"); + + // read solver settings + const int numLevels = parameterSet.get<int>("numLevels"); + const double tolerance = parameterSet.get<double>("tolerance"); + const int maxTrustRegionSteps = parameterSet.get<int>("maxTrustRegionSteps"); + const double initialTrustRegionRadius = parameterSet.get<double>("initialTrustRegionRadius"); + 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 bool instrumented = parameterSet.get<bool>("instrumented"); + std::string resultPath = parameterSet.get("resultPath", ""); + + // read problem settings + std::string path = parameterSet.get<std::string>("path"); + std::string gridFile = parameterSet.get<std::string>("gridFile"); + + // /////////////////////////////////////// + // Create the grid + // /////////////////////////////////////// + typedef UGGrid<dim> GridType; + GridType grid; + grid.setRefinementType(GridType::COPY); + AmiraMeshReader<GridType>::read(grid, path + gridFile); + + grid.globalRefine(numLevels-1); + + SolutionType x(grid.size(dim)); + + // ////////////////////////// + // Initial solution + // ////////////////////////// + + for (int i=0; i<x.size(); i++) { + x[i] = Rotation<3,double>::identity(); + } + + // backup for error measurement later + SolutionType initialIterate = x; + + // ///////////////////////////////////////// + // Read Dirichlet values + // ///////////////////////////////////////// + + BitSetVector<1> allNodes(grid.size(dim)); + allNodes.setAll(); + LeafBoundaryPatch<GridType> dirichletBoundary(grid, allNodes); + + BitSetVector<blocksize> dirichletNodes(grid.size(1)); + for (int i=0; i<dirichletNodes.size(); i++) + dirichletNodes[i] = dirichletBoundary.containsVertex(i); + + // //////////////////////////////////////////////////////////// + // Create an assembler for the Harmonic Energy Functional + // //////////////////////////////////////////////////////////// + GeodesicFEAssembler<GridType::LeafGridView,TargetSpace> assembler(grid.leafView()); + + // ///////////////////////////////////////////////// + // Create a Riemannian trust-region solver + // ///////////////////////////////////////////////// +#if 0 + RodSolver<GridType> rodSolver; + rodSolver.setup(grid, + &assembler, + x, + dirichletNodes, + tolerance, + maxTrustRegionSteps, + initialTrustRegionRadius, + multigridIterations, + mgTolerance, + mu, nu1, nu2, + baseIterations, + baseTolerance, + instrumented); + + // ///////////////////////////////////////////////////// + // Solve! + // ///////////////////////////////////////////////////// + + std::cout << "Energy: " << assembler.computeEnergy(x) << std::endl; + + rodSolver.setInitialSolution(x); + rodSolver.solve(); + + x = rodSolver.getSol(); +#endif + // ////////////////////////////// + // Output result + // ////////////////////////////// +#if 0 + writeRod(x, resultPath + "rod3d.result"); +#endif + +#if 0 + // ////////////////////////////////////////////////////////// + // Recompute and compare against exact solution + // ////////////////////////////////////////////////////////// + + SolutionType exactSolution = x; + + // ////////////////////////////////////////////////////////// + // Compute hessian of the rod functional at the exact solution + // for use of the energy norm it creates. + // ////////////////////////////////////////////////////////// + + BCRSMatrix<FieldMatrix<double, 6, 6> > hessian; + MatrixIndexSet indices(exactSolution.size(), exactSolution.size()); + rodAssembler.getNeighborsPerVertex(indices); + indices.exportIdx(hessian); + rodAssembler.assembleMatrixFD(exactSolution, hessian); + + + double error = std::numeric_limits<double>::max(); + + SolutionType intermediateSolution(x.size()); + + // Create statistics file + std::ofstream statisticsFile((resultPath + "trStatistics").c_str()); + + // Compute error of the initial iterate + typedef BlockVector<FieldVector<double,6> > RodDifferenceType; + RodDifferenceType rodDifference = computeRodDifference(exactSolution, initialIterate); + double oldError = std::sqrt(computeEnergyNormSquared(rodDifference, hessian)); + + int i; + for (i=0; i<maxTrustRegionSteps; i++) { + + // ///////////////////////////////////////////////////// + // Read iteration from file + // ///////////////////////////////////////////////////// + char iSolFilename[100]; + sprintf(iSolFilename, "tmp/intermediateSolution_%04d", i); + + FILE* fp = fopen(iSolFilename, "rb"); + if (!fp) + DUNE_THROW(IOError, "Couldn't open intermediate solution '" << iSolFilename << "'"); + for (int j=0; j<intermediateSolution.size(); j++) { + fread(&intermediateSolution[j].r, sizeof(double), 3, fp); + fread(&intermediateSolution[j].q, sizeof(double), 4, fp); + } + + fclose(fp); + + // ///////////////////////////////////////////////////// + // Compute error + // ///////////////////////////////////////////////////// + + rodDifference = computeRodDifference(exactSolution, intermediateSolution); + + error = std::sqrt(computeEnergyNormSquared(rodDifference, hessian)); + + + double convRate = error / oldError; + + // Output + std::cout << "Trust-region iteration: " << i << " error : " << error << ", " + << "convrate " << convRate << std::endl; + statisticsFile << i << " " << error << " " << convRate << std::endl; + + if (error < 1e-12) + break; + + oldError = error; + + } +#endif + + // ////////////////////////////// + } catch (Exception e) { + + std::cout << e << std::endl; + + }