diff --git a/Makefile.am b/Makefile.am index ea8fba908986b09fb6ab846d92619a5f4ff5f383..1507982c6c504c60e2fa436d5e6c2afe238e4038 100644 --- a/Makefile.am +++ b/Makefile.am @@ -9,7 +9,7 @@ SUBDIRS = m4 src test LDADD = $(IPOPT_LDFLAGS) $(IPOPT_LIBS) AM_CPPFLAGS += $(IPOPT_CPPFLAGS) -noinst_PROGRAMS = rodobstacle rod3d harmonicmaps dirneucoupling rod-eoc +noinst_PROGRAMS = rodobstacle rod3d harmonicmaps harmonicmaps-eoc dirneucoupling rod-eoc rodobstacle_SOURCES = rodobstacle.cc rod3d_SOURCES = rod3d.cc @@ -21,6 +21,11 @@ harmonicmaps_CXXFLAGS = $(UG_CPPFLAGS) $(AMIRAMESH_CPPFLAGS) $(IPOPT_CPPFLAGS) $ harmonicmaps_LDADD = $(UG_LDFLAGS) $(AMIRAMESH_LDFLAGS) $(UG_LIBS) $(AMIRAMESH_LIBS) \ $(IPOPT_LDFLAGS) $(IPOPT_LIBS) $(PSURFACE_LDFLAGS) $(PSURFACE_LIBS) +harmonicmaps_eoc_SOURCES = harmonicmaps-eoc.cc +harmonicmaps_eoc_CXXFLAGS = $(UG_CPPFLAGS) $(AMIRAMESH_CPPFLAGS) $(IPOPT_CPPFLAGS) $(PSURFACE_CPPFLAGS) +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) \ diff --git a/harmonicmaps-eoc.cc b/harmonicmaps-eoc.cc new file mode 100644 index 0000000000000000000000000000000000000000..5d73e84ed5e0ad91f9316a33f203f92c1679df44 --- /dev/null +++ b/harmonicmaps-eoc.cc @@ -0,0 +1,253 @@ +#include <config.h> + +#include <dune/common/bitsetvector.hh> +#include <dune/common/configparser.hh> + +#include <dune/grid/uggrid.hh> +#include <dune/grid/onedgrid.hh> +#include <dune/grid/../../doc/grids/gridfactory/structuredgridfactory.hh> + +#include <dune/ag-common/functionspacebases/p1nodalbasis.hh> +#include <dune/ag-common/assemblers/operatorassembler.hh> +#include <dune/ag-common/assemblers/localassemblers/laplaceassembler.hh> +#include <dune/ag-common/assemblers/localassemblers/massassembler.hh> + +#include <dune/solvers/solvers/iterativesolver.hh> +#include <dune/solvers/norms/energynorm.hh> + +#include "src/unitvector.hh" +#include "src/harmonicenergystiffness.hh" +#include "src/geodesicfeassembler.hh" +#include "src/riemanniantrsolver.hh" +#include "src/rodrefine.hh" +#include "src/rodwriter.hh" + +// grid dimension +const int dim = 2; + +typedef UnitVector<3> TargetSpace; +typedef std::vector<TargetSpace> SolutionType; + +const int blocksize = TargetSpace::TangentVector::size; + +using namespace Dune; +using std::string; + +template <class GridType> +void solve (const shared_ptr<GridType>& grid, + SolutionType& x, + int numLevels, + ConfigParser& parameters) +{ + // read solver setting + const double innerTolerance = parameters.get<double>("innerTolerance"); + const double tolerance = parameters.get<double>("tolerance"); + const int maxTrustRegionSteps = parameters.get<int>("maxTrustRegionSteps"); + const double initialTrustRegionRadius = parameters.get<double>("initialTrustRegionRadius"); + const int multigridIterations = parameters.get<int>("numIt"); + + // ///////////////////////////////////////// + // Read Dirichlet values + // ///////////////////////////////////////// + + BitSetVector<1> allNodes(grid->size(dim)); + allNodes.setAll(); + LeafBoundaryPatch<GridType> dirichletBoundary(*grid, allNodes); + + BitSetVector<blocksize> dirichletNodes(grid->size(dim)); + for (int i=0; i<dirichletNodes.size(); i++) + dirichletNodes[i] = dirichletBoundary.containsVertex(i); + + // ////////////////////////// + // Initial solution + // ////////////////////////// + + x.resize(grid->size(dim)); + + FieldVector<double,3> yAxis(0); + yAxis[1] = 1; + + typename GridType::LeafGridView::template Codim<dim>::Iterator vIt = grid->template leafbegin<dim>(); + typename GridType::LeafGridView::template Codim<dim>::Iterator vEndIt = grid->template leafend<dim>(); + + for (; vIt!=vEndIt; ++vIt) { + int idx = grid->leafIndexSet().index(*vIt); + + FieldVector<double,3> v; + FieldVector<double,2> pos = vIt->geometry().corner(0); + FieldVector<double,3> axis; + axis[0] = pos[0]; axis[1] = pos[1]; axis[2] = 1; + Rotation<3,double> rotation(axis, pos.two_norm()*M_PI*1.5); + + if (dirichletNodes[idx][0]) { +// FieldMatrix<double,3,3> rMat; +// rotation.matrix(rMat); +// v = rMat[2]; + v[0] = std::sin(pos[0]*M_PI); + v[1] = 0; + v[2] = std::cos(pos[0]*M_PI); + } else { + v[0] = 1; + v[1] = 0; + v[2] = 0; + } + + x[idx] = v; + + } + + + // //////////////////////////////////////////////////////////// + // Create an assembler for the Harmonic Energy Functional + // //////////////////////////////////////////////////////////// + + HarmonicEnergyLocalStiffness<typename GridType::LeafGridView,TargetSpace> harmonicEnergyLocalStiffness; + + GeodesicFEAssembler<typename GridType::LeafGridView,TargetSpace> assembler(grid->leafView(), + &harmonicEnergyLocalStiffness); + + // /////////////////////////////////////////// + // Create a solver for the rod problem + // /////////////////////////////////////////// + + RiemannianTrustRegionSolver<GridType,TargetSpace> solver; + + solver.setup(*grid, + &assembler, + x, + dirichletNodes, + tolerance, + maxTrustRegionSteps, + initialTrustRegionRadius, + multigridIterations, + innerTolerance, + 1, 3, 3, + 100, // iterations of the base solver + 1e-8, // base tolerance + false); // instrumentation + + // ///////////////////////////////////////////////////// + // Solve! + // ///////////////////////////////////////////////////// + + solver.setInitialSolution(x); + solver.solve(); + + x = solver.getSol(); +} + +int main (int argc, char *argv[]) try +{ + // parse data file + ConfigParser parameterSet; + if (argc==2) + parameterSet.parseFile(argv[1]); + else + parameterSet.parseFile("harmonicmaps-eoc.parset"); + + // read solver settings + const int numLevels = parameterSet.get<int>("numLevels"); + const int baseIterations = parameterSet.get<int>("baseIt"); + const double baseTolerance = parameterSet.get<double>("baseTolerance"); + + const int numBaseElements = parameterSet.get<int>("numBaseElements"); + + // ///////////////////////////////////////// + // Read Dirichlet values + // ///////////////////////////////////////// + + + + + // /////////////////////////////////////////////////////////// + // First compute the 'exact' solution on a very fine grid + // /////////////////////////////////////////////////////////// + + typedef std::conditional<dim==1,OneDGrid,UGGrid<dim> >::type GridType; + + // Create the reference grid + + array<unsigned int,dim> elements; + elements.fill(4); + shared_ptr<GridType> referenceGrid = StructuredGridFactory<GridType>::createSimplexGrid(FieldVector<double,dim>(0), + FieldVector<double,dim>(1), + elements); + referenceGrid->globalRefine(numLevels-1); + + // Solve the rod Dirichlet problem + SolutionType referenceSolution; + solve(referenceGrid, referenceSolution, numLevels, parameterSet); + + + // ////////////////////////////////////////////////////////////////////// + // Compute mass matrix and laplace matrix to emulate L2 and H1 norms + // ////////////////////////////////////////////////////////////////////// +#if 0 + typedef P1NodalBasis<GridType::LeafGridView,double> FEBasis; + FEBasis basis(referenceGrid->leafView()); + OperatorAssembler<FEBasis,FEBasis> operatorAssembler(basis, basis); + + LaplaceAssembler<GridType, FEBasis::LocalFiniteElement, FEBasis::LocalFiniteElement> laplaceLocalAssembler; + MassAssembler<GridType, FEBasis::LocalFiniteElement, FEBasis::LocalFiniteElement> massMatrixLocalAssembler; + + typedef Dune::BCRSMatrix<Dune::FieldMatrix<double,1,1> > ScalarMatrixType; + ScalarMatrixType laplace, massMatrix; + + operatorAssembler.assemble(laplaceLocalAssembler, laplace); + operatorAssembler.assemble(massMatrixLocalAssembler, massMatrix); +#endif + // /////////////////////////////////////////////////////////// + // Compute on all coarser levels, and compare + // /////////////////////////////////////////////////////////// + + for (int i=1; i<=numLevels; i++) { + + array<unsigned int,dim> elements; + elements.fill(numBaseElements); + shared_ptr<GridType> grid = StructuredGridFactory<GridType>::createSimplexGrid(FieldVector<double,dim>(0), + FieldVector<double,dim>(1), + elements); + + grid->globalRefine(i-1); + + // compute again + SolutionType solution; + solve(grid, solution, i, parameterSet); + +#if 0 + // Prolong solution to the very finest grid + for (int j=i; j<numLevels; j++) + globalRodRefine(grid, solution); + + std::stringstream numberAsAscii; + numberAsAscii << i; + writeRod(solution, "rodGrid_" + numberAsAscii.str()); + + assert(referenceSolution.size() == solution.size()); +#endif +#if 0 + BlockVector<TargetSpace::TangentVector> difference = computeGeodesicDifference(solution,referenceSolution); + + H1SemiNorm< BlockVector<TargetSpace::TangentVector> > h1Norm(laplace); + H1SemiNorm< BlockVector<TargetSpace::TangentVector> > l2Norm(massMatrix); + + // Compute max-norm difference + std::cout << "Level: " << i-1 + << ", max-norm error: " << difference.infinity_norm() + << std::endl; + + std::cout << "Level: " << i-1 + << ", L2 error: " << l2Norm(difference) + << std::endl; + + std::cout << "Level: " << i-1 + << ", H1 error: " << h1Norm(difference) + << std::endl; +#endif + } + + } catch (Exception e) { + + std::cout << e << std::endl; + + } diff --git a/harmonicmaps-eoc.parset b/harmonicmaps-eoc.parset new file mode 100644 index 0000000000000000000000000000000000000000..ce10259d114217dc5b3c176b83f63099b8d008fe --- /dev/null +++ b/harmonicmaps-eoc.parset @@ -0,0 +1,31 @@ +# Number of grid levels +numLevels = 1 + +# Tolerance of the trust region solver +tolerance = 1e-12 + +# Max number of steps of the trust region solver +maxTrustRegionSteps = 200 + +# Initial trust-region radius +initialTrustRegionRadius = 1 + +# Number of multigrid iterations per trust-region step +numIt = 200 + +# Number of base solver iterations +baseIt = 100 + +# Tolerance of the inner solver +innerTolerance = 1e-5 + +# Tolerance of the base grid solver +baseTolerance = -1 + +############################ +# Problem specifications +############################ + +# Number of elements of the rod grid +numBaseElements = 4 +