Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • podlesny/dune-tectonic
  • agnumpde/dune-tectonic
2 results
Show changes
Showing
with 1090 additions and 339 deletions
#ifndef SRC_MIDPOINT_HH
#define SRC_MIDPOINT_HH
#include <dune/solvers/common/arithmetic.hh>
template <class Vector> Vector midPoint(Vector const &x, Vector const &y) {
Vector ret(0);
Arithmetic::addProduct(ret, 0.5, x);
Arithmetic::addProduct(ret, 0.5, y);
return ret;
}
#endif
#ifndef SRC_SAND_WEDGE_DATA_MYBODY_HH
#define SRC_SAND_WEDGE_DATA_MYBODY_HH
#ifndef SRC_ONE_BODY_PROBLEM_DATA_MYBODY_HH
#define SRC_ONE_BODY_PROBLEM_DATA_MYBODY_HH
#include <dune/common/fvector.hh>
......@@ -8,8 +8,8 @@
#include <dune/tectonic/body.hh>
#include <dune/tectonic/gravity.hh>
#include "twopiece.hh"
#include "mygeometry.hh"
#include "segmented-function.hh"
template <int dimension> class MyBody : public Body<dimension> {
using typename Body<dimension>::ScalarFunction;
......@@ -47,9 +47,9 @@ template <int dimension> class MyBody : public Body<dimension> {
private:
double const poissonRatio_;
double const youngModulus_;
TwoPieceFunction const shearViscosityField_;
TwoPieceFunction const bulkViscosityField_;
TwoPieceFunction const densityField_;
SegmentedFunction const shearViscosityField_;
SegmentedFunction const bulkViscosityField_;
SegmentedFunction const densityField_;
Gravity<dimension> const gravityField_;
};
#endif
......@@ -4,14 +4,13 @@
#include <fstream>
#include "mygeometry.hh"
#ifdef HAVE_CAIROMM
#include <cairomm/context.h>
#include <cairomm/fontface.h>
#include <cairomm/surface.h>
#endif
double MyGeometry::verticalProjection(LocalVector const &x) {
return zenith * x;
}
double MyGeometry::horizontalProjection(LocalVector const &x) {
return rotatedZenith * x;
}
#include "mygeometry.hh"
void MyGeometry::write() {
std::fstream writer("geometry", std::fstream::out);
......@@ -48,19 +47,18 @@ void MyGeometry::render() {
((colour & 0x00FF00) >> 8) / 255.0,
((colour & 0x0000FF) >> 0) / 255.0);
};
auto const moveTo = [&](LocalVector const &v) { cr->move_to(v[0], -v[1]); };
auto const lineTo = [&](LocalVector const &v) { cr->line_to(v[0], -v[1]); };
auto const moveTo = [&](LocalVector2D const &v) { cr->move_to(v[0], -v[1]); };
auto const lineTo = [&](LocalVector2D const &v) { cr->line_to(v[0], -v[1]); };
cr->scale(widthScale, heightScale);
cr->translate(0.1, 0.1);
cr->rotate(leftAngle);
cr->set_line_width(0.0025);
// triangle
{
moveTo(A);
lineTo(B);
lineTo(C);
moveTo(reference::A);
lineTo(reference::B);
lineTo(reference::C);
cr->close_path();
cr->stroke();
}
......@@ -70,10 +68,10 @@ void MyGeometry::render() {
cr->save();
std::vector<double> dashPattern = { 0.005 };
cr->set_dash(dashPattern, 0);
moveTo(Z);
lineTo(Y);
moveTo(U);
lineTo(X);
moveTo(reference::Z);
lineTo(reference::Y);
moveTo(reference::U);
lineTo(reference::X);
cr->stroke();
cr->restore();
}
......@@ -82,9 +80,9 @@ void MyGeometry::render() {
{
cr->save();
setRGBColor(0x0097E0);
moveTo(B);
lineTo(K);
lineTo(M);
moveTo(reference::B);
lineTo(reference::K);
lineTo(reference::M);
cr->fill();
cr->restore();
}
......@@ -94,41 +92,40 @@ void MyGeometry::render() {
cr->save();
setRGBColor(0x7AD3FF);
cr->set_line_width(0.005);
moveTo(X);
lineTo(Y);
moveTo(reference::X);
lineTo(reference::Y);
cr->stroke();
cr->restore();
}
// mark points
{
auto const drawCircle = [&](LocalVector const &v) {
auto const drawCircle = [&](LocalVector2D const &v) {
cr->arc(v[0], -v[1], 0.0075, -M_PI, M_PI); // x,y,radius,angle1,angle2
cr->fill();
};
cr->save();
setRGBColor(0x002F47);
drawCircle(A);
drawCircle(B);
drawCircle(C);
drawCircle(Y);
drawCircle(X);
drawCircle(Z);
drawCircle(U);
drawCircle(K);
drawCircle(M);
drawCircle(G);
drawCircle(H);
drawCircle(J);
drawCircle(I);
drawCircle(reference::A);
drawCircle(reference::B);
drawCircle(reference::C);
drawCircle(reference::Y);
drawCircle(reference::X);
drawCircle(reference::Z);
drawCircle(reference::U);
drawCircle(reference::K);
drawCircle(reference::M);
drawCircle(reference::G);
drawCircle(reference::H);
drawCircle(reference::J);
drawCircle(reference::I);
cr->restore();
}
// labels
{
auto const label = [&](LocalVector const &v,
std::string l) { // TODO: implicit?
auto const label = [&](LocalVector2D const &v, std::string l) {
moveTo(v);
cr->rel_move_to(0.005, -0.02);
cr->show_text(l);
......@@ -140,19 +137,19 @@ void MyGeometry::render() {
cr->set_font_face(font);
cr->set_font_size(0.03);
label(A, "A");
label(B, "B");
label(C, "C");
label(K, "K");
label(M, "M");
label(U, "U");
label(X, "X");
label(Y, "Y");
label(Z, "Z");
label(G, "G");
label(H, "H");
label(J, "J");
label(I, "I");
label(reference::A, "A");
label(reference::B, "B");
label(reference::C, "C");
label(reference::K, "K");
label(reference::M, "M");
label(reference::U, "U");
label(reference::X, "X");
label(reference::Y, "Y");
label(reference::Z, "Z");
label(reference::G, "G");
label(reference::H, "H");
label(reference::J, "J");
label(reference::I, "I");
cr->restore();
}
......
#ifndef SRC_MYGEOMETRY_HH
#define SRC_MYGEOMETRY_HH
#include <dune/common/fvector.hh>
#include "midpoint.hh"
namespace MyGeometry {
namespace {
using LocalVector2D = Dune::FieldVector<double, 2>;
using LocalMatrix2D = Dune::FieldMatrix<double, 2, 2>;
using LocalVector = Dune::FieldVector<double, MY_DIM>;
}
namespace reference {
double const s = 1.0; // scaling factor
double const rightLeg = 0.27 * s;
double const leftLeg = 1.00 * s;
double const leftAngle = atan(rightLeg / leftLeg);
double const viscoHeight = 0.06 * s; // Height of the viscous bottom layer
double const weakLen = 0.20 * s; // Length of the weak zone
double const zDistance = 0.35;
LocalVector2D const A = {0, 0};
LocalVector2D const B = {leftLeg, -rightLeg};
LocalVector2D const C = {leftLeg, 0};
LocalVector2D const Z = {zDistance * s, 0};
LocalVector2D const Y = {zDistance * s, -zDistance *s / leftLeg *rightLeg};
LocalVector2D const X = {Y[0] - weakLen * std::cos(leftAngle),
Y[1] + weakLen *std::sin(leftAngle)};
LocalVector2D const U = {X[0], 0};
LocalVector2D const K = {B[0] - leftLeg * viscoHeight / rightLeg,
B[1] + viscoHeight};
LocalVector2D const M = {B[0], B[1] + viscoHeight};
LocalVector2D const G = midPoint(A, X);
LocalVector2D const H = midPoint(X, Y);
LocalVector2D const J = midPoint(Y, B);
LocalVector2D const I = {Y[0] + G[0], Y[1] + G[1]};
LocalVector2D const zenith = {0, 1};
LocalMatrix2D const rotation = {{std::cos(leftAngle), -std::sin(leftAngle)},
{std::sin(leftAngle), std::cos(leftAngle)}};
}
namespace {
LocalVector rotate(LocalVector2D const &x) {
LocalVector2D ret2D;
reference::rotation.mv(x, ret2D);
LocalVector ret(0);
ret[0] = ret2D[0];
ret[1] = ret2D[1];
return ret;
}
}
double const lengthScale = reference::s;
double const depth = 0.60 * lengthScale;
LocalVector const A = rotate(reference::A);
LocalVector const B = rotate(reference::B);
LocalVector const C = rotate(reference::C);
LocalVector const G = rotate(reference::G);
LocalVector const H = rotate(reference::H);
LocalVector const I = rotate(reference::I);
LocalVector const J = rotate(reference::J);
LocalVector const K = rotate(reference::K);
LocalVector const M = rotate(reference::M);
LocalVector const U = rotate(reference::U);
LocalVector const X = rotate(reference::X);
LocalVector const Y = rotate(reference::Y);
LocalVector const Z = rotate(reference::Z);
LocalVector const zenith = rotate(reference::zenith);
void write();
void render();
}
#endif
#ifndef SRC_SAND_WEDGE_DATA_MYGLOBALFRICTIONDATA_HH
#define SRC_SAND_WEDGE_DATA_MYGLOBALFRICTIONDATA_HH
#ifndef SRC_ONE_BODY_PROBLEM_DATA_MYGLOBALFRICTIONDATA_HH
#define SRC_ONE_BODY_PROBLEM_DATA_MYGLOBALFRICTIONDATA_HH
#include <dune/common/function.hh>
#include <dune/common/fvector.hh>
#include <dune/tectonic/globalfrictiondata.hh>
#include "mygeometry.hh"
#include "patchfunction.hh"
template <int dimension>
class MyGlobalFrictionData : public GlobalFrictionData<dimension> {
template <class LocalVector>
class MyGlobalFrictionData : public GlobalFrictionData<LocalVector::dimension> {
private:
using typename GlobalFrictionData<dimension>::VirtualFunction;
using typename GlobalFrictionData<LocalVector::dimension>::VirtualFunction;
public:
MyGlobalFrictionData(Dune::ParameterTree const &parset)
MyGlobalFrictionData(Dune::ParameterTree const &parset,
ConvexPolyhedron<LocalVector> const &segment)
: C_(parset.get<double>("C")),
L_(parset.get<double>("L")),
V0_(parset.get<double>("V0")),
a_(parset.get<double>("strengthening.a"),
parset.get<double>("weakening.a")),
parset.get<double>("weakening.a"), segment),
b_(parset.get<double>("strengthening.b"),
parset.get<double>("weakening.b")),
parset.get<double>("weakening.b"), segment),
mu0_(parset.get<double>("mu0")) {}
double virtual const &C() const override { return C_; }
double virtual const &L() const override { return L_; }
double virtual const &V0() const override { return V0_; }
VirtualFunction virtual const &a() const override { return a_; }
VirtualFunction virtual const &b() const override { return b_; }
double virtual const &mu0() const override { return mu0_; }
double const &C() const override { return C_; }
double const &L() const override { return L_; }
double const &V0() const override { return V0_; }
VirtualFunction const &a() const override { return a_; }
VirtualFunction const &b() const override { return b_; }
double const &mu0() const override { return mu0_; }
private:
double const C_;
......
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <dune/fufem/geometry/polyhedrondistance.hh>
#include "mygrid.hh"
#include "midpoint.hh"
#include "../diameter.hh"
#if MY_DIM == 3
SimplexManager::SimplexManager(unsigned int shift) : shift_(shift) {}
#endif
// back-to-front, front-to-back, front-to-back
void SimplexManager::addFromVerticesFBB(unsigned int U, unsigned int V,
unsigned int W) {
#if MY_DIM == 3
unsigned int const U2 = U + shift_;
unsigned int const V2 = V + shift_;
unsigned int const W2 = W + shift_;
simplices_.push_back({ U, V, W, U2 });
simplices_.push_back({ V, V2, W2, U2 });
simplices_.push_back({ W, W2, U2, V });
#else
simplices_.push_back({ U, V, W });
#endif
}
// back-to-front, back-to-front, front-to-back
void SimplexManager::addFromVerticesFFB(unsigned int U, unsigned int V,
unsigned int W) {
#if MY_DIM == 3
unsigned int const U2 = U + shift_;
unsigned int const V2 = V + shift_;
unsigned int const W2 = W + shift_;
simplices_.push_back({ U, V, W, U2 });
simplices_.push_back({ V, V2, W, U2 });
simplices_.push_back({ V2, W, U2, W2 });
#else
simplices_.push_back({ U, V, W });
#endif
}
auto SimplexManager::getSimplices() -> SimplexList const & {
return simplices_;
}
template <class Grid> GridConstructor<Grid>::GridConstructor() {
auto const &A = MyGeometry::A;
auto const &B = MyGeometry::B;
auto const &C = MyGeometry::C;
unsigned int const vc = 3;
#if MY_DIM == 3
Dune::FieldMatrix<double, 2 * vc, MY_DIM> vertices;
#else
Dune::FieldMatrix<double, vc, MY_DIM> vertices;
#endif
for (size_t i = 0; i < 2; ++i) {
#if MY_DIM == 3
size_t numXYplanes = 2;
#else
size_t numXYplanes = 1;
#endif
size_t k = 0;
for (size_t j = 1; j <= numXYplanes; ++j) {
vertices[k++][i] = A[i];
vertices[k++][i] = B[i];
vertices[k++][i] = C[i];
assert(k == j * vc);
}
}
#if MY_DIM == 3
for (size_t k = 0; k < vc; ++k) {
vertices[k][2] = -MyGeometry::depth / 2.0;
vertices[k + vc][2] = MyGeometry::depth / 2.0;
}
#endif
for (size_t i = 0; i < vertices.N(); ++i)
gridFactory.insertVertex(vertices[i]);
Dune::GeometryType cell;
#if MY_DIM == 3
cell.makeTetrahedron();
#else
cell.makeTriangle();
#endif
#if MY_DIM == 3
SimplexManager sm(vc);
#else
SimplexManager sm;
#endif
sm.addFromVerticesFFB(1, 2, 0);
auto const &simplices = sm.getSimplices();
// sanity-check choices of simplices
for (size_t i = 0; i < simplices.size(); ++i) {
Dune::FieldMatrix<double, MY_DIM, MY_DIM> check;
for (size_t j = 0; j < MY_DIM; ++j)
check[j] = vertices[simplices[i][j + 1]] - vertices[simplices[i][j]];
assert(check.determinant() > 0);
gridFactory.insertElement(cell, simplices[i]);
}
}
template <class Grid> std::shared_ptr<Grid> GridConstructor<Grid>::getGrid() {
return std::shared_ptr<Grid>(gridFactory.createGrid());
}
template <class Grid>
template <class GridView>
MyFaces<GridView> GridConstructor<Grid>::constructFaces(
GridView const &gridView) {
return MyFaces<GridView>(gridView);
}
template <class GridView>
template <class Vector>
bool MyFaces<GridView>::xyCollinear(Vector const &a, Vector const &b,
Vector const &c) {
return isClose2((b[0] - a[0]) * (c[1] - a[1]), (b[1] - a[1]) * (c[0] - a[0]));
}
template <class GridView>
template <class Vector>
bool MyFaces<GridView>::xyBoxed(Vector const &v1, Vector const &v2,
Vector const &x) {
auto const minmax0 = std::minmax(v1[0], v2[0]);
auto const minmax1 = std::minmax(v1[1], v2[1]);
if (minmax0.first - 1e-14 * MyGeometry::lengthScale > x[0] or
x[0] > minmax0.second + 1e-14 * MyGeometry::lengthScale)
return false;
if (minmax1.first - 1e-14 * MyGeometry::lengthScale > x[1] or
x[1] > minmax1.second + 1e-14 * MyGeometry::lengthScale)
return false;
return true;
}
template <class GridView>
template <class Vector>
bool MyFaces<GridView>::xyBetween(Vector const &v1, Vector const &v2,
Vector const &x) {
return xyCollinear(v1, v2, x) && xyBoxed(v1, v2, x);
}
template <class GridView>
MyFaces<GridView>::MyFaces(GridView const &gridView)
:
#if MY_DIM == 3
lower(gridView),
right(gridView),
upper(gridView),
front(gridView),
back(gridView)
#else
lower(gridView),
right(gridView),
upper(gridView)
#endif
{
assert(isClose(MyGeometry::A[1], 0));
assert(isClose(MyGeometry::B[1], 0));
lower.insertFacesByProperty([&](typename GridView::Intersection const &in) {
return isClose(0, in.geometry().center()[1]);
});
#if MY_DIM == 3
front.insertFacesByProperty([&](typename GridView::Intersection const &in) {
return isClose(MyGeometry::depth / 2.0, in.geometry().center()[2]);
});
back.insertFacesByProperty([&](typename GridView::Intersection const &in) {
return isClose(-MyGeometry::depth / 2.0, in.geometry().center()[2]);
});
#endif
upper.insertFacesByProperty([&](typename GridView::Intersection const &in) {
return xyBetween(MyGeometry::A, MyGeometry::C, in.geometry().center());
});
right.insertFacesByProperty([&](typename GridView::Intersection const &in) {
return xyBetween(MyGeometry::B, MyGeometry::C, in.geometry().center());
});
}
double computeAdmissibleDiameter(double distance, double smallestDiameter) {
return (distance / 0.0125 / MyGeometry::lengthScale + 1.0) * smallestDiameter;
}
template <class Grid, class LocalVector>
void refine(Grid &grid, ConvexPolyhedron<LocalVector> const &weakPatch,
double smallestDiameter) {
bool needRefine = true;
while (true) {
needRefine = false;
for (auto &&e : elements(grid.leafGridView())) {
auto const geometry = e.geometry();
auto const weakeningRegionDistance =
distance(weakPatch, geometry, 1e-6 * MyGeometry::lengthScale);
auto const admissibleDiameter =
computeAdmissibleDiameter(weakeningRegionDistance, smallestDiameter);
if (diameter(geometry) <= admissibleDiameter)
continue;
needRefine = true;
grid.mark(1, e);
}
if (!needRefine)
break;
grid.preAdapt();
grid.adapt();
grid.postAdapt();
}
}
#include "mygrid_tmpl.cc"
#ifndef SRC_ONE_BODY_PROBLEM_DATA_MYGRID_HH
#define SRC_ONE_BODY_PROBLEM_DATA_MYGRID_HH
#include <dune/common/fmatrix.hh>
#include <dune/grid/common/gridfactory.hh>
#include <dune/fufem/boundarypatch.hh>
#include <dune/fufem/geometry/convexpolyhedron.hh>
#include "mygeometry.hh"
template <class GridView> struct MyFaces {
BoundaryPatch<GridView> lower;
BoundaryPatch<GridView> right;
BoundaryPatch<GridView> upper;
#if MY_DIM == 3
BoundaryPatch<GridView> front;
BoundaryPatch<GridView> back;
#endif
MyFaces(GridView const &gridView);
private:
bool isClose(double a, double b) {
return std::abs(a - b) < 1e-14 * MyGeometry::lengthScale;
};
bool isClose2(double a, double b) {
return std::abs(a - b) <
1e-14 * MyGeometry::lengthScale * MyGeometry::lengthScale;
};
template <class Vector>
bool xyBoxed(Vector const &v1, Vector const &v2, Vector const &x);
template <class Vector>
bool xyCollinear(Vector const &a, Vector const &b, Vector const &c);
template <class Vector>
bool xyBetween(Vector const &v1, Vector const &v2, Vector const &x);
};
class SimplexManager {
public:
using SimplexList = std::vector<std::vector<unsigned int>>;
#if MY_DIM == 3
SimplexManager(unsigned int shift);
#endif
void addFromVerticesFBB(unsigned int U, unsigned int V, unsigned int W);
void addFromVerticesFFB(unsigned int U, unsigned int V, unsigned int W);
SimplexList const &getSimplices();
private:
SimplexList simplices_;
#if MY_DIM == 3
unsigned int const shift_;
#endif
};
template <class Grid> class GridConstructor {
public:
GridConstructor();
std::shared_ptr<Grid> getGrid();
template <class GridView>
MyFaces<GridView> constructFaces(GridView const &gridView);
private:
Dune::GridFactory<Grid> gridFactory;
};
double computeAdmissibleDiameter(double distance, double smallestDiameter);
template <class Grid, class LocalVector>
void refine(Grid &grid, ConvexPolyhedron<LocalVector> const &weakPatch,
double smallestDiameter);
#endif
#ifndef MY_DIM
#error MY_DIM unset
#endif
#include "../explicitgrid.hh"
#include "../explicitvectors.hh"
template class GridConstructor<Grid>;
template struct MyFaces<GridView>;
template MyFaces<GridView> GridConstructor<Grid>::constructFaces(
GridView const &gridView);
template void refine<Grid, LocalVector>(
Grid &grid, ConvexPolyhedron<LocalVector> const &weakPatch,
double smallestDiameter);
#ifndef SRC_ONE_BODY_PROBLEM_DATA_PATCHFUNCTION_HH
#define SRC_ONE_BODY_PROBLEM_DATA_PATCHFUNCTION_HH
#include <dune/common/function.hh>
#include <dune/common/fvector.hh>
#include <dune/common/parametertree.hh>
#include <dune/fufem/geometry/polyhedrondistance.hh>
class PatchFunction
: public Dune::VirtualFunction<Dune::FieldVector<double, MY_DIM>,
Dune::FieldVector<double, 1>> {
private:
using Polyhedron = ConvexPolyhedron<Dune::FieldVector<double, MY_DIM>>;
double const v1_;
double const v2_;
Polyhedron const &segment_;
public:
PatchFunction(double v1, double v2, Polyhedron const &segment)
: v1_(v1), v2_(v2), segment_(segment) {}
void evaluate(Dune::FieldVector<double, MY_DIM> const &x,
Dune::FieldVector<double, 1> &y) const {
y = distance(x, segment_, 1e-6 * MyGeometry::lengthScale) <= 1e-5 ? v2_
: v1_;
}
};
#endif
#ifndef SRC_SAND_WEDGE_DATA_TWOPIECE_HH
#define SRC_SAND_WEDGE_DATA_TWOPIECE_HH
#ifndef SRC_ONE_BODY_PROBLEM_DATA_SEGMENTED_FUNCTION_HH
#define SRC_ONE_BODY_PROBLEM_DATA_SEGMENTED_FUNCTION_HH
#include <dune/common/function.hh>
#include <dune/common/fvector.hh>
......@@ -7,30 +7,26 @@
#include "mygeometry.hh"
class TwoPieceFunction
: public Dune::VirtualFunction<Dune::FieldVector<double, 2>,
class SegmentedFunction
: public Dune::VirtualFunction<Dune::FieldVector<double, MY_DIM>,
Dune::FieldVector<double, 1>> {
private:
bool liesBelow(Dune::FieldVector<double, 2> const &x,
Dune::FieldVector<double, 2> const &y,
Dune::FieldVector<double, 2> const &z) const {
return (z[0] - x[0]) * (y[1] - x[1]) / (y[0] - x[0]) >= z[1] - x[1];
bool liesBelow(Dune::FieldVector<double, MY_DIM> const &x,
Dune::FieldVector<double, MY_DIM> const &y,
Dune::FieldVector<double, MY_DIM> const &z) const {
return x[1] + (z[0] - x[0]) * (y[1] - x[1]) / (y[0] - x[0]) >= z[1];
};
bool insideRegion2(Dune::FieldVector<double, 2> const &z) const {
return liesBelow(_K, _M, z);
bool insideRegion2(Dune::FieldVector<double, MY_DIM> const &z) const {
return liesBelow(MyGeometry::K, MyGeometry::M, z);
};
Dune::FieldVector<double, 2> const &_K;
Dune::FieldVector<double, 2> const &_M;
double const _v1;
double const _v2;
public:
TwoPieceFunction(double v1, double v2)
: _K(MyGeometry::K), _M(MyGeometry::M), _v1(v1), _v2(v2) {}
SegmentedFunction(double v1, double v2) : _v1(v1), _v2(v2) {}
void evaluate(Dune::FieldVector<double, 2> const &x,
void evaluate(Dune::FieldVector<double, MY_DIM> const &x,
Dune::FieldVector<double, 1> &y) const {
y = insideRegion2(x) ? _v2 : _v1;
}
......
#ifndef SRC_ONE_BODY_PROBLEM_DATA_WEAKPATCH_HH
#define SRC_ONE_BODY_PROBLEM_DATA_WEAKPATCH_HH
template <class LocalVector>
ConvexPolyhedron<LocalVector> getWeakPatch(Dune::ParameterTree const &parset) {
ConvexPolyhedron<LocalVector> weakPatch;
#if MY_DIM == 3
weakPatch.vertices.resize(4);
weakPatch.vertices[0] = weakPatch.vertices[2] = MyGeometry::X;
weakPatch.vertices[1] = weakPatch.vertices[3] = MyGeometry::Y;
for (size_t k = 0; k < 2; ++k) {
weakPatch.vertices[k][2] = -MyGeometry::depth / 2.0;
weakPatch.vertices[k + 2][2] = MyGeometry::depth / 2.0;
}
switch (parset.get<Config::PatchType>("patchType")) {
case Config::Rectangular:
break;
case Config::Trapezoidal:
weakPatch.vertices[1][0] += 0.05 * MyGeometry::lengthScale;
weakPatch.vertices[3][0] -= 0.05 * MyGeometry::lengthScale;
break;
default:
assert(false);
}
#else
weakPatch.vertices.resize(2);
weakPatch.vertices[0] = MyGeometry::X;
weakPatch.vertices[1] = MyGeometry::Y;
#endif
return weakPatch;
};
#endif
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_IPOPT
#undef HAVE_IPOPT
#endif
#include <atomic>
#include <cmath>
#include <csignal>
#include <exception>
#include <fstream>
#include <iostream>
#include <iomanip>
#include <dune/common/bitsetvector.hh>
#include <dune/common/exceptions.hh>
#include <dune/common/fmatrix.hh>
#include <dune/common/function.hh>
#include <dune/common/fvector.hh>
#include <dune/common/parallel/mpihelper.hh>
#include <dune/common/parametertree.hh>
#include <dune/common/parametertreeparser.hh>
#include <dune/grid/common/mcmgmapper.hh>
#include <dune/istl/bcrsmatrix.hh>
#include <dune/istl/bvector.hh>
#include <dune/fufem/boundarypatch.hh>
#include <dune/fufem/formatstring.hh>
#include <dune/solvers/norms/energynorm.hh>
#include <dune/solvers/solvers/loopsolver.hh>
#include <dune/solvers/solvers/solver.hh>
#include <dune/tnnmg/problem-classes/convexproblem.hh>
#include <dune/tectonic/geocoordinate.hh>
#include <dune/tectonic/myblockproblem.hh>
#include <dune/tectonic/globalfriction.hh>
#include <dune/fufem/hdf5/file.hh>
#include "assemblers.hh"
#include "diameter.hh"
#include "enumparser.hh"
#include "enums.hh"
#include "gridselector.hh"
#include "hdf5-writer.hh"
#include "hdf5/restart-io.hh"
#include "matrices.hh"
#include "program_state.hh"
#include "one-body-problem-data/bc.hh"
#include "one-body-problem-data/mybody.hh"
#include "one-body-problem-data/mygeometry.hh"
#include "one-body-problem-data/myglobalfrictiondata.hh"
#include "one-body-problem-data/mygrid.hh"
#include "one-body-problem-data/weakpatch.hh"
#include "spatial-solving/solverfactory.hh"
#include "time-stepping/adaptivetimestepper.hh"
#include "time-stepping/rate.hh"
#include "time-stepping/state.hh"
#include "time-stepping/updaters.hh"
#include "vtk.hh"
size_t const dims = MY_DIM;
Dune::ParameterTree getParameters(int argc, char *argv[]) {
Dune::ParameterTree parset;
Dune::ParameterTreeParser::readINITree("one-body-problem.cfg", parset);
Dune::ParameterTreeParser::readINITree(
Dune::Fufem::formatString("one-body-problem-%dD.cfg", dims), parset);
Dune::ParameterTreeParser::readOptions(argc, argv, parset);
return parset;
}
static std::atomic<bool> terminationRequested(false);
void handleSignal(int signum) { terminationRequested = true; }
int main(int argc, char *argv[]) {
try {
Dune::MPIHelper::instance(argc, argv);
auto const parset = getParameters(argc, argv);
MyGeometry::render();
MyGeometry::write();
using GridView = Grid::LeafGridView;
using MyAssembler = MyAssembler<GridView, dims>;
using Matrix = MyAssembler::Matrix;
using Vector = MyAssembler::Vector;
using LocalVector = Vector::block_type;
using ScalarMatrix = MyAssembler::ScalarMatrix;
using ScalarVector = MyAssembler::ScalarVector;
auto const weakPatch =
getWeakPatch<LocalVector>(parset.sub("boundary.friction.weakening"));
// {{{ Set up grid
GridConstructor<Grid> gridConstructor;
auto grid = gridConstructor.getGrid();
refine(*grid, weakPatch,
parset.get<double>("boundary.friction.smallestDiameter"));
double minDiameter = std::numeric_limits<double>::infinity();
double maxDiameter = 0.0;
for (auto &&e : elements(grid->leafGridView())) {
auto const geometry = e.geometry();
auto const diam = diameter(geometry);
minDiameter = std::min(minDiameter, diam);
maxDiameter = std::max(maxDiameter, diam);
}
std::cout << "min diameter: " << minDiameter << std::endl;
std::cout << "max diameter: " << maxDiameter << std::endl;
auto const leafView = grid->leafGridView();
auto const leafVertexCount = leafView.size(dims);
std::cout << "Number of DOFs: " << leafVertexCount << std::endl;
auto myFaces = gridConstructor.constructFaces(leafView);
BoundaryPatch<GridView> const neumannBoundary(leafView);
BoundaryPatch<GridView> const &frictionalBoundary = myFaces.lower;
BoundaryPatch<GridView> const &surface = myFaces.upper;
// Dirichlet Boundary
Dune::BitSetVector<dims> noNodes(leafVertexCount);
Dune::BitSetVector<dims> dirichletNodes(leafVertexCount);
for (size_t i = 0; i < leafVertexCount; ++i) {
if (myFaces.right.containsVertex(i))
dirichletNodes[i][0] = true;
if (myFaces.lower.containsVertex(i))
dirichletNodes[i][1] = true;
#if MY_DIM == 3
if (myFaces.front.containsVertex(i) || myFaces.back.containsVertex(i))
dirichletNodes[i][2] = true;
#endif
}
// Set up functions for time-dependent boundary conditions
using Function = Dune::VirtualFunction<double, double>;
Function const &velocityDirichletFunction = VelocityDirichletCondition();
Function const &neumannFunction = NeumannCondition();
MyAssembler const myAssembler(leafView);
MyBody<dims> const body(parset);
Matrices<Matrix> matrices;
myAssembler.assembleElasticity(body.getYoungModulus(),
body.getPoissonRatio(), matrices.elasticity);
myAssembler.assembleViscosity(body.getShearViscosityField(),
body.getBulkViscosityField(),
matrices.damping);
myAssembler.assembleMass(body.getDensityField(), matrices.mass);
ScalarMatrix relativeFrictionalBoundaryMass;
myAssembler.assembleFrictionalBoundaryMass(frictionalBoundary,
relativeFrictionalBoundaryMass);
relativeFrictionalBoundaryMass /= frictionalBoundary.area();
EnergyNorm<ScalarMatrix, ScalarVector> const stateEnergyNorm(
relativeFrictionalBoundaryMass);
// Assemble forces
Vector gravityFunctional;
myAssembler.assembleBodyForce(body.getGravityField(), gravityFunctional);
// Problem formulation: right-hand side
std::function<void(double, Vector &)> computeExternalForces =
[&](double _relativeTime, Vector &_ell) {
myAssembler.assembleNeumann(neumannBoundary, _ell, neumannFunction,
_relativeTime);
_ell += gravityFunctional;
};
using MyProgramState = ProgramState<Vector, ScalarVector>;
MyProgramState programState(leafVertexCount);
auto const firstRestart = parset.get<size_t>("io.restarts.first");
auto const restartSpacing = parset.get<size_t>("io.restarts.spacing");
auto const writeRestarts = parset.get<bool>("io.restarts.write");
auto const writeData = parset.get<bool>("io.data.write");
bool const handleRestarts = writeRestarts or firstRestart > 0;
auto dataFile =
writeData ? std::make_unique<HDF5::File>("output.h5") : nullptr;
auto restartFile = handleRestarts
? std::make_unique<HDF5::File>(
"restarts.h5",
writeRestarts ? HDF5::Access::READWRITE
: HDF5::Access::READONLY)
: nullptr;
auto restartIO = handleRestarts
? std::make_unique<RestartIO<MyProgramState>>(
*restartFile, leafVertexCount)
: nullptr;
if (firstRestart > 0) // automatically adjusts the time and timestep
restartIO->read(firstRestart, programState);
else
programState.setupInitialConditions(parset, computeExternalForces,
matrices, myAssembler, dirichletNodes,
noNodes, frictionalBoundary, body);
MyGlobalFrictionData<LocalVector> frictionInfo(
parset.sub("boundary.friction"), weakPatch);
auto myGlobalFriction = myAssembler.assembleFrictionNonlinearity(
parset.get<Config::FrictionModel>("boundary.friction.frictionModel"),
frictionalBoundary, frictionInfo, programState.weightedNormalStress);
myGlobalFriction->updateAlpha(programState.alpha);
Vector vertexCoordinates(leafVertexCount);
{
Dune::MultipleCodimMultipleGeomTypeMapper<
GridView, Dune::MCMGVertexLayout> const vertexMapper(leafView);
for (auto &&v : vertices(leafView))
vertexCoordinates[vertexMapper.index(v)] = geoToPoint(v.geometry());
}
using MyVertexBasis = typename MyAssembler::VertexBasis;
auto dataWriter =
writeData ? std::make_unique<
HDF5Writer<MyProgramState, MyVertexBasis, GridView>>(
*dataFile, vertexCoordinates, myAssembler.vertexBasis,
surface, frictionalBoundary, weakPatch)
: nullptr;
MyVTKWriter<MyVertexBasis, typename MyAssembler::CellBasis> const vtkWriter(
myAssembler.cellBasis, myAssembler.vertexBasis, "obs");
IterationRegister iterationCount;
auto const report = [&](bool initial = false) {
if (writeData) {
dataWriter->reportSolution(programState, *myGlobalFriction);
if (!initial)
dataWriter->reportIterations(programState, iterationCount);
dataFile->flush();
}
if (writeRestarts and !initial and
programState.timeStep % restartSpacing == 0) {
restartIO->write(programState);
restartFile->flush();
}
if (parset.get<bool>("io.printProgress"))
std::cout << "timeStep = " << std::setw(6) << programState.timeStep
<< ", time = " << std::setw(12) << programState.relativeTime
<< ", tau = " << std::setw(12) << programState.relativeTau
<< std::endl;
if (parset.get<bool>("io.vtk.write")) {
ScalarVector stress;
myAssembler.assembleVonMisesStress(body.getYoungModulus(),
body.getPoissonRatio(),
programState.u, stress);
vtkWriter.write(programState.timeStep, programState.u, programState.v,
programState.alpha, stress);
}
};
report(true);
// Set up TNNMG solver
using NonlinearFactory = SolverFactory<
dims,
MyBlockProblem<ConvexProblem<GlobalFriction<Matrix, Vector>, Matrix>>,
Grid>;
NonlinearFactory factory(parset.sub("solver.tnnmg"), *grid, dirichletNodes);
using MyUpdater = Updaters<RateUpdater<Vector, Matrix, Function, dims>,
StateUpdater<ScalarVector, Vector>>;
MyUpdater current(
initRateUpdater(parset.get<Config::scheme>("timeSteps.scheme"),
velocityDirichletFunction, dirichletNodes, matrices,
programState.u, programState.v, programState.a),
initStateUpdater<ScalarVector, Vector>(
parset.get<Config::stateModel>("boundary.friction.stateModel"),
programState.alpha, *frictionalBoundary.getVertices(),
parset.get<double>("boundary.friction.L"),
parset.get<double>("boundary.friction.V0")));
auto const refinementTolerance =
parset.get<double>("timeSteps.refinementTolerance");
auto const mustRefine = [&](MyUpdater &coarseUpdater,
MyUpdater &fineUpdater) {
ScalarVector coarseAlpha;
coarseUpdater.state_->extractAlpha(coarseAlpha);
ScalarVector fineAlpha;
fineUpdater.state_->extractAlpha(fineAlpha);
return stateEnergyNorm.diff(fineAlpha, coarseAlpha) > refinementTolerance;
};
std::signal(SIGXCPU, handleSignal);
std::signal(SIGINT, handleSignal);
std::signal(SIGTERM, handleSignal);
AdaptiveTimeStepper<NonlinearFactory, MyUpdater,
EnergyNorm<ScalarMatrix, ScalarVector>>
adaptiveTimeStepper(factory, parset, myGlobalFriction, current,
programState.relativeTime, programState.relativeTau,
computeExternalForces, stateEnergyNorm, mustRefine);
while (!adaptiveTimeStepper.reachedEnd()) {
programState.timeStep++;
iterationCount = adaptiveTimeStepper.advance();
programState.relativeTime = adaptiveTimeStepper.relativeTime_;
programState.relativeTau = adaptiveTimeStepper.relativeTau_;
current.rate_->extractDisplacement(programState.u);
current.rate_->extractVelocity(programState.v);
current.rate_->extractAcceleration(programState.a);
current.state_->extractAlpha(programState.alpha);
report();
if (terminationRequested) {
std::cerr << "Terminating prematurely" << std::endl;
break;
}
}
} catch (Dune::Exception &e) {
Dune::derr << "Dune reported error: " << e << std::endl;
} catch (std::exception &e) {
std::cerr << "Standard exception: " << e.what() << std::endl;
}
}
......@@ -2,19 +2,23 @@
gravity = 9.81 # [m/s^2]
[io]
data.write = true
printProgress = false
writeVTK = false
restarts.first = 0
restarts.spacing= 20
restarts.write = true
vtk.write = false
[problem]
finalTime = 1800 # [s]
finalTime = 1000 # [s]
[body]
bulkModulus = 1e5 # [Pa]
poissonRatio = 0.3 # [1] 0.2 - 0.3
bulkModulus = 0.5e5 # [Pa]
poissonRatio = 0.3 # [1]
[body.elastic]
density = 900 # [kg/m^3]
shearViscosity = 1e3 # [Pas] 0
bulkViscosity = 1e3 # [Pas] 0
shearViscosity = 1e3 # [Pas]
bulkViscosity = 1e3 # [Pas]
[body.viscoelastic]
density = 1000 # [kg/m^3]
shearViscosity = 1e4 # [Pas]
......@@ -22,49 +26,40 @@ bulkViscosity = 1e4 # [Pas]
[boundary.friction]
C = 10 # [Pa]
mu0 = 0.7 # [1]
mu0 = 0.7 # [ ]
V0 = 5e-5 # [m/s]
L = 2e-5 # [m] ?
initialLogState = 0 # [ ] ?
stateModel = Dieterich
L = 2.25e-5 # [m]
initialAlpha = 0 # [ ]
stateModel = AgeingLaw
frictionModel = Regularised
[boundary.friction.weakening]
a = 0.015 # [1] ?
b = 0.030 # [1] ?
a = 0.002 # [ ]
b = 0.017 # [ ]
[boundary.friction.strengthening]
a = 0.030 # [1] ?
b = 0.015 # [1] ?
a = 0.020 # [ ]
b = 0.005 # [ ]
[timeSteps]
number = 100000
scheme = newmark
[grid]
refinements = 4
[u0.solver]
tolerance = 1e-10
maximumIterations = 100000
verbosity = quiet
[a0.solver]
tolerance = 1e-10
maximumIterations = 100000
verbosity = quiet
[v.solver]
tolerance = 1e-10
maximumIterations = 100000
verbosity = quiet
[v.fpi]
tolerance = 1e-10
maximumIterations = 10000
relaxation = 0.5
requiredReduction = 0.5
lambda = 0.5
[solver.tnnmg.linear]
maxiumumIterations = 100000
tolerance = 1e-10
pre = 3
cycle = 1 # 1 = V, 2 = W, etc.
post = 3
......@@ -73,6 +68,3 @@ post = 3
pre = 1
multi = 5 # number of multigrid steps
post = 0
[localsolver]
steps = 100
#ifndef SRC_PROGRAM_STATE_HH
#define SRC_PROGRAM_STATE_HH
#include <dune/common/parametertree.hh>
#include <dune/fufem/boundarypatch.hh>
#include <dune/tnnmg/nonlinearities/zerononlinearity.hh>
#include <dune/tnnmg/problem-classes/blocknonlineartnnmgproblem.hh>
#include <dune/tectonic/body.hh>
#include "assemblers.hh"
#include "matrices.hh"
#include "spatial-solving/solverfactory.hh"
template <class VectorTEMPLATE, class ScalarVectorTEMPLATE> class ProgramState {
public:
using Vector = VectorTEMPLATE;
using ScalarVector = ScalarVectorTEMPLATE;
ProgramState(int leafVertexCount)
: u(leafVertexCount),
v(leafVertexCount),
a(leafVertexCount),
alpha(leafVertexCount),
weightedNormalStress(leafVertexCount) {}
// Set up initial conditions
template <class Matrix, class GridView>
void setupInitialConditions(
Dune::ParameterTree const &parset,
std::function<void(double, Vector &)> externalForces,
Matrices<Matrix> const matrices,
MyAssembler<GridView, Vector::block_type::dimension> const &myAssembler,
Dune::BitSetVector<Vector::block_type::dimension> const &dirichletNodes,
Dune::BitSetVector<Vector::block_type::dimension> const &noNodes,
BoundaryPatch<GridView> const &frictionalBoundary,
Body<Vector::block_type::dimension> const &body) {
using LocalVector = typename Vector::block_type;
using LocalMatrix = typename Matrix::block_type;
auto constexpr dims = LocalVector::dimension;
// Solving a linear problem with a multigrid solver
auto const solveLinearProblem = [&](
Dune::BitSetVector<dims> const &_dirichletNodes, Matrix const &_matrix,
Vector const &_rhs, Vector &_x,
Dune::ParameterTree const &_localParset) {
using LinearFactory = SolverFactory<
dims, BlockNonlinearTNNMGProblem<ConvexProblem<
ZeroNonlinearity<LocalVector, LocalMatrix>, Matrix>>,
typename GridView::Grid>;
ZeroNonlinearity<LocalVector, LocalMatrix> zeroNonlinearity;
LinearFactory factory(parset.sub("solver.tnnmg"), // FIXME
myAssembler.gridView.grid(), _dirichletNodes);
typename LinearFactory::ConvexProblem convexProblem(
1.0, _matrix, zeroNonlinearity, _rhs, _x);
typename LinearFactory::BlockProblem problem(parset, convexProblem);
auto multigridStep = factory.getStep();
multigridStep->setProblem(_x, problem);
EnergyNorm<Matrix, Vector> const norm(_matrix);
LoopSolver<Vector> solver(
multigridStep.get(), _localParset.get<size_t>("maximumIterations"),
_localParset.get<double>("tolerance"), &norm,
_localParset.get<Solver::VerbosityMode>("verbosity"),
false); // absolute error
solver.preprocess();
solver.solve();
};
timeStep = 0;
relativeTime = 0.0;
relativeTau = 1e-6;
Vector ell0(u.size());
externalForces(relativeTime, ell0);
// Initial velocity
v = 0.0;
// Initial displacement: Start from a situation of minimal stress,
// which is automatically attained in the case [v = 0 = a].
// Assuming dPhi(v = 0) = 0, we thus only have to solve Au = ell0
solveLinearProblem(dirichletNodes, matrices.elasticity, ell0, u,
parset.sub("u0.solver"));
// Initial acceleration: Computed in agreement with Ma = ell0 - Au
// (without Dirichlet constraints), again assuming dPhi(v = 0) = 0
Vector accelerationRHS = ell0;
Arithmetic::subtractProduct(accelerationRHS, matrices.elasticity, u);
solveLinearProblem(noNodes, matrices.mass, accelerationRHS, a,
parset.sub("a0.solver"));
// Initial state
alpha = parset.get<double>("boundary.friction.initialAlpha");
// Initial normal stress
myAssembler.assembleWeightedNormalStress(
frictionalBoundary, weightedNormalStress, body.getYoungModulus(),
body.getPoissonRatio(), u);
}
public:
Vector u;
Vector v;
Vector a;
ScalarVector alpha;
ScalarVector weightedNormalStress;
double relativeTime;
double relativeTau;
size_t timeStep;
};
#endif
class neumannCondition:
def __call__(self, relativeTime):
return 0
class velocityDirichletCondition:
def __call__(self, relativeTime):
if relativeTime <= 0.25:
factor = 4*relativeTime;
else:
factor = 1
return -5e-5 * factor
Functions = {
'neumannCondition' : neumannCondition(),
'velocityDirichletCondition' : velocityDirichletCondition()
}
#ifndef MY_GEOMETRY_HH
#define MY_GEOMETRY_HH
#include <dune/common/fassign.hh>
#include <dune/common/fvector.hh>
#include <dune/fufem/arithmetic.hh>
#ifdef HAVE_CAIROMM
#include <cairomm/context.h>
#include <cairomm/fontface.h>
#include <cairomm/surface.h>
#endif
namespace MyGeometry {
namespace {
using LocalVector = Dune::FieldVector<double, 2>;
// kludge because fieldvectors have no initialiser_list constructor, see
// https://dune-project.org/flyspray/index.php?do=details&task_id=1166
LocalVector generateVector(double x, double y) {
LocalVector tmp;
tmp <<= x, y;
return tmp;
}
double degreesToRadians(double degrees) {
return M_PI * degrees / 180;
};
LocalVector convexCombination(LocalVector const &x, LocalVector const &y) {
LocalVector ret;
ret = 0.0;
Arithmetic::addProduct(ret, 0.5, x);
Arithmetic::addProduct(ret, 0.5, y);
return ret;
}
double leftLeg = 1.00;
double rightLeg = 0.27;
double leftAngle = degreesToRadians(15);
double rightAngle = degreesToRadians(75);
double const depth = 0.10;
}
LocalVector const A = generateVector(0, 0);
LocalVector const B = generateVector(std::hypot(leftLeg, rightLeg), 0);
LocalVector const C = generateVector(leftLeg * std::sin(rightAngle),
leftLeg * std::sin(leftAngle));
LocalVector const Y = generateVector(0.35 / std::sin(rightAngle), 0);
LocalVector const X = generateVector(Y[0] - 0.20, 0);
LocalVector const Z =
generateVector(0.35 * std::sin(rightAngle), 0.35 * std::sin(leftAngle));
LocalVector const U = generateVector(Z[0] * X[0] / Y[0], Z[1] * X[0] / Y[0]);
LocalVector const K = generateVector(B[0] - 0.06 / std::sin(leftAngle), 0);
LocalVector const M = generateVector(B[0] - 0.06 * std::sin(leftAngle),
0.06 * std::sin(rightAngle));
LocalVector const G = convexCombination(A, X);
LocalVector const H = convexCombination(X, Y);
LocalVector const J = convexCombination(Y, B);
LocalVector const I = generateVector(Y[0] + G[0], 0);
LocalVector const zenith =
generateVector(-std::sin(leftAngle), std::cos(leftAngle));
LocalVector const rotatedZenith =
generateVector(-std::cos(leftAngle), -std::sin(leftAngle));
double verticalProjection(LocalVector const &);
double horizontalProjection(LocalVector const &);
void write();
void render();
}
#endif
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "mygrid.hh"
template <class Grid> std::shared_ptr<Grid> constructGrid() {
Dune::GridFactory<Grid> gridFactory;
Dune::FieldMatrix<double, 3, DIM> vertices;
vertices[0] = MyGeometry::A;
vertices[1] = MyGeometry::B;
vertices[2] = MyGeometry::C;
for (size_t i = 0; i < vertices.N(); ++i)
gridFactory.insertVertex(vertices[i]);
Dune::GeometryType cell;
cell.makeTriangle();
std::vector<std::vector<unsigned int>> simplices = { { 0, 1, 2 } };
// sanity-check choices of simplices
for (size_t i = 0; i < simplices.size(); ++i) {
Dune::FieldMatrix<double, DIM, DIM> check;
for (size_t j = 0; j < DIM; ++j)
check[j] = vertices[simplices[i][j + 1]] - vertices[simplices[i][j]];
assert(check.determinant() > 0);
gridFactory.insertElement(cell, simplices[i]);
}
return std::shared_ptr<Grid>(gridFactory.createGrid());
}
template <class GridView>
MyFaces<GridView>::MyFaces(GridView const &gridView)
: lower(gridView), right(gridView) {
using Grid = typename GridView::Grid;
using LevelGridView = typename Grid::LevelGridView;
LevelGridView const rootView = gridView.grid().levelView(0);
lower.insertFacesByProperty([&](
typename Grid::LeafGridView::Intersection const &in) {
return isClose(0, in.geometry().center()[1]);
});
BoundaryPatch<LevelGridView> upperRoot(rootView);
upperRoot.insertFacesByProperty([&](
typename LevelGridView::Intersection const &in) {
auto const geometry = in.geometry();
auto const range = boost::irange(0, geometry.corners());
return boost::algorithm::all_of(range, [&](int i) {
auto const &co = geometry.corner(i);
return (isClose(co[1], MyGeometry::A[1]) &&
isClose(co[0], MyGeometry::A[0])) ||
(isClose(co[1], MyGeometry::C[1]) &&
isClose(co[0], MyGeometry::C[0]));
});
});
BoundaryPatchProlongator<Grid>::prolong(upperRoot, upper);
BoundaryPatch<LevelGridView> rightRoot(rootView);
rightRoot.insertFacesByProperty([&](
typename LevelGridView::Intersection const &in) {
auto const geometry = in.geometry();
auto const range = boost::irange(0, geometry.corners());
return boost::algorithm::all_of(range, [&](int i) {
auto const &co = geometry.corner(i);
return (isClose(co[1], MyGeometry::C[1]) &&
isClose(co[0], MyGeometry::C[0])) ||
(isClose(co[1], MyGeometry::B[1]) &&
isClose(co[0], MyGeometry::B[0]));
});
});
BoundaryPatchProlongator<Grid>::prolong(rightRoot, right);
}
#include "mygrid_tmpl.cc"
#ifndef SRC_SAND_WEDGE_DATA_MYGRID_HH
#define SRC_SAND_WEDGE_DATA_MYGRID_HH
#include <boost/range/irange.hpp>
#include <boost/algorithm/cxx11/all_of.hpp>
#include <dune/common/fmatrix.hh>
#include <dune/grid/common/gridfactory.hh>
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#include <dune/fufem/boundarypatch.hh>
#pragma clang diagnostic pop
#include <dune/fufem/boundarypatchprolongator.hh>
#include "mygeometry.hh"
template <class Grid> std::shared_ptr<Grid> constructGrid();
template <class GridView> struct MyFaces {
BoundaryPatch<GridView> lower;
BoundaryPatch<GridView> right;
BoundaryPatch<GridView> upper;
MyFaces(GridView const &gridView);
private:
bool isClose(double a, double b) {
return std::abs(a - b) < 1e-14;
};
};
#endif
#ifndef DIM
#error DIM unset
#endif
#include "explicitgrid.hh"
template std::shared_ptr<Grid> constructGrid();
template struct MyFaces<GridView>;
#ifndef SRC_SAND_WEDGE_DATA_PATCHFUNCTION_HH
#define SRC_SAND_WEDGE_DATA_PATCHFUNCTION_HH
#include <dune/common/function.hh>
#include <dune/common/fvector.hh>
#include <dune/common/parametertree.hh>
class PatchFunction
: public Dune::VirtualFunction<Dune::FieldVector<double, 2>,
Dune::FieldVector<double, 1>> {
private:
bool static isBetween(double x, double lower, double upper) {
return lower <= x and x <= upper;
}
bool static isClose(double a, double b) {
return std::abs(a - b) < 1e-14;
};
bool insideRegion2(Dune::FieldVector<double, 2> const &z) const {
assert(isClose(0, z[1]));
return isBetween(z[0], _X[0], _Y[0]);
}
Dune::FieldVector<double, 2> const &_X;
Dune::FieldVector<double, 2> const &_Y;
double const _v1;
double const _v2;
public:
PatchFunction(double v1, double v2)
: _X(MyGeometry::X), _Y(MyGeometry::Y), _v1(v1), _v2(v2) {}
void evaluate(Dune::FieldVector<double, 2> const &x,
Dune::FieldVector<double, 1> &y) const {
y = insideRegion2(x) ? _v2 : _v1;
}
};
#endif