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 1213 additions and 852 deletions
......@@ -10,75 +10,61 @@ namespace {
using LocalVector2D = Dune::FieldVector<double, 2>;
using LocalMatrix2D = Dune::FieldMatrix<double, 2, 2>;
using LocalVector = Dune::FieldVector<double, DIM>;
// kludge because fieldvectors have no initialiser_list constructor, see
// https://dune-project.org/flyspray/index.php?do=details&task_id=1166
LocalVector2D createVector(double x, double y) {
LocalVector2D ret{ 0 };
ret[0] = x;
ret[1] = y;
return ret;
}
LocalMatrix2D createMatrix(double a11, double a12, double a21, double a22) {
LocalMatrix2D ret{ 0 };
ret[0][0] = a11;
ret[0][1] = a12;
ret[1][0] = a21;
ret[1][1] = a22;
return ret;
}
using LocalVector = Dune::FieldVector<double, MY_DIM>;
}
namespace reference {
double const rightLeg = 0.27;
double const leftLeg = 1.00;
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; // Height of the viscous bottom layer
double const weakLen = 0.20; // Length of the weak zone
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 = createVector(0, 0);
LocalVector2D const B = createVector(leftLeg, -rightLeg);
LocalVector2D const C = createVector(leftLeg, 0);
LocalVector2D const A = {0, 0};
LocalVector2D const B = {leftLeg, -rightLeg};
LocalVector2D const C = {leftLeg, 0};
LocalVector2D const Z = createVector(0.35, 0);
LocalVector2D const Y = createVector(0.35, -0.35 / leftLeg * rightLeg);
LocalVector2D const X = createVector(Y[0] - weakLen * std::cos(leftAngle),
Y[1] + weakLen * std::sin(leftAngle));
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 = createVector(X[0], 0);
LocalVector2D const U = {X[0], 0};
LocalVector2D const K =
createVector(B[0] - leftLeg * viscoHeight / rightLeg, B[1] + viscoHeight);
LocalVector2D const M = createVector(B[0], B[1] + viscoHeight);
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 = createVector(Y[0] + G[0], Y[1] + G[1]);
LocalVector2D const I = {Y[0] + G[0], Y[1] + G[1]};
LocalVector2D const zenith = createVector(0, 1);
LocalVector2D const rotatedZenith = createVector(-1, 0);
LocalVector2D const zenith = {0, 1};
LocalMatrix2D const rotation =
createMatrix(std::cos(leftAngle), -std::sin(leftAngle),
std::sin(leftAngle), std::cos(leftAngle));
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 };
LocalVector ret(0);
ret[0] = ret2D[0];
ret[1] = ret2D[1];
return ret;
}
}
double const depth = 0.10;
double const lengthScale = reference::s;
double const depth = 0.60 * lengthScale;
LocalVector const A = rotate(reference::A);
LocalVector const B = rotate(reference::B);
......@@ -95,11 +81,6 @@ LocalVector const Y = rotate(reference::Y);
LocalVector const Z = rotate(reference::Z);
LocalVector const zenith = rotate(reference::zenith);
LocalVector const rotatedZenith =
rotate(reference::rotatedZenith); // FIXME: misnomer
double verticalProjection(LocalVector const &);
double horizontalProjection(LocalVector const &);
void write();
......
#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_;
......
......@@ -2,165 +2,130 @@
#include "config.h"
#endif
#include <dune/fufem/geometry/polyhedrondistance.hh>
#include "mygrid.hh"
#include "midpoint.hh"
#include "../diameter.hh"
class SimplexManager {
public:
using SimplexList = std::vector<std::vector<unsigned int>>;
#if DIM == 3
SimplexManager(unsigned int shift) : shift_(shift) {}
#if MY_DIM == 3
SimplexManager::SimplexManager(unsigned int shift) : shift_(shift) {}
#endif
void addFromVertices(unsigned int U, unsigned int V, unsigned int W) {
#if DIM == 3
unsigned int const U2 = U + shift_;
unsigned int const V2 = V + shift_;
unsigned int const W2 = W + shift_;
// back-to-front, back-to-front, back-to-front
simplices_.push_back({ U, V, W, U2 });
simplices_.push_back({ V, V2, W2, U2 });
simplices_.push_back({ W, W2, U2, V });
// 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_;
// back-to-front, front-to-back, back-to-front would be
/*
simplices_.push_back({ U, V, W, U2 });
simplices_.push_back({ V, V2, W, U2 });
simplices_.push_back({ V2, W2, U2, W });
*/
simplices_.push_back({ V, V2, W2, U2 });
simplices_.push_back({ W, W2, U2, V });
#else
simplices_.push_back({ U, V, W });
simplices_.push_back({ U, V, W });
#endif
}
SimplexList const &getSimplices() { return simplices_; }
}
private:
SimplexList simplices_;
// 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_;
#if DIM == 3
unsigned int const 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
};
template <class Grid> class GridConstructor {
public:
GridConstructor() {
auto const &A = MyGeometry::A;
auto const &B = MyGeometry::B;
auto const &C = MyGeometry::C;
}
auto const AB = midPoint(A, B);
auto const AC = midPoint(A, C);
auto const BC = midPoint(B, C);
auto SimplexManager::getSimplices() -> SimplexList const & {
return simplices_;
}
auto const AAB = midPoint(A, AB);
auto const AAC = midPoint(A, AC);
auto const ABB = midPoint(AB, B);
auto const ABC = midPoint(AB, C); // the interiour point
auto const ACC = midPoint(AC, C);
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 = 11;
unsigned int const vc = 3;
#if DIM == 3
Dune::FieldMatrix<double, 2 * vc, DIM> vertices;
#if MY_DIM == 3
Dune::FieldMatrix<double, 2 * vc, MY_DIM> vertices;
#else
Dune::FieldMatrix<double, vc, DIM> vertices;
Dune::FieldMatrix<double, vc, MY_DIM> vertices;
#endif
for (size_t i = 0; i < 2; ++i) {
size_t k = 0;
vertices[k++][i] = A[i];
vertices[k++][i] = AAB[i];
vertices[k++][i] = AB[i];
vertices[k++][i] = ABB[i];
vertices[k++][i] = B[i];
vertices[k++][i] = AAC[i];
vertices[k++][i] = AC[i];
vertices[k++][i] = ABC[i];
vertices[k++][i] = BC[i];
vertices[k++][i] = ACC[i];
vertices[k++][i] = C[i];
assert(k == vc);
#if DIM == 3
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] = AAB[i];
vertices[k++][i] = AB[i];
vertices[k++][i] = ABB[i];
vertices[k++][i] = B[i];
vertices[k++][i] = AAC[i];
vertices[k++][i] = AC[i];
vertices[k++][i] = ABC[i];
vertices[k++][i] = BC[i];
vertices[k++][i] = ACC[i];
vertices[k++][i] = C[i];
assert(k == 2 * vc);
#endif
assert(k == j * vc);
}
}
#if 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;
}
#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]);
for (size_t i = 0; i < vertices.N(); ++i)
gridFactory.insertVertex(vertices[i]);
Dune::GeometryType cell;
#if DIM == 3
cell.makeTetrahedron();
Dune::GeometryType cell;
#if MY_DIM == 3
cell.makeTetrahedron();
#else
cell.makeTriangle();
cell.makeTriangle();
#endif
#if DIM == 3
SimplexManager sm(vc);
#if MY_DIM == 3
SimplexManager sm(vc);
#else
SimplexManager sm;
SimplexManager sm;
#endif
sm.addFromVertices(1, 5, 0);
sm.addFromVertices(1, 6, 5);
sm.addFromVertices(2, 6, 1);
sm.addFromVertices(7, 6, 2);
sm.addFromVertices(7, 2, 3);
sm.addFromVertices(7, 3, 8);
sm.addFromVertices(7, 8, 10);
sm.addFromVertices(7, 10, 9);
sm.addFromVertices(7, 9, 6);
sm.addFromVertices(8, 3, 4);
auto const &simplices = sm.getSimplices();
// 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]);
}
}
std::shared_ptr<Grid> getGrid() {
return std::shared_ptr<Grid>(gridFactory.createGrid());
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 GridView>
MyFaces<GridView> constructFaces(GridView const &gridView) {
return MyFaces<GridView>(gridView);
}
template <class Grid> std::shared_ptr<Grid> GridConstructor<Grid>::getGrid() {
return std::shared_ptr<Grid>(gridFactory.createGrid());
}
private:
Dune::GridFactory<Grid> gridFactory;
};
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 isClose((b[0] - a[0]) * (c[1] - a[1]), (b[1] - a[1]) * (c[0] - a[0]));
return isClose2((b[0] - a[0]) * (c[1] - a[1]), (b[1] - a[1]) * (c[0] - a[0]));
}
template <class GridView>
......@@ -170,9 +135,11 @@ bool MyFaces<GridView>::xyBoxed(Vector const &v1, Vector const &v2,
auto const minmax0 = std::minmax(v1[0], v2[0]);
auto const minmax1 = std::minmax(v1[1], v2[1]);
if (minmax0.first - 1e-14 > x[0] or x[0] > minmax0.second + 1e-14)
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 > x[1] or x[1] > minmax1.second + 1e-14)
if (minmax1.first - 1e-14 * MyGeometry::lengthScale > x[1] or
x[1] > minmax1.second + 1e-14 * MyGeometry::lengthScale)
return false;
return true;
......@@ -188,7 +155,7 @@ bool MyFaces<GridView>::xyBetween(Vector const &v1, Vector const &v2,
template <class GridView>
MyFaces<GridView>::MyFaces(GridView const &gridView)
:
#if DIM == 3
#if MY_DIM == 3
lower(gridView),
right(gridView),
upper(gridView),
......@@ -200,13 +167,12 @@ MyFaces<GridView>::MyFaces(GridView const &gridView)
upper(gridView)
#endif
{
using Grid = typename GridView::Grid;
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 DIM == 3
#if MY_DIM == 3
front.insertFacesByProperty([&](typename GridView::Intersection const &in) {
return isClose(MyGeometry::depth / 2.0, in.geometry().center()[2]);
});
......@@ -225,4 +191,37 @@ MyFaces<GridView>::MyFaces(GridView const &gridView)
});
}
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_SAND_WEDGE_DATA_MYGRID_HH
#define SRC_SAND_WEDGE_DATA_MYGRID_HH
#include <boost/range/irange.hpp>
#include <boost/algorithm/cxx11/all_of.hpp>
#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>
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#include <dune/fufem/boundarypatch.hh>
#pragma clang diagnostic pop
#include <dune/fufem/geometry/convexpolyhedron.hh>
#include "mygeometry.hh"
......@@ -19,7 +14,7 @@ template <class GridView> struct MyFaces {
BoundaryPatch<GridView> right;
BoundaryPatch<GridView> upper;
#if DIM == 3
#if MY_DIM == 3
BoundaryPatch<GridView> front;
BoundaryPatch<GridView> back;
#endif
......@@ -28,7 +23,12 @@ template <class GridView> struct MyFaces {
private:
bool isClose(double a, double b) {
return std::abs(a - b) < 1e-14;
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>
......@@ -40,4 +40,45 @@ template <class GridView> struct MyFaces {
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, DIM>,
class SegmentedFunction
: public Dune::VirtualFunction<Dune::FieldVector<double, MY_DIM>,
Dune::FieldVector<double, 1>> {
private:
bool liesBelow(Dune::FieldVector<double, DIM> const &x,
Dune::FieldVector<double, DIM> const &y,
Dune::FieldVector<double, DIM> 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, DIM> 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, DIM> const &_K;
Dune::FieldVector<double, DIM> 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, DIM> 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,50 +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] ?
initialAlpha = 0.916290731874155 # [ ] ?
L = 2.25e-5 # [m]
initialAlpha = 0 # [ ]
stateModel = AgeingLaw
frictionModel = Truncated
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]
refinementTolerance = 1e-5
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
lambda = 0.5
[solver.tnnmg.linear]
maxiumumIterations = 100000
tolerance = 1e-10
pre = 3
cycle = 1 # 1 = V, 2 = W, etc.
post = 3
......
#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
import math
class neumannCondition:
def __call__(self, relativeTime):
return 0
class velocityDirichletCondition:
def __call__(self, relativeTime):
finalVelocity = -5e-5
if relativeTime <= 0.1:
return finalVelocity * ( 1.0 - math.cos(relativeTime * math.pi / 0.1) ) / 2.0
return finalVelocity
Functions = {
'neumannCondition' : neumannCondition(),
'velocityDirichletCondition' : velocityDirichletCondition()
}
#ifndef DIM
#error DIM unset
#endif
#include "explicitgrid.hh"
template class GridConstructor<Grid>;
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, DIM>,
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, DIM> const &z) const {
assert(isClose(0, z[1]));
return isBetween(z[0], _X[0], _Y[0]);
}
Dune::FieldVector<double, DIM> const &_X;
Dune::FieldVector<double, DIM> 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, DIM> const &x,
Dune::FieldVector<double, 1> &y) const {
y = insideRegion2(x) ? _v2 : _v1;
}
};
#endif
#ifndef SRC_SPECIAL_WRITER_HH
#define SRC_SPECIAL_WRITER_HH
#include <fstream>
#include <utility>
#include <dune/common/fvector.hh>
#include <dune/grid/utility/hierarchicsearch.hh>
#include <dune/fufem/functions/virtualgridfunction.hh>
#include "mygeometry.hh"
template <class GridView, int dimension> class SpecialWriter {
using LocalVector = Dune::FieldVector<double, dimension>;
using Element = typename GridView::Grid::template Codim<0>::Entity;
using ElementPointer =
typename GridView::Grid::template Codim<0>::EntityPointer;
void writeHorizontal(LocalVector const &v) {
writer_ << MyGeometry::horizontalProjection(v) << " ";
}
void writeVertical(LocalVector const &v) {
writer_ << MyGeometry::verticalProjection(v) << " ";
}
std::pair<ElementPointer, LocalVector> globalToLocal(LocalVector const &x)
const {
auto const element = hsearch_.findEntity(x);
return std::pair<ElementPointer, LocalVector>(element,
element->geometry().local(x));
}
std::fstream writer_;
Dune::HierarchicSearch<typename GridView::Grid, GridView> const hsearch_;
std::pair<ElementPointer, LocalVector> const G;
std::pair<ElementPointer, LocalVector> const H;
std::pair<ElementPointer, LocalVector> const J;
std::pair<ElementPointer, LocalVector> const I;
std::pair<ElementPointer, LocalVector> const U;
std::pair<ElementPointer, LocalVector> const Z;
public:
SpecialWriter(std::string filename, GridView const &gridView)
: writer_(filename, std::fstream::out),
hsearch_(gridView.grid(), gridView),
G(globalToLocal(MyGeometry::G)),
H(globalToLocal(MyGeometry::H)),
J(globalToLocal(MyGeometry::J)),
I(globalToLocal(MyGeometry::I)),
U(globalToLocal(MyGeometry::U)),
Z(globalToLocal(MyGeometry::Z)) {
writer_ << "Gh Hh Jh Ih Uv Uh Zv Zh" << std::endl;
}
void write(VirtualGridFunction<typename GridView::Grid, LocalVector> const &
specialField) {
LocalVector value;
specialField.evaluateLocal(*G.first, G.second, value);
writeHorizontal(value);
specialField.evaluateLocal(*H.first, H.second, value);
writeHorizontal(value);
specialField.evaluateLocal(*J.first, J.second, value);
writeHorizontal(value);
specialField.evaluateLocal(*I.first, I.second, value);
writeHorizontal(value);
specialField.evaluateLocal(*U.first, U.second, value);
writeVertical(value);
writeHorizontal(value);
specialField.evaluateLocal(*Z.first, Z.second, value);
writeVertical(value);
writeHorizontal(value);
writer_ << std::endl;
}
};
#endif
This diff is collapsed.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <dune/common/exceptions.hh>
#include <dune/solvers/common/arithmetic.hh>
#include <dune/solvers/norms/energynorm.hh>
#include <dune/solvers/solvers/loopsolver.hh>
#include "../enums.hh"
#include "../enumparser.hh"
#include "fixedpointiterator.hh"
void FixedPointIterationCounter::operator+=(
FixedPointIterationCounter const &other) {
iterations += other.iterations;
multigridIterations += other.multigridIterations;
}
template <class Factory, class Updaters, class ErrorNorm>
FixedPointIterator<Factory, Updaters, ErrorNorm>::FixedPointIterator(
Factory &factory, Dune::ParameterTree const &parset,
std::shared_ptr<Nonlinearity> globalFriction, ErrorNorm const &errorNorm)
: step_(factory.getStep()),
parset_(parset),
globalFriction_(globalFriction),
fixedPointMaxIterations_(parset.get<size_t>("v.fpi.maximumIterations")),
fixedPointTolerance_(parset.get<double>("v.fpi.tolerance")),
lambda_(parset.get<double>("v.fpi.lambda")),
velocityMaxIterations_(parset.get<size_t>("v.solver.maximumIterations")),
velocityTolerance_(parset.get<double>("v.solver.tolerance")),
verbosity_(parset.get<Solver::VerbosityMode>("v.solver.verbosity")),
errorNorm_(errorNorm) {}
template <class Factory, class Updaters, class ErrorNorm>
FixedPointIterationCounter
FixedPointIterator<Factory, Updaters, ErrorNorm>::run(
Updaters updaters, Matrix const &velocityMatrix, Vector const &velocityRHS,
Vector &velocityIterate) {
EnergyNorm<Matrix, Vector> energyNorm(velocityMatrix);
LoopSolver<Vector> velocityProblemSolver(step_.get(), velocityMaxIterations_,
velocityTolerance_, &energyNorm,
verbosity_, false); // absolute error
size_t fixedPointIteration;
size_t multigridIterations = 0;
ScalarVector alpha;
updaters.state_->extractAlpha(alpha);
for (fixedPointIteration = 0; fixedPointIteration < fixedPointMaxIterations_;
++fixedPointIteration) {
// solve a velocity problem
globalFriction_->updateAlpha(alpha);
ConvexProblem convexProblem(1.0, velocityMatrix, *globalFriction_,
velocityRHS, velocityIterate);
BlockProblem velocityProblem(parset_, convexProblem);
step_->setProblem(velocityIterate, velocityProblem);
velocityProblemSolver.preprocess();
velocityProblemSolver.solve();
multigridIterations += velocityProblemSolver.getResult().iterations;
Vector v_m;
updaters.rate_->extractOldVelocity(v_m);
v_m *= 1.0 - lambda_;
Arithmetic::addProduct(v_m, lambda_, velocityIterate);
// solve a state problem
updaters.state_->solve(v_m);
ScalarVector newAlpha;
updaters.state_->extractAlpha(newAlpha);
if (lambda_ < 1e-12 or
errorNorm_.diff(alpha, newAlpha) < fixedPointTolerance_) {
fixedPointIteration++;
break;
}
alpha = newAlpha;
}
if (fixedPointIteration == fixedPointMaxIterations_)
DUNE_THROW(Dune::Exception, "FPI failed to converge");
updaters.rate_->postProcess(velocityIterate);
// Cannot use return { fixedPointIteration, multigridIterations };
// with gcc 4.9.2, see also http://stackoverflow.com/a/37777814/179927
FixedPointIterationCounter ret;
ret.iterations = fixedPointIteration;
ret.multigridIterations = multigridIterations;
return ret;
}
std::ostream &operator<<(std::ostream &stream,
FixedPointIterationCounter const &fpic) {
return stream << "(" << fpic.iterations << "," << fpic.multigridIterations
<< ")";
}
#include "fixedpointiterator_tmpl.cc"
#ifndef SRC_SPATIAL_SOLVING_FIXEDPOINTITERATOR_HH
#define SRC_SPATIAL_SOLVING_FIXEDPOINTITERATOR_HH
#include <memory>
#include <dune/common/parametertree.hh>
#include <dune/solvers/norms/norm.hh>
#include <dune/solvers/solvers/solver.hh>
struct FixedPointIterationCounter {
size_t iterations = 0;
size_t multigridIterations = 0;
void operator+=(FixedPointIterationCounter const &other);
};
std::ostream &operator<<(std::ostream &stream,
FixedPointIterationCounter const &fpic);
template <class Factory, class Updaters, class ErrorNorm>
class FixedPointIterator {
using ScalarVector = typename Updaters::StateUpdater::ScalarVector;
using Vector = typename Factory::Vector;
using Matrix = typename Factory::Matrix;
using ConvexProblem = typename Factory::ConvexProblem;
using BlockProblem = typename Factory::BlockProblem;
using Nonlinearity = typename ConvexProblem::NonlinearityType;
public:
FixedPointIterator(Factory &factory, Dune::ParameterTree const &parset,
std::shared_ptr<Nonlinearity> globalFriction,
ErrorNorm const &errorNorm_);
FixedPointIterationCounter run(Updaters updaters,
Matrix const &velocityMatrix,
Vector const &velocityRHS,
Vector &velocityIterate);
private:
std::shared_ptr<typename Factory::Step> step_;
Dune::ParameterTree const &parset_;
std::shared_ptr<Nonlinearity> globalFriction_;
size_t fixedPointMaxIterations_;
double fixedPointTolerance_;
double lambda_;
size_t velocityMaxIterations_;
double velocityTolerance_;
Solver::VerbosityMode verbosity_;
ErrorNorm const &errorNorm_;
};
#endif
#ifndef MY_DIM
#error MY_DIM unset
#endif
#include "../explicitgrid.hh"
#include "../explicitvectors.hh"
#include <dune/common/function.hh>
#include <dune/solvers/norms/energynorm.hh>
#include <dune/tnnmg/problem-classes/convexproblem.hh>
#include <dune/tectonic/globalfriction.hh>
#include <dune/tectonic/myblockproblem.hh>
#include "../time-stepping/rate/rateupdater.hh"
#include "../time-stepping/state/stateupdater.hh"
#include "../time-stepping/updaters.hh"
#include "solverfactory.hh"
using Function = Dune::VirtualFunction<double, double>;
using Factory = SolverFactory<
MY_DIM,
MyBlockProblem<ConvexProblem<GlobalFriction<Matrix, Vector>, Matrix>>,
Grid>;
using MyStateUpdater = StateUpdater<ScalarVector, Vector>;
using MyRateUpdater = RateUpdater<Vector, Matrix, Function, MY_DIM>;
using MyUpdaters = Updaters<MyRateUpdater, MyStateUpdater>;
using ErrorNorm = EnergyNorm<ScalarMatrix, ScalarVector>;
template class FixedPointIterator<Factory, MyUpdaters, ErrorNorm>;
......@@ -13,15 +13,16 @@
template <size_t dim, class BlockProblem, class Grid>
SolverFactory<dim, BlockProblem, Grid>::SolverFactory(
Dune::ParameterTree const &parset, size_t refinements, Grid const &grid,
Dune::ParameterTree const &parset, Grid const &grid,
Dune::BitSetVector<dim> const &ignoreNodes)
: baseEnergyNorm(linearBaseSolverStep),
linearBaseSolver(&linearBaseSolverStep,
parset.get<size_t>("linear.maxiumumIterations"),
parset.get<double>("linear.tolerance"), &baseEnergyNorm,
Solver::QUIET),
transferOperators(refinements),
multigridStep(new Solver(linearIterationStep, nonlinearSmoother)) {
transferOperators(grid.maxLevel()),
multigridStep(
std::make_shared<Step>(linearIterationStep, nonlinearSmoother)) {
// linear iteration step
linearIterationStep.setMGType(parset.get<int>("linear.cycle"),
parset.get<int>("linear.pre"),
......@@ -47,12 +48,11 @@ template <size_t dim, class BlockProblem, class Grid>
SolverFactory<dim, BlockProblem, Grid>::~SolverFactory() {
for (auto &&x : transferOperators)
delete x;
delete multigridStep;
}
template <size_t dim, class BlockProblem, class Grid>
auto SolverFactory<dim, BlockProblem, Grid>::getSolver() -> Solver *{
auto SolverFactory<dim, BlockProblem, Grid>::getStep()
-> std::shared_ptr<Step> {
return multigridStep;
}
......