Newer
Older

Lisa Julia Nebel
committed
#include <config.h>
#include <fenv.h>
#include <array>
#include <dune/common/typetraits.hh>
#include <dune/common/bitsetvector.hh>
#include <dune/common/parametertree.hh>
#include <dune/curvedgeometry/curvedgeometry.hh>
#include <dune/curvedgrid/grid.hh>
#include <dune/curvedgrid/gridfunctions/analyticdiscretefunction.hh>
#include <dune/curvedgrid/geometries/cylinder.hh>
#include <dune/grid/yaspgrid.hh>
#include <dune/grid/utility/structuredgridfactory.hh>
#include <dune/gfe/linearalgebra.hh>
#include <dune/grid/io/file/vtk/subsamplingvtkwriter.hh>
// grid dimension
const int gridDim = 2;
const int dimWorld = 3;
const int approximationOrderGeometry = 4;
const int approximationOrderAnalytics = 6;
const int elementsCircle = 9;
const auto pi = std::acos(-1.0);
using namespace Dune;
int main (int argc, char *argv[])
{
MPIHelper::instance(argc,argv);
// Cylinder
static const double radius = 4;
static const double height = 2;
static const double cylinderFraction = 0.75;
/////////////////////////////////////////////
// Create the grid for the cylinder
/////////////////////////////////////////////
struct CylinderCreator
: public Dune :: AnalyticalCoordFunction< double, 2, 3, CylinderCreator >
{
FieldVector<double,3> operator() ( const FieldVector<double, 2> &x ) const

Lisa Julia Nebel
committed
{
FieldVector<double,3> y;
y[0] = radius * std::cos(x[0]);
y[1] = radius * std::sin(x[0]);
y[2] = x[1];
return y;

Lisa Julia Nebel
committed
}
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
};
using GridType = Dune::GeometryGrid< YaspGrid<gridDim>, CylinderCreator>;
std::shared_ptr<YaspGrid<gridDim> > hostGrid;
hostGrid = Dune::StructuredGridFactory<Dune::YaspGrid<2> >::createCubeGrid({0, 0}, {cylinderFraction*2*pi, height}, {elementsCircle,2});
auto cylinderCreator = std::make_shared<CylinderCreator>();
auto grid = std::make_shared<GridType>(hostGrid, cylinderCreator);
auto gridView = grid->leafGridView();
auto cylinder = CylinderProjection<double>{radius};
auto polynomialCylinderGF = analyticDiscreteFunction(cylinder, *grid, approximationOrderAnalytics);
auto analyticCylinderGF = cylinderGridFunction<GridType>(radius);
auto cylinderLocalFunction = localFunction(analyticCylinderGF);
auto quadOrder = 10;
for (const auto& element : elements(gridView, Dune::Partitions::interior)) {
using DT = decltype(gridView)::ctype;
Dune::CurvedGeometry<DT, gridDim, dimWorld, Dune::CurvedGeometryTraits<DT, Dune::LagrangeLFECache<DT,DT,gridDim> > >
polynomialGeometry(Dune::referenceElement(element.geometry()), [element, polynomialCylinderGF](const auto& local) {
auto localGridFunction = localFunction(polynomialCylinderGF);
localGridFunction.bind(element);
return localGridFunction(local);
}, approximationOrderGeometry);
cylinderLocalFunction.bind(element);
auto localGeometry = Dune::DefaultLocalGeometry<double,2,2>{};
auto analyticGeometry = Dune::LocalFunctionGeometry{element.type(), cylinderLocalFunction, localGeometry};
Dune::LagrangeLFECache<DT,DT,gridDim> cache(approximationOrderAnalytics);
auto refEle = referenceElement(element);
auto lFE = cache.get(refEle.type());
const auto& quad = Dune::QuadratureRules<DT, gridDim>::rule(element.type(), quadOrder);
for (size_t pt=0; pt<quad.size(); pt++) {
// Check if mean curvature is correct
auto realMeanCurvature = std::abs(cylinder.mean_curvature(polynomialGeometry.global(quad[pt].position())));
auto normalDerivativeP = polynomialGeometry.normalGradient(quad[pt].position());
auto approximatedCurvatureP = 0.5*std::abs(Dune::GFE::trace(normalDerivativeP));
auto relativeDifferenceP = std::abs((realMeanCurvature - approximatedCurvatureP)/realMeanCurvature);
auto normalDerivativeA = analyticGeometry.normalGradient(quad[pt].position(), lFE);
auto approximatedCurvatureA = 0.5*std::abs(Dune::GFE::trace(normalDerivativeA));
std::cout << approximatedCurvatureA << std::endl;
auto relativeDifferenceA = std::abs((realMeanCurvature - approximatedCurvatureA)/realMeanCurvature);
if (relativeDifferenceP > 0.005) {
std::cerr << "At point " << polynomialGeometry.global(quad[pt].position()) << " the curvature (approximated using a polynomial) is "
<< approximatedCurvatureP << " but " << realMeanCurvature << " was expected!" << std::endl;
return 1;
}
if (relativeDifferenceA > 0.005) {
std::cerr << "At point " << polynomialGeometry.global(quad[pt].position()) << " the curvature (approximated using the real analytic cylinder function) is "
<< approximatedCurvatureA << " but " << realMeanCurvature << " was expected!" << std::endl;
return 1;
}
}
}