Grids and Discrete Functions
A grid is a partitioning of a domain into simple geometric elements, like triangles or quads in 2d and tetrahedra, cubes, pyramids, or prisms in 3d. The grid data structure manages the various entities (vertices, edges, faces, and cells) that are part of the grid and its connectivity.
Several grid implementations are available for different puroses. Some are optimized for very structured domain discretizations, some are build for unstructured grids. Some grid managers are shipped with the Dune core modules, others need to be installed separately, as an extra Dune module or external library.
All grid implementations have a common interface defined in dune-grid
. But each
module may have some extended features not shared with other grid managers.
Some standard grid modules are
OneDGrid
: an unstructured one-dimensional gridYaspGrid
: a structured 2/3 dimensional cube gridUGGrid
: an unstructured 2/3 dimensional grid with mixed element types (requires thedune-uggrid
module)AlbertaGrid
: wrapper for the 1/2/3 dimensional simplex grid of the external Alberta FEM library. Allows for surface grids, i.e.dim != dow
.
Grid Construction
There are several ways to create a grid. Each grid provides some construtors
for individual creation. A common approach is to use a GridFactory
that
allows to insert vertices and element connectivity directly. For rectangular
domains a StructuredGridFactory
can be used that discretizes a box-partitioning
of the domain into cubes or simplices. And there are some file readers that allow
to read a grid description from a common file format, like GMsh
, AmiraMesh
, or
AlbertaGrid
files.
#include <dune/grid/yaspgrid.hh>
#include <dune/grid/uggrid.hh>
// direct creation of [0.0, 1.0]^2 with 4 elements in each coordinate direction
Dune::YaspGrid<2> grid1({1.0, 1.0}, {4,4});
// using a StructuredGridFactory
using Factory = Dune::StructuredGridFactory<Dune::YaspGrid<2>>;
std::array<unsigned int, 2> numCells{4,4};
std::unique_ptr<Dune::YaspGrid<2>> grid2( Factory::createCubeGrid({0.0, 0.0}, {1.0, 1.0}, numCells) );
// using a file reader
using Reader = Dune::GmshReader<Dune::UGGrid<2>>;
std::unique_ptr<Dune::UGGrid<2>> grid3( Reader::read("gridfile.msh") );
AMDiS provides a way to construct a grid by inspecting some initfile parameters.
Therefore, we have implemented the MeshCreator
. It expects in the constructor the
base name of a parameter that defines how to construct the grid given as template
type:
#include <dune/grid/albertagrid.hh>
using Grid = Dune::AlbertaGrid<2>;
std::unique_ptr<Grid> grid4( MeshCreator<Grid>("mesh").create() );
where "mesh"
defines a key that can be used in the parameter file to describe the grid:
% structured rectangular grid
mesh->structured: [cube|simplex]
mesh->min corner: 0.0 0.0
mesh->max corner: 1.0 1.0
mesh->num cells: 4 4
% read grid from file
mesh->macro file name: gridfile.msh
At first, the MeshCreator
looks for the parameter macro file name
, if found,
it tries to determine from the file extension which file format to read. GMsh
files use the extension .msh
, AlbertaGrid
files one of .2d
, .3d
, or .amc
and
the Dune DGF files have the extension .dgf
.
If no filename is given, it looks for the structured
parameter to determine
which elements (cubes or simplices) to use for the construction of a structured
rectangular grid described by the bounding box min corner
- max corner
and
the number of subdivisions in each coordinate direction num cells
.
If no structured
parameter is given, the MeshCreator tries to create the grid
directly. This may allow to pass more grid specific parameters, e.g. the YaspGrid
allows to specify in addition to min corner
, max corner
, and num cells
:
overlap
: the number of overlapping elements in a partitioned gridperiodic
: a bitfield characterizing the periodicity of the grid
A full list of available parameters can be found in the initfile article.
Global Basis and Function Spaces
A discrete function is described by a set of (global) basis functions and a coefficient
vector. This pair is called a DOFVector
in AMDiS. The global basis is thereby
a class implementing the interface of the GlobalBasis
in the dune-functions module.
The simplest global bases are build of a composition of local basis functions associated to grid elements. The connectivity of these basis functions, i.e. a global numbering of all the local functions, defines the set of global basis functions restricted to each grid element. Details about this interface and mathematical background can be found on dune-project and in the publication The interface for functions in the dune-functions module.
Construction of a global basis can be done using directly the factory functions of dune-functions:
#include <dune/functions/functionspacebases/lagrangebasis.hh>
#include <dune/functions/functionspacebases/powerbasis.hh>
#include <amdis/functions/GlobalBasis.hpp>
// the factory functions are defined in this namespace
using namespace Dune::Functions::BasisFactory;
// create a power basis of 3 lagrange bases with local polynomial degree 2
// on the leaf elements of the grid
GlobalBasis basis1{grid2->leafGridView(), power<3>(lagrange<2>())};
or by using some predefined wrappers:
#include <amdis/ProblemStatTraits.hpp>
// use the wrapper provided in AMDiS to create a power basis of 3 lagrange bases
// of local polynomial degree 2
using BasisCreator = LagrangeBasis<Dune::YaspGrid<2>, 2,2,2>;
auto basis2 = BasisCreator::create(grid2->leafGridView());
Note
Different to dune-functions, we have introduced a (Parallel) GlobalBasis that has a direct connection to the underlying Grid and can thus react on grid changes by grid refinement or by repartitioning. Additionally, it stores a communication object to construct global DOFMappings for distributed data structured.
This GlobalBasis
can be converted from a DefaultGlobalBasis
of dune-functions.
A DOFVector
takes a global basis and provides the coefficient vector as data member.
This defines a discrete function that can be evaluated in local and global coordinates
and can be used as GridFunction
in the operators, see below.
// use a generator function
auto vec1 = makeDOFVector(basis1);
// provide the type of the basis directly
DOFVector<typename BasisCreator::GlobalBasis> vec2(basis2);
// with c++17 class template argument deduction
DOFVector vec3(basis2);
Note
DOFVectors allow to specify the underlying data type, e.g. to use quad-precision coefficients or (maybe in the future) to use complex-valued data.
This coefficient type can be specified as additional template parameter to makeDOFVector<double>(...)
or in the class templates DOFVector<GB, double>
.