Skip to content
Snippets Groups Projects
phasefield4.cc 4.16 KiB
Newer Older
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#if ! HAVE_DUNE_FUNCTIONS
#error "Require dune-functions!"
#endif

#if ! HAVE_DUNE_ALUGRID
#error "Require dune-alugrid!"
#endif

#if ! HAVE_ALBERTA
#error "Require Alberta!"
#endif

#include <iostream>
#include <dune/common/parallel/mpihelper.hh> // An initializer of MPI
#include <dune/common/exceptions.hh> // We use exceptions

#include <dune/alugrid/grid.hh>

#include <dune/multimesh/mmhierarchiciterator.hh>
#include <dune/multimesh/mmgridfactory.hh>

#include <dune/geometry/quadraturerules.hh>

#include <dune/grid/albertagrid/albertareader.hh>
#include <dune/grid/io/file/vtk/vtkwriter.hh>

#include <boost/numeric/mtl/mtl.hpp>
#include <boost/numeric/mtl/interface/umfpack_solve.hpp>

#include <dune/functions/functionspacebases/interpolate.hh>
#include <dune/functions/functionspacebases/hierarchicvectorwrapper.hh>
#include <dune/functions/functionspacebases/lagrangebasis.hh>

#include <dune/functions/gridfunctions/discreteglobalbasisfunction.hh>


using namespace Dune;
using namespace Dune::Indices;

struct MTLVector
{
  using value_type = double;

  MTLVector(mtl::dense_vector<double>& vec)
    : vec_(vec) {}

  void resize(std::size_t s) { vec_.change_dim(s); }

  std::size_t size() const { return mtl::size(vec_); }

  decltype(auto) operator[](std::size_t i) { return vec_[i]; }
  decltype(auto) operator[](std::size_t i) const { return vec_[i]; }

  decltype(auto) operator[](ReservedVector<long unsigned int, 1> i) { return vec_[i[0]]; }
  decltype(auto) operator[](ReservedVector<long unsigned int, 1> i) const { return vec_[i[0]]; }

  mtl::dense_vector<double>& vec_;
};

template <class VectorType, class Basis>
void writeFile(VectorType& x, Basis const& basis, std::string filename)
{
  auto gv = basis.gridView();
  auto xWrapper = MTLVector(x);
  auto xFct = Functions::makeDiscreteGlobalBasisFunction<double>(basis, TypeTree::hybridTreePath(), xWrapper);
  VTKWriter<decltype(gv)> vtkWriter(gv);
  vtkWriter.addVertexData(xFct, VTK::FieldInfo("u", VTK::FieldInfo::Type::scalar, 1));
  vtkWriter.write(filename);
}


int main(int argc, char** argv)
{
  MPIHelper::instance(argc, argv);

  assert(argc > 1);
  std::string filename = argv[1];

  using Grid = Dune::ALUGrid<2, 2, Dune::simplex, Dune::conforming>;
  AlbertaReader<Grid> albertaReader;
  GridFactory<Grid> factory;
  albertaReader.readGrid(filename, factory);

  std::unique_ptr<Grid> gridPtr(factory.createGrid());
  auto& grid = *gridPtr;

  double eps = 0.05;
  auto signedDistFct = [](auto const& x) { return x.two_norm() - 1.0; };

  grid.globalRefine(6);

  // refine grid[1] along phase-field interface
  for (int i = 0; i < 8; ++i) {
    std::cout << "refine " << i << "...\n";
    for (auto const& elem : elements(grid.leafGridView())) {
      auto geo = elem.geometry();
      bool refine = false;
      for (int j = 0; j < geo.corners(); ++j)
        refine = refine || std::abs(signedDistFct(geo.corner(j))) < std::max(1,6-i)*eps;

      if (refine)
        grid.mark(1, elem);
    }

    grid.preAdapt();
    grid.adapt();
    grid.postAdapt();
  }

  using namespace Functions::BasisBuilder;
  auto fine_basis = makeBasis(grid.leafGridView(), lagrange<1>());

  using VectorType = mtl::dense_vector<double>;
  using MatrixType = mtl::compressed2D<double>;

  // interpolate phase-field to fine grid
  VectorType phase(fine_basis.dimension());
  auto phaseWrapper = MTLVector(phase);
  interpolate(fine_basis, phaseWrapper, [eps,d=signedDistFct](auto const& x)
  {
    return 0.5*(1.0 - std::tanh(3.0*d(x)/eps));
  });
  writeFile(phase, fine_basis, "phase");

  // assemble a sequence of systems for finer and finer grids
  for (int l = 2; l < 7; ++l) {
    auto coarse_basis = makeBasis(grid.levelGridView(l), lagrange<1>());

    VectorType rhs(coarse_basis.dimension());
    MatrixType matrix(coarse_basis.dimension(), coarse_basis.dimension());
    assembleSystem(coarse_basis, fine_basis, phase, matrix, rhs, eps);

    VectorType u(coarse_basis.dimension());
    u = 0.0;
    umfpack_solve(matrix, u, rhs);

    writeFile(u, coarse_basis, "u_" + std::to_string(l));
  }
}