diff --git a/Makefile.am b/Makefile.am index 38be5927cd5830f81805acdcdf10e9d20bf43b90..6b6997f8e66d0f5350188a010c70cd7d883b05ae 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,15 +4,20 @@ #LDADD = $(UG_LDFLAGS) $(AMIRAMESH_LDFLAGS) $(UG_LIBS) $(AMIRAMESH_LIBS) #AM_CPPFLAGS = $(UG_CPPFLAGS) $(AMIRAMESH_CPPFLAGS) -noinst_PROGRAMS = staticrod staticrod2 rod3d simplecoupling +noinst_PROGRAMS = staticrod staticrod2 rod3d simplecoupling dirneucoupling staticrod_SOURCES = staticrod.cc staticrod2_SOURCES = staticrod2.cc rod3d_SOURCES = rod3d.cc -simplecoupling_SOURCES = simplecoupling.cc + +simplecoupling_SOURCES = simplecoupling.cc simplecoupling_CXXFLAGS = $(UG_CPPFLAGS) $(AMIRAMESH_CPPFLAGS) $(MPI_CPPFLAGS) simplecoupling_LDADD = $(UG_LDFLAGS) $(AMIRAMESH_LDFLAGS) $(UG_LIBS) $(AMIRAMESH_LIBS) $(MPI_LDFLAGS) +dirneucoupling_SOURCES = dirneucoupling.cc +dirneucoupling_CXXFLAGS = $(UG_CPPFLAGS) $(AMIRAMESH_CPPFLAGS) $(MPI_CPPFLAGS) +dirneucoupling_LDADD = $(UG_LDFLAGS) $(AMIRAMESH_LDFLAGS) $(UG_LIBS) $(AMIRAMESH_LIBS) $(MPI_LDFLAGS) + # 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 new file mode 100644 index 0000000000000000000000000000000000000000..8cb84786f315ee772248fe66b1c6d40e060a14d9 --- /dev/null +++ b/dirneucoupling.cc @@ -0,0 +1,303 @@ +#include <config.h> + +//#define HAVE_IPOPT + +#include <dune/grid/onedgrid.hh> +#include <dune/grid/uggrid.hh> + +#include <dune/disc/elasticity/linearelasticityassembler.hh> +#include <dune/disc/operators/p1operator.hh> +#include <dune/istl/io.hh> +#include <dune/grid/io/file/amirameshreader.hh> +#include <dune/grid/io/file/amirameshwriter.hh> + + +#include <dune/common/bitfield.hh> +#include <dune/common/configparser.hh> + +#include "../contact/src/contactmmgstep.hh" +#include "../solver/iterativesolver.hh" +#include "../common/projectedblockgsstep.hh" +#include "../common/geomestimator.hh" +#include "../common/readbitfield.hh" +#include "../common/energynorm.hh" +#include "../common/boundarypatch.hh" +#include "../common/prolongboundarypatch.hh" + +#include "src/quaternion.hh" +//#include "src/rodassembler.hh" +#include "src/configuration.hh" +#include "src/averageinterface.hh" +#include "src/rodsolver.hh" +#include "src/rodwriter.hh" + +// Number of degrees of freedom of a correction for a rod configuration +// 6 (x, y, z, v_1, v_2, v_3) for a spatial rod +const int blocksize = 6; + +// Space dimension +const int dim = 3; + +using namespace Dune; +using std::string; + +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; + + //typedef BCRSMatrix<FieldMatrix<double, blocksize, blocksize> > RodMatrixType; + //typedef BlockVector<FieldVector<double, blocksize> > RodCorrectionType; + typedef std::vector<Configuration> RodSolutionType; + + // parse data file + ConfigParser parameterSet; + parameterSet.parseFile("dirneucoupling.parset"); + + // read solver settings + const int minLevel = parameterSet.get("minLevel", int(0)); + const int maxLevel = parameterSet.get("maxLevel", int(0)); + const int maxDirichletNeumannSteps = parameterSet.get("maxDirichletNeumannSteps", int(0)); + const int maxTrustRegionSteps = parameterSet.get("maxTrustRegionSteps", 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 + std::string path = parameterSet.get("path", "xyz"); + std::string objectName = parameterSet.get("gridFile", "xyz"); + std::string dirichletNodesFile = parameterSet.get("dirichletNodes", "xyz"); + std::string dirichletValuesFile = parameterSet.get("dirichletValues", "xyz"); + std::string interfaceNodesFile = parameterSet.get("interfaceNodes", "xyz"); + const int numRodBaseElements = parameterSet.get("numRodBaseElements", int(0)); + + + // /////////////////////////////////////// + // Create the rod grid + // /////////////////////////////////////// + typedef OneDGrid<1,1> RodGridType; + RodGridType rodGrid(numRodBaseElements, 0, 5); + + // /////////////////////////////////////// + // Create the grid for the 3d object + // /////////////////////////////////////// + typedef UGGrid<dim,dim> GridType; + GridType grid; + grid.setRefinementType(GridType::COPY); + + AmiraMeshReader<GridType>::read(grid, path + objectName); + + + //Array<SimpleVector<BoxConstraint<dim> > > trustRegionObstacles(1); + //Array<BitField> hasObstacle(1); + Array<BitField> dirichletNodes(1); + + double trustRegionRadius = 0.1; + + RodSolutionType rodX(rodGrid.size(0,1)); + + // ////////////////////////// + // Initial solution + // ////////////////////////// + + for (int i=0; i<rodX.size(); i++) { + rodX[i].r = 0.5; + rodX[i].r[2] = i+5; + rodX[i].q = Quaternion<double>::identity(); + } + + rodX[rodX.size()-1].r[0] = 0.5; + rodX[rodX.size()-1].r[1] = 0.5; + rodX[rodX.size()-1].r[2] = 11; +// rodX[rodX.size()-1].q[0] = 0; +// rodX[rodX.size()-1].q[1] = 0; +// rodX[rodX.size()-1].q[2] = 1/sqrt(2); +// rodX[rodX.size()-1].q[3] = 1/sqrt(2); + +// std::cout << "Left boundary orientation:" << std::endl; +// std::cout << "director 0: " << rodX[0].q.director(0) << std::endl; +// std::cout << "director 1: " << rodX[0].q.director(1) << std::endl; +// std::cout << "director 2: " << rodX[0].q.director(2) << std::endl; +// std::cout << std::endl; + std::cout << "Right boundary orientation:" << std::endl; + std::cout << "director 0: " << rodX[rodX.size()-1].q.director(0) << std::endl; + std::cout << "director 1: " << rodX[rodX.size()-1].q.director(1) << std::endl; + std::cout << "director 2: " << rodX[rodX.size()-1].q.director(2) << std::endl; +// exit(0); + + int toplevel = rodGrid.maxLevel(); + + // ///////////////////////////////////////////////////// + // Determine the Dirichlet nodes + // ///////////////////////////////////////////////////// + Array<VectorType> dirichletValues; + dirichletValues.resize(toplevel+1); + dirichletValues[0].resize(grid.size(0, dim)); + AmiraMeshReader<int>::readFunction(dirichletValues[0], path + dirichletValuesFile); + + Array<BoundaryPatch<GridType> > dirichletBoundary; + dirichletBoundary.resize(maxLevel+1); + dirichletBoundary[0].setup(grid, 0); + readBoundaryPatch(dirichletBoundary[0], path + dirichletNodesFile); + PatchProlongator<GridType>::prolong(dirichletBoundary); + + dirichletNodes.resize(toplevel+1); + for (int i=0; i<=toplevel; i++) { + + dirichletNodes[i].resize( dim*grid.size(i,dim) + blocksize * rodGrid.size(i,1)); + dirichletNodes[i].unsetAll(); + + for (int j=0; j<grid.size(i,dim); j++) + for (int k=0; k<dim; k++) + dirichletNodes[i][j*dim+k] = dirichletBoundary[i].containsVertex(j); + + for (int j=0; j<blocksize; j++) + dirichletNodes[i][dirichletNodes[i].size()-1-j] = true; + + } + + // //////////////////////////////////////////////////////////// + // Create solution and rhs vectors + // //////////////////////////////////////////////////////////// + + VectorType totalRhs, totalCorr; + totalRhs.resize(grid.size(toplevel,dim) + 2*rodGrid.size(toplevel,1)); + totalCorr.resize(grid.size(toplevel,dim) + 2*rodGrid.size(toplevel,1)); + + // ////////////////////////////////////////// + // Assemble 3d linear elasticity problem + // ////////////////////////////////////////// + LeafP1Function<GridType,double,dim> u(grid),f(grid); + LinearElasticityLocalStiffness<GridType,double> lstiff(2.5e5, 0.3); + LeafP1OperatorAssembler<GridType,double,dim> hessian3d(grid); + hessian3d.assemble(lstiff,u,f); + + VectorType x3d(grid.size(toplevel,dim)); + //VectorType corr3d(grid.size(toplevel,dim)); + VectorType rhs3d(grid.size(toplevel,dim)); + + // No external forces + rhs3d = 0; + + // Set initial solution + x3d = 0; + for (int i=0; i<x3d.size(); i++) + for (int j=0; j<dim; j++) + if (dirichletNodes[toplevel][i*dim+j]) + x3d[i][j] = dirichletValues[toplevel][i][j]; + + // //////////////////////////////// + // Create a multigrid solver + // //////////////////////////////// + + // 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, postsmoother; + + ContactMMGStep<MatrixType, VectorType> contactMMGStep(totalHessian, totalCorr, totalRhs, 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::QUIET; + + + + EnergyNorm<MatrixType, VectorType> energyNorm(contactMMGStep); + + IterativeSolver<MatrixType, VectorType> solver; + solver.iterationStep = &contactMMGStep; + solver.numIt = numIt; + solver.verbosity_ = Solver::FULL; + solver.errorNorm_ = &energyNorm; + solver.tolerance_ = tolerance; + + // //////////////////////////////////// + // 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<VectorType>* newTransferOp = new TruncatedMGTransfer<VectorType>; + newTransferOp->setup(grid,i,i+1); + contactMMGStep.mgTransfer_[i] = newTransferOp; + } + + // ///////////////////////////////////////////////////// + // Dirichlet-Neumann Solver + // ///////////////////////////////////////////////////// + + // Init interface value + Configuration lambda; + lambda.r = 0; + lambda.q = Quaternion<double>::identity(); + + for (int i=0; i<maxDirichletNeumannSteps; i++) { + + std::cout << "----------------------------------------------------" << std::endl; + std::cout << " Dirichlet-Neumann Step Number: " << i << std::endl; + std::cout << "----------------------------------------------------" << std::endl; + + // ////////////////////////////////////////////////// + // Dirichlet step for the rod + // ////////////////////////////////////////////////// + + rodX[0] = lambda; + + rodSolver.solve(); + + // /////////////////////////////////////////////////////////// + // Extract Neumann values and transfer it to the 3d object + // /////////////////////////////////////////////////////////// + + // /////////////////////////////////////////////////////////// + // Solve the Neumann problem for the 3d body + // /////////////////////////////////////////////////////////// + + // /////////////////////////////////////////////////////////// + // Extract new interface position and orientation + // /////////////////////////////////////////////////////////// + Configuration averageInterface; + computeAverageInterface(interface, x, averageInterface); + + // /////////////////////////////////////////////////////////// + // Compute new damped interface value + // /////////////////////////////////////////////////////////// + + } + + // ////////////////////////////// + // Output result + // ////////////////////////////// + AmiraMeshWriter<GridType>::writeGrid(grid, "grid.result"); + AmiraMeshWriter<GridType>::writeBlockVector(grid, x3d, "grid.sol"); + writeRod(rodX, "rod3d.result"); + + } catch (Exception e) { + + std::cout << e << std::endl; + + }