Skip to content
Snippets Groups Projects
Commit e55af7a3 authored by Elias Pipping's avatar Elias Pipping
Browse files

[Cleanup] Store only the necessary DOFs

parent 4b154528
No related branches found
No related tags found
No related merge requests found
#ifndef DUNE_TECTONIC_GEOCOORDINATE_HH
#define DUNE_TECTONIC_GEOCOORDINATE_HH
// tiny helper to make a common piece of code pleasanter to read
template <class Geometry>
typename Geometry::GlobalCoordinate geoToPoint(Geometry geo) {
assert(geo.corners() == 1);
return geo.corner(0);
}
#endif
...@@ -22,7 +22,7 @@ template <class Matrix, class Vector> class GlobalFriction { ...@@ -22,7 +22,7 @@ template <class Matrix, class Vector> class GlobalFriction {
using LocalMatrix = typename Matrix::block_type; using LocalMatrix = typename Matrix::block_type;
using LocalVectorType = typename Vector::block_type; using LocalVectorType = typename Vector::block_type;
size_t static const block_size = LocalVectorType::dimension; size_t static const block_size = LocalVectorType::dimension;
using Friction = LocalFriction<block_size>; using LocalNonlinearity = LocalFriction<block_size>;
double operator()(Vector const &x) const { double operator()(Vector const &x) const {
double tmp = 0; double tmp = 0;
...@@ -35,7 +35,7 @@ template <class Matrix, class Vector> class GlobalFriction { ...@@ -35,7 +35,7 @@ template <class Matrix, class Vector> class GlobalFriction {
/* /*
Return a restriction of the outer function to the i'th node. Return a restriction of the outer function to the i'th node.
*/ */
Friction const virtual &restriction(size_t i) const = 0; LocalNonlinearity const virtual &restriction(size_t i) const = 0;
void addHessian(Vector const &v, Matrix &hessian) const { void addHessian(Vector const &v, Matrix &hessian) const {
for (size_t i = 0; i < v.size(); ++i) for (size_t i = 0; i < v.size(); ++i)
......
...@@ -10,14 +10,16 @@ ...@@ -10,14 +10,16 @@
#include <dune/istl/bcrsmatrix.hh> #include <dune/istl/bcrsmatrix.hh>
#include <dune/istl/bvector.hh> #include <dune/istl/bvector.hh>
#include <dune/tectonic/geocoordinate.hh>
#include <dune/tectonic/globalfrictiondata.hh> #include <dune/tectonic/globalfrictiondata.hh>
#include <dune/tectonic/globalfriction.hh> #include <dune/tectonic/globalfriction.hh>
#include <dune/tectonic/index-in-sorted-range.hh>
template <class Matrix, class Vector, class ScalarFriction, class GridView> template <class Matrix, class Vector, class ScalarFriction, class GridView>
class GlobalRateStateFriction : public GlobalFriction<Matrix, Vector> { class GlobalRateStateFriction : public GlobalFriction<Matrix, Vector> {
public: public:
using GlobalFriction<Matrix, Vector>::block_size; using GlobalFriction<Matrix, Vector>::block_size;
using typename GlobalFriction<Matrix, Vector>::Friction; using typename GlobalFriction<Matrix, Vector>::LocalNonlinearity;
private: private:
using typename GlobalFriction<Matrix, Vector>::ScalarVector; using typename GlobalFriction<Matrix, Vector>::ScalarVector;
...@@ -27,40 +29,43 @@ class GlobalRateStateFriction : public GlobalFriction<Matrix, Vector> { ...@@ -27,40 +29,43 @@ class GlobalRateStateFriction : public GlobalFriction<Matrix, Vector> {
GlobalFrictionData<block_size> const &frictionInfo, GlobalFrictionData<block_size> const &frictionInfo,
ScalarVector const &weights, ScalarVector const &weights,
ScalarVector const &weightedNormalStress) ScalarVector const &weightedNormalStress)
: restrictions(weightedNormalStress.size()) { : restrictions(), localToGlobal(), zeroFriction() {
auto zeroNonlinearity =
std::make_shared<Friction>(std::make_shared<ZeroFunction>());
auto const gridView = frictionalBoundary.gridView(); auto const gridView = frictionalBoundary.gridView();
Dune::MultipleCodimMultipleGeomTypeMapper< Dune::MultipleCodimMultipleGeomTypeMapper<
GridView, Dune::MCMGVertexLayout> const vertexMapper(gridView); GridView, Dune::MCMGVertexLayout> const vertexMapper(gridView);
for (auto it = gridView.template begin<block_size>(); for (auto it = gridView.template begin<block_size>();
it != gridView.template end<block_size>(); ++it) { it != gridView.template end<block_size>(); ++it) {
auto const i = vertexMapper.index(*it); auto const i = vertexMapper.index(*it);
auto const coordinate = it->geometry().corner(0);
if (not frictionalBoundary.containsVertex(i)) { if (not frictionalBoundary.containsVertex(i))
restrictions[i] = zeroNonlinearity;
continue; continue;
}
auto const fp = std::make_shared<ScalarFriction>( localToGlobal.emplace_back(i);
weights[i], weightedNormalStress[i], frictionInfo(coordinate)); restrictions.emplace_back(weights[i], weightedNormalStress[i],
restrictions[i] = std::make_shared<Friction>(fp); frictionInfo(geoToPoint(it->geometry())));
} }
assert(restrictions.size() == frictionalBoundary.numVertices());
assert(localToGlobal.size() == frictionalBoundary.numVertices());
} }
void updateAlpha(ScalarVector const &alpha) override { void updateAlpha(ScalarVector const &alpha) override {
for (size_t i = 0; i < restrictions.size(); ++i) for (size_t j = 0; j < restrictions.size(); ++j)
restrictions[i]->updateAlpha(alpha[i]); restrictions[j].updateAlpha(alpha[localToGlobal[j]]);
} }
/* /*
Return a restriction of the outer function to the i'th node. Return a restriction of the outer function to the i'th node.
*/ */
Friction const &restriction(size_t i) const override { LocalNonlinearity const &restriction(size_t i) const override {
return *restrictions[i]; auto const index = indexInSortedRange(localToGlobal, i);
if (index == localToGlobal.size())
return zeroFriction;
return restrictions[index];
} }
private: private:
std::vector<std::shared_ptr<Friction>> restrictions; std::vector<WrappedScalarFriction<block_size, ScalarFriction>> restrictions;
std::vector<size_t> localToGlobal;
WrappedScalarFriction<block_size, ZeroFunction> const zeroFriction;
}; };
#endif #endif
#ifndef DUNE_TECTONIC_INDEX_IN_SORTED_RANGE_HH
#define DUNE_TECTONIC_INDEX_IN_SORTED_RANGE_HH
#include <algorithm>
// returns v.size() if value does not exist
template <typename T>
size_t indexInSortedRange(std::vector<T> const &v, T value) {
size_t const specialReturnValue = v.size();
auto const b = std::begin(v);
auto const e = std::end(v);
auto const lb = std::lower_bound(b, e, value);
if (lb == e) // all elements are strictly smaller
return specialReturnValue;
if (value < *lb) // value falls between to elements
return specialReturnValue;
return std::distance(b, lb);
}
#endif
...@@ -14,39 +14,59 @@ ...@@ -14,39 +14,59 @@
template <size_t dimension> class LocalFriction { template <size_t dimension> class LocalFriction {
public: public:
virtual ~LocalFriction() {}
using VectorType = Dune::FieldVector<double, dimension>; using VectorType = Dune::FieldVector<double, dimension>;
using MatrixType = Dune::FieldMatrix<double, dimension, dimension>; using MatrixType = Dune::FieldMatrix<double, dimension, dimension>;
explicit LocalFriction(std::shared_ptr<FrictionPotential> func) void virtual updateAlpha(double alpha) = 0;
: func(func) {} double virtual regularity(VectorType const &x) const = 0;
double virtual coefficientOfFriction(VectorType const &x) const = 0;
void virtual directionalSubDiff(VectorType const &x, VectorType const &v,
Dune::Solvers::Interval<double> &D) const = 0;
double operator()(VectorType const &x) const { void virtual addHessian(VectorType const &x, MatrixType &A) const = 0;
return func->evaluate(x.two_norm());
} void virtual addGradient(VectorType const &x, VectorType &y) const = 0;
void virtual directionalDomain(
VectorType const &, VectorType const &,
Dune::Solvers::Interval<double> &dom) const = 0;
};
template <size_t dimension, class ScalarFriction>
class WrappedScalarFriction : public LocalFriction<dimension> {
using VectorType = typename LocalFriction<dimension>::VectorType;
using MatrixType = typename LocalFriction<dimension>::MatrixType;
public:
template <typename... Args>
WrappedScalarFriction(Args... args)
: func_(args...) {}
void updateAlpha(double alpha) { func->updateAlpha(alpha); } void updateAlpha(double alpha) override { func_.updateAlpha(alpha); }
double regularity(VectorType const &x) const { double regularity(VectorType const &x) const override {
double const xnorm = x.two_norm(); double const xnorm = x.two_norm();
if (xnorm <= 0.0) if (xnorm <= 0.0)
return std::numeric_limits<double>::infinity(); return std::numeric_limits<double>::infinity();
return func->regularity(xnorm); return func_.regularity(xnorm);
} }
double coefficientOfFriction(VectorType const &x) const { double coefficientOfFriction(VectorType const &x) const override {
return func->coefficientOfFriction(x.two_norm()); return func_.coefficientOfFriction(x.two_norm());
} }
// directional subdifferential: at u on the line u + t*v // directional subdifferential: at u on the line u + t*v
// u and v are assumed to be non-zero // u and v are assumed to be non-zero
void directionalSubDiff(VectorType const &x, VectorType const &v, void directionalSubDiff(VectorType const &x, VectorType const &v,
Dune::Solvers::Interval<double> &D) const { Dune::Solvers::Interval<double> &D) const override {
double const xnorm = x.two_norm(); double const xnorm = x.two_norm();
if (xnorm <= 0.0) if (xnorm <= 0.0)
D[0] = D[1] = func->differential(0.0) * v.two_norm(); D[0] = D[1] = func_.differential(0.0) * v.two_norm();
else else
D[0] = D[1] = func->differential(xnorm) * (x * v) / xnorm; D[0] = D[1] = func_.differential(xnorm) * (x * v) / xnorm;
} }
/** Formula for the derivative: /** Formula for the derivative:
...@@ -65,14 +85,14 @@ template <size_t dimension> class LocalFriction { ...@@ -65,14 +85,14 @@ template <size_t dimension> class LocalFriction {
+ \frac {H'(|z|)}{|z|} \operatorname{id} + \frac {H'(|z|)}{|z|} \operatorname{id}
\f} \f}
*/ */
void addHessian(VectorType const &x, MatrixType &A) const { void addHessian(VectorType const &x, MatrixType &A) const override {
double const xnorm2 = x.two_norm2(); double const xnorm2 = x.two_norm2();
double const xnorm = std::sqrt(xnorm2); double const xnorm = std::sqrt(xnorm2);
if (xnorm2 <= 0.0) if (xnorm2 <= 0.0)
return; return;
double const H1 = func->differential(xnorm); double const H1 = func_.differential(xnorm);
double const H2 = func->second_deriv(xnorm); double const H2 = func_.second_deriv(xnorm);
double const tensorweight = (H2 - H1 / xnorm) / xnorm2; double const tensorweight = (H2 - H1 / xnorm) / xnorm2;
double const idweight = H1 / xnorm; double const idweight = H1 / xnorm;
...@@ -90,22 +110,22 @@ template <size_t dimension> class LocalFriction { ...@@ -90,22 +110,22 @@ template <size_t dimension> class LocalFriction {
} }
} }
void addGradient(VectorType const &x, VectorType &y) const { void addGradient(VectorType const &x, VectorType &y) const override {
double const xnorm = x.two_norm(); double const xnorm = x.two_norm();
if (std::isinf(func->regularity(xnorm))) if (std::isinf(func_.regularity(xnorm)))
return; return;
if (xnorm > 0.0) if (xnorm > 0.0)
Arithmetic::addProduct(y, func->differential(xnorm) / xnorm, x); Arithmetic::addProduct(y, func_.differential(xnorm) / xnorm, x);
} }
void directionalDomain(VectorType const &, VectorType const &, void directionalDomain(VectorType const &, VectorType const &,
Dune::Solvers::Interval<double> &dom) const { Dune::Solvers::Interval<double> &dom) const override {
dom[0] = -std::numeric_limits<double>::max(); dom[0] = -std::numeric_limits<double>::max();
dom[1] = std::numeric_limits<double>::max(); dom[1] = std::numeric_limits<double>::max();
} }
private: private:
std::shared_ptr<FrictionPotential> const func; ScalarFriction func_;
}; };
#endif #endif
...@@ -256,7 +256,8 @@ class MyBlockProblem<ConvexProblem>::IterateObject { ...@@ -256,7 +256,8 @@ class MyBlockProblem<ConvexProblem>::IterateObject {
else else
ui[j] = 0; ui[j] = 0;
QuadraticEnergy<typename ConvexProblem::NonlinearityType::Friction> QuadraticEnergy<
typename ConvexProblem::NonlinearityType::LocalNonlinearity>
localJ(maxEigenvalues_[m], localb, problem.phi.restriction(m)); localJ(maxEigenvalues_[m], localb, problem.phi.restriction(m));
minimise(localJ, ui, bisection_); minimise(localJ, ui, bisection_);
} }
......
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#include <dune/solvers/solvers/solver.hh> #include <dune/solvers/solvers/solver.hh>
#include <dune/tnnmg/problem-classes/convexproblem.hh> #include <dune/tnnmg/problem-classes/convexproblem.hh>
#include <dune/tectonic/geocoordinate.hh>
#include <dune/tectonic/myblockproblem.hh> #include <dune/tectonic/myblockproblem.hh>
#include <dune/tectonic/globalfriction.hh> #include <dune/tectonic/globalfriction.hh>
#include <dune/fufem/hdf5/hdf5file.hh> #include <dune/fufem/hdf5/hdf5file.hh>
...@@ -236,11 +237,8 @@ int main(int argc, char *argv[]) { ...@@ -236,11 +237,8 @@ int main(int argc, char *argv[]) {
{ {
Dune::MultipleCodimMultipleGeomTypeMapper< Dune::MultipleCodimMultipleGeomTypeMapper<
GridView, Dune::MCMGVertexLayout> const vertexMapper(leafView); GridView, Dune::MCMGVertexLayout> const vertexMapper(leafView);
for (auto it = leafView.begin<dims>(); it != leafView.end<dims>(); ++it) { for (auto it = leafView.begin<dims>(); it != leafView.end<dims>(); ++it)
auto const geometry = it->geometry(); vertexCoordinates[vertexMapper.index(*it)] = geoToPoint(it->geometry());
assert(geometry.corners() == 1);
vertexCoordinates[vertexMapper.index(*it)] = geometry.corner(0);
}
} }
HDF5Writer<ProgramState<Vector, ScalarVector>, HDF5Writer<ProgramState<Vector, ScalarVector>,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment