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
Commits on Source (62)
Showing
with 480 additions and 243 deletions
...@@ -17,7 +17,7 @@ include(DuneMacros) ...@@ -17,7 +17,7 @@ include(DuneMacros)
# start a dune project with information from dune.module # start a dune project with information from dune.module
dune_project() dune_project()
dune_enable_all_packages()
find_package(HDF5 COMPONENTS C REQUIRED) find_package(HDF5 COMPONENTS C REQUIRED)
add_subdirectory("src") add_subdirectory("src")
......
...@@ -10,6 +10,6 @@ Name: @PACKAGE_NAME@ ...@@ -10,6 +10,6 @@ Name: @PACKAGE_NAME@
Version: @VERSION@ Version: @VERSION@
Description: dune-tectonic module Description: dune-tectonic module
URL: http://dune-project.org/ URL: http://dune-project.org/
Requires: dune-common dune-fufem dune-grid dune-istl dune-solvers dune-tnnmg dune-uggrid Requires: dune-common dune-contact dune-fufem dune-grid dune-istl dune-solvers dune-tnnmg dune-uggrid
Libs: -L${libdir} Libs: -L${libdir}
Cflags: -I${includedir} Cflags: -I${includedir}
...@@ -5,4 +5,4 @@ ...@@ -5,4 +5,4 @@
Module: dune-tectonic Module: dune-tectonic
Version: 2.5-1 Version: 2.5-1
Maintainer: elias.pipping@fu-berlin.de Maintainer: elias.pipping@fu-berlin.de
Depends: dune-common dune-fufem dune-grid dune-istl dune-solvers dune-tnnmg dune-uggrid Depends: dune-common dune-contact dune-fufem dune-grid dune-istl dune-solvers dune-tnnmg dune-uggrid
install(FILES install(FILES
body.hh bodydata.hh
frictiondata.hh frictiondata.hh
frictionpotential.hh frictionpotential.hh
globalfrictiondata.hh globalfrictiondata.hh
...@@ -12,4 +12,5 @@ install(FILES ...@@ -12,4 +12,5 @@ install(FILES
mydirectionalconvexfunction.hh mydirectionalconvexfunction.hh
quadraticenergy.hh quadraticenergy.hh
tectonic.hh tectonic.hh
transformedglobalratestatefriction.hh
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/tectonic) DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/tectonic)
#ifndef DUNE_TECTONIC_BODY_HH #ifndef DUNE_TECTONIC_BODY_DATA_HH
#define DUNE_TECTONIC_BODY_HH #define DUNE_TECTONIC_BODY_DATA_HH
template <int dimension> struct Body { template <int dimension> struct BodyData {
using ScalarFunction = using ScalarFunction =
Dune::VirtualFunction<Dune::FieldVector<double, dimension>, Dune::VirtualFunction<Dune::FieldVector<double, dimension>,
Dune::FieldVector<double, 1>>; Dune::FieldVector<double, 1>>;
......
...@@ -41,26 +41,42 @@ class TruncatedRateState : public FrictionPotential { ...@@ -41,26 +41,42 @@ class TruncatedRateState : public FrictionPotential {
} }
double differential(double V) const override { double differential(double V) const override {
//std::cout << "differential: " << weight * fd.C - weightedNormalStress * coefficientOfFriction(V) << std::endl;
return weight * fd.C - weightedNormalStress * coefficientOfFriction(V); return weight * fd.C - weightedNormalStress * coefficientOfFriction(V);
} }
double second_deriv(double V) const override { double second_deriv(double V) const override {
//std::cout << "second deriv: " << ((V<=Vmin) ? 0.0 : -weightedNormalStress * (fd.a / V)) << std::endl;
if (V <= Vmin) if (V <= Vmin)
return 0; return 0.0;
return -weightedNormalStress * (fd.a / V); return -weightedNormalStress * (fd.a / V);
} }
double regularity(double V) const override { double regularity(double V) const override {
//std::cout << "regularity: " << ((std::abs(V - Vmin) < 1e-14) ? std::numeric_limits<double>::infinity() : std::abs(second_deriv(V))) << std::endl;
if (std::abs(V - Vmin) < 1e-14) // TODO if (std::abs(V - Vmin) < 1e-14) // TODO
return std::numeric_limits<double>::infinity(); return std::numeric_limits<double>::infinity();
return std::abs(second_deriv(V)); return std::abs(second_deriv(V));
} }
double evaluate(double V) const override {
//std::cout << "second deriv: " << ((V<=Vmin) ? 0.0 : weight * fd.C * V - weightedNormalStress * fd.a * V * (std::log(V / Vmin) - 1)) << std::endl;
if (V <= Vmin)
return 0.0;
return weight * fd.C * V - weightedNormalStress * fd.a * V * (std::log(V / Vmin) - 1);
}
void updateAlpha(double alpha) override { void updateAlpha(double alpha) override {
double const logrest = (fd.mu0 + fd.b * alpha) / fd.a; double const logrest = (fd.mu0 + fd.b * alpha) / fd.a;
Vmin = fd.V0 / std::exp(logrest); Vmin = fd.V0 / std::exp(logrest);
//std::cout << "Vmin: " << Vmin << std::endl;
} }
private: private:
...@@ -92,6 +108,10 @@ class RegularisedRateState : public FrictionPotential { ...@@ -92,6 +108,10 @@ class RegularisedRateState : public FrictionPotential {
return std::abs(second_deriv(V)); return std::abs(second_deriv(V));
} }
double evaluate(double V) const override {
return weight * fd.C * V - weightedNormalStress * 4 * fd.a * Vmin * std::pow(std::asinh(0.25 * V / Vmin), 2.0);
}
void updateAlpha(double alpha) override { void updateAlpha(double alpha) override {
double const logrest = (fd.mu0 + fd.b * alpha) / fd.a; double const logrest = (fd.mu0 + fd.b * alpha) / fd.a;
Vmin = fd.V0 / std::exp(logrest); Vmin = fd.V0 / std::exp(logrest);
...@@ -106,6 +126,9 @@ class RegularisedRateState : public FrictionPotential { ...@@ -106,6 +126,9 @@ class RegularisedRateState : public FrictionPotential {
class ZeroFunction : public FrictionPotential { class ZeroFunction : public FrictionPotential {
public: public:
template <typename... Args>
ZeroFunction(Args... args) {}
double evaluate(double) const override { return 0; } double evaluate(double) const override { return 0; }
double coefficientOfFriction(double s) const override { return 0; } double coefficientOfFriction(double s) const override { return 0; }
......
...@@ -9,9 +9,12 @@ ...@@ -9,9 +9,12 @@
#include <dune/solvers/common/interval.hh> #include <dune/solvers/common/interval.hh>
#include <dune/tnnmg/functionals/nonsmoothconvexfunctional.hh>
#include <dune/tectonic/localfriction.hh> #include <dune/tectonic/localfriction.hh>
template <class Matrix, class Vector> class GlobalFriction { template <class Matrix, class Vector>
class GlobalFriction { //: public Dune::TNNMG::NonsmoothConvexFunctional<> {
protected: protected:
using ScalarVector = Dune::BlockVector<Dune::FieldVector<double, 1>>; using ScalarVector = Dune::BlockVector<Dune::FieldVector<double, 1>>;
...@@ -81,6 +84,7 @@ template <class Matrix, class Vector> class GlobalFriction { ...@@ -81,6 +84,7 @@ template <class Matrix, class Vector> class GlobalFriction {
return ret; return ret;
} }
void virtual updateAlpha(ScalarVector const &alpha) = 0; void virtual updateAlpha(const std::vector<ScalarVector>& alpha) = 0;
}; };
#endif #endif
...@@ -27,6 +27,7 @@ template <int dimension> class GlobalFrictionData { ...@@ -27,6 +27,7 @@ template <int dimension> class GlobalFrictionData {
Dune::VirtualFunction<Dune::FieldVector<double, dimension>, Dune::VirtualFunction<Dune::FieldVector<double, dimension>,
Dune::FieldVector<double, 1>>; Dune::FieldVector<double, 1>>;
public:
double virtual const &C() const = 0; double virtual const &C() const = 0;
double virtual const &L() const = 0; double virtual const &L() const = 0;
double virtual const &V0() const = 0; double virtual const &V0() const = 0;
......
...@@ -10,62 +10,123 @@ ...@@ -10,62 +10,123 @@
#include <dune/istl/bcrsmatrix.hh> #include <dune/istl/bcrsmatrix.hh>
#include <dune/istl/bvector.hh> #include <dune/istl/bvector.hh>
#include <dune/contact/assemblers/dualmortarcoupling.hh>
#include <dune/tectonic/geocoordinate.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> #include <dune/tectonic/index-in-sorted-range.hh>
template <class Matrix, class Vector, class ScalarFriction, class GridView> #include "../../src/frictioncouplingpair.hh"
template <class Matrix, class Vector, class ScalarFriction, class GridType>
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>::LocalNonlinearity; using typename GlobalFriction<Matrix, Vector>::LocalNonlinearity;
private: private:
using typename GlobalFriction<Matrix, Vector>::ScalarVector; using Base = GlobalFriction<Matrix, Vector>;
using field_type = typename Vector::field_type;
using typename Base::ScalarVector;
using typename Base::LocalVectorType;
using FrictionCouplingPair = FrictionCouplingPair<GridType, LocalVectorType, field_type>;
using ContactCoupling = Dune::Contact::DualMortarCoupling<field_type, GridType>;
size_t bodyIndex(const size_t globalIdx) {
size_t i=0;
for (; i<maxIndex_.size(); i++) {
if (globalIdx < maxIndex_[i])
break;
}
return i;
}
public: public:
GlobalRateStateFriction(BoundaryPatch<GridView> const &frictionalBoundary, GlobalRateStateFriction(const std::vector<std::shared_ptr<ContactCoupling>>& contactCouplings, // contains nonmortarBoundary
GlobalFrictionData<block_size> const &frictionInfo, const std::vector<std::shared_ptr<FrictionCouplingPair>>& couplings, // contains frictionInfo
ScalarVector const &weights, const std::vector<ScalarVector>& weights,
ScalarVector const &weightedNormalStress) const std::vector<ScalarVector>& weightedNormalStress)
: restrictions(), localToGlobal(), zeroFriction() { : restrictions_(), localToGlobal_(), zeroFriction_() {
auto const gridView = frictionalBoundary.gridView();
Dune::MultipleCodimMultipleGeomTypeMapper< assert(contactCouplings.size() == couplings.size());
GridView, Dune::MCMGVertexLayout> const vertexMapper(gridView); assert(weights.size() == weightedNormalStress.size());
for (auto it = gridView.template begin<block_size>();
it != gridView.template end<block_size>(); ++it) { const auto nBodies = weights.size();
auto const i = vertexMapper.index(*it);
std::vector<std::vector<int>> nonmortarBodies(nBodies); // first index body, second index coupling
if (not frictionalBoundary.containsVertex(i)) for (size_t i=0; i<contactCouplings.size(); i++) {
continue; const auto nonmortarIdx = couplings[i]->gridIdx_[0];
nonmortarBodies[nonmortarIdx].emplace_back(i);
localToGlobal.emplace_back(i); }
restrictions.emplace_back(weights[i], weightedNormalStress[i],
frictionInfo(geoToPoint(it->geometry()))); maxIndex_.resize(nBodies);
size_t globalIdx = 0;
for (size_t bodyIdx=0; bodyIdx<nBodies; bodyIdx++) {
const auto& couplingIndices = nonmortarBodies[bodyIdx];
if (couplingIndices.size()==0)
continue;
const auto gridView = contactCouplings[couplingIndices[0]]->nonmortarBoundary().gridView();
Dune::MultipleCodimMultipleGeomTypeMapper<
decltype(gridView), Dune::MCMGVertexLayout> const vertexMapper(gridView, Dune::mcmgVertexLayout());
for (auto it = gridView.template begin<block_size>(); it != gridView.template end<block_size>(); ++it) {
const auto i = vertexMapper.index(*it);
for (size_t j=0; j<couplingIndices.size(); j++) {
const auto couplingIdx = couplingIndices[j];
if (not contactCouplings[couplingIdx]->nonmortarBoundary().containsVertex(i))
continue;
localToGlobal_.emplace_back(i);
restrictions_.emplace_back(weights[bodyIdx][i], weightedNormalStress[bodyIdx][i],
couplings[j]->frictionData()(geoToPoint(it->geometry())));
break;
}
globalIdx++;
}
maxIndex_[bodyIdx] = globalIdx;
} }
assert(restrictions.size() == frictionalBoundary.numVertices());
assert(localToGlobal.size() == frictionalBoundary.numVertices());
} }
void updateAlpha(ScalarVector const &alpha) override { void updateAlpha(const std::vector<ScalarVector>& alpha) override {
for (size_t j = 0; j < restrictions.size(); ++j) for (size_t j = 0; j < restrictions_.size(); ++j) {
restrictions[j].updateAlpha(alpha[localToGlobal[j]]); const auto bodyIdx = bodyIndex(j);
const auto globalDof = localToGlobal_[j];
size_t bodyDof;
if (bodyIdx>0) {
bodyDof = globalDof - maxIndex_[bodyIdx-1];
} else {
bodyDof = globalDof;
}
restrictions_[j].updateAlpha(alpha[bodyIdx][bodyDof]);
}
} }
/* /*
Return a restriction of the outer function to the i'th node. Return a restriction of the outer function to the i'th node.
*/ */
LocalNonlinearity const &restriction(size_t i) const override { LocalNonlinearity const &restriction(size_t i) const override {
auto const index = indexInSortedRange(localToGlobal, i); auto const index = indexInSortedRange(localToGlobal_, i);
if (index == localToGlobal.size()) if (index == localToGlobal_.size())
return zeroFriction; return zeroFriction_;
return restrictions[index]; return restrictions_[index];
} }
private: private:
std::vector<WrappedScalarFriction<block_size, ScalarFriction>> restrictions; std::vector<WrappedScalarFriction<block_size, ScalarFriction>> restrictions_;
std::vector<size_t> localToGlobal; std::vector<size_t> maxIndex_; // max global index per body
WrappedScalarFriction<block_size, ZeroFunction> const zeroFriction; std::vector<size_t> localToGlobal_;
WrappedScalarFriction<block_size, ZeroFunction> const zeroFriction_;
}; };
#endif #endif
...@@ -19,6 +19,7 @@ template <size_t dimension> class LocalFriction { ...@@ -19,6 +19,7 @@ template <size_t dimension> class 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>;
double virtual operator()(VectorType const &x) const = 0;
void virtual updateAlpha(double alpha) = 0; void virtual updateAlpha(double alpha) = 0;
double virtual regularity(VectorType const &x) const = 0; double virtual regularity(VectorType const &x) const = 0;
double virtual coefficientOfFriction(VectorType const &x) const = 0; double virtual coefficientOfFriction(VectorType const &x) const = 0;
...@@ -44,6 +45,10 @@ class WrappedScalarFriction : public LocalFriction<dimension> { ...@@ -44,6 +45,10 @@ class WrappedScalarFriction : public LocalFriction<dimension> {
WrappedScalarFriction(Args... args) WrappedScalarFriction(Args... args)
: func_(args...) {} : func_(args...) {}
double operator()(VectorType const &x) const override {
return func_.evaluate(x.two_norm());
}
void updateAlpha(double alpha) override { func_.updateAlpha(alpha); } void updateAlpha(double alpha) override { func_.updateAlpha(alpha); }
double regularity(VectorType const &x) const override { double regularity(VectorType const &x) const override {
...@@ -86,17 +91,26 @@ class WrappedScalarFriction : public LocalFriction<dimension> { ...@@ -86,17 +91,26 @@ class WrappedScalarFriction : public LocalFriction<dimension> {
\f} \f}
*/ */
void addHessian(VectorType const &x, MatrixType &A) const override { void addHessian(VectorType const &x, MatrixType &A) const override {
//std::cout << A << std::endl;
//std::cout << x << std::endl;
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;
//std::cout << xnorm << " " << xnorm2 << std::endl;
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);
//std::cout << H1 << " " << H2 << std::endl;
double const tensorweight = (H2 - H1 / xnorm) / xnorm2; double const tensorweight = (H2 - H1 / xnorm) / xnorm2;
double const idweight = H1 / xnorm; double const idweight = H1 / xnorm;
//std::cout << tensorweight << " " << idweight << std::endl;
for (size_t i = 0; i < dimension; ++i) for (size_t i = 0; i < dimension; ++i)
for (size_t j = 0; j < i; ++j) { for (size_t j = 0; j < i; ++j) {
double const entry = tensorweight * x[i] * x[j]; double const entry = tensorweight * x[i] * x[j];
...@@ -108,6 +122,8 @@ class WrappedScalarFriction : public LocalFriction<dimension> { ...@@ -108,6 +122,8 @@ class WrappedScalarFriction : public LocalFriction<dimension> {
double const entry = tensorweight * x[k] * x[k]; double const entry = tensorweight * x[k] * x[k];
A[k][k] += entry + idweight; A[k][k] += entry + idweight;
} }
//std::cout << A << std::endl;
} }
void addGradient(VectorType const &x, VectorType &y) const override { void addGradient(VectorType const &x, VectorType &y) const override {
......
...@@ -57,7 +57,7 @@ class MyBlockProblem : /* not public */ BlockNonlinearGSProblem<ConvexProblem> { ...@@ -57,7 +57,7 @@ class MyBlockProblem : /* not public */ BlockNonlinearGSProblem<ConvexProblem> {
MyBlockProblem(Dune::ParameterTree const &parset, ConvexProblem &problem) MyBlockProblem(Dune::ParameterTree const &parset, ConvexProblem &problem)
: Base(parset, problem), : Base(parset, problem),
maxEigenvalues_(problem.f.size()), maxEigenvalues_(problem.f.size()),
localBisection(0.0, 1.0, 0.0, true, 0.0) { localBisection(0.0, 1.0, 0.0, 0.0) {
for (size_t i = 0; i < problem.f.size(); ++i) { for (size_t i = 0; i < problem.f.size(); ++i) {
LocalVectorType eigenvalues; LocalVectorType eigenvalues;
Dune::FMatrixHelp::eigenValues(problem.A[i][i], eigenvalues); Dune::FMatrixHelp::eigenValues(problem.A[i][i], eigenvalues);
......
#ifndef DUNE_TECTONIC_MYDIRECTIONALCONVEXFUNCTION_HH
#define DUNE_TECTONIC_MYDIRECTIONALCONVEXFUNCTION_HH
// Copied from dune/tnnmg/problem-classes/directionalconvexfunction.hh
// Allows phi to be const
#include <dune/fufem/arithmetic.hh>
#include <dune/solvers/common/interval.hh>
template <class Nonlinearity> class MyDirectionalConvexFunction {
public:
using Vector = typename Nonlinearity::VectorType;
using Matrix = typename Nonlinearity::MatrixType;
MyDirectionalConvexFunction(double A, double b, Nonlinearity const &phi,
Vector const &u, Vector const &v)
: A(A), b(b), phi(phi), u(u), v(v) {
phi.directionalDomain(u, v, dom);
}
double quadraticPart() const { return A; }
double linearPart() const { return b; }
void subDiff(double x, Dune::Solvers::Interval<double> &D) const {
Vector uxv = u;
Arithmetic::addProduct(uxv, x, v);
phi.directionalSubDiff(uxv, v, D);
auto const Axmb = A * x - b;
D[0] += Axmb;
D[1] += Axmb;
}
void domain(Dune::Solvers::Interval<double> &domain) const {
domain[0] = this->dom[0];
domain[1] = this->dom[1];
}
double A;
double b;
private:
Nonlinearity const &phi;
Vector const &u;
Vector const &v;
Dune::Solvers::Interval<double> dom;
};
/*
1/2 <A(u + hv),u + hv> - <b, u + hv>
= 1/2 <Av,v> h^2 - <b - Au, v> h + const.
localA = <Av,v>
localb = <b - Au, v>
*/
template <class Matrix, class Vector, class Nonlinearity>
MyDirectionalConvexFunction<Nonlinearity> restrict(Matrix const &A,
Vector const &b,
Vector const &u,
Vector const &v,
Nonlinearity const &phi) {
return MyDirectionalConvexFunction<Nonlinearity>(
Arithmetic::Axy(A, v, v), Arithmetic::bmAxy(A, b, u, v), phi, u, v);
}
#endif
#ifndef DUNE_TECTONIC_TECTONIC_HH
#define DUNE_TECTONIC_TECTONIC_HH
// add your classes here
#endif
--------------------------
-- Program structure: --
--------------------------
1. build n-body system
- contains grids, couplings, gridViews, assembler
Data structure: LevelContactNetwork
Factories: StackedBlocksFactory
2. initialize/set up program state
- holds bodyStates, u, v, a, alpha for each body
- defines time, timeStep
- computes initial conditions
Data structure: ProgramState
-- tested until here
3. assemble RSD friction
4. set up TNNMG solver
- rate updater
- state updater
5. adaptive time stepper
add_subdirectory("tests")
add_subdirectory("spatial-solving")
set(SW_SOURCE_FILES set(SW_SOURCE_FILES
assemblers.cc assemblers.cc
enumparser.cc data-structures/body.cc
hdf5/frictionalboundary-writer.cc data-structures/enumparser.cc
hdf5/iteration-writer.cc io/vtk.cc
hdf5/patchinfo-writer.cc io/hdf5/frictionalboundary-writer.cc
hdf5/restart-io.cc io/hdf5/iteration-writer.cc
hdf5/surface-writer.cc io/hdf5/patchinfo-writer.cc
hdf5/time-writer.cc io/hdf5/restart-io.cc
one-body-problem-data/mygeometry.cc io/hdf5/surface-writer.cc
one-body-problem-data/mygrid.cc io/hdf5/time-writer.cc
one-body-problem.cc # one-body-problem-data/mygeometry.cc
# one-body-problem-data/mygrid.cc
# one-body-problem.cc
spatial-solving/fixedpointiterator.cc spatial-solving/fixedpointiterator.cc
spatial-solving/solverfactory.cc spatial-solving/solverfactory.cc
time-stepping/adaptivetimestepper.cc time-stepping/adaptivetimestepper.cc
...@@ -17,26 +22,92 @@ set(SW_SOURCE_FILES ...@@ -17,26 +22,92 @@ set(SW_SOURCE_FILES
time-stepping/rate.cc time-stepping/rate.cc
time-stepping/rate/rateupdater.cc time-stepping/rate/rateupdater.cc
time-stepping/state.cc time-stepping/state.cc
vtk.cc
) )
set(MSW_SOURCE_FILES
assemblers.cc
#nodalweights.cc
data-structures/body.cc
data-structures/levelcontactnetwork.cc
data-structures/contactnetwork.cc
data-structures/enumparser.cc
#factories/cantorfactory.cc
factories/threeblocksfactory.cc
factories/stackedblocksfactory.cc
io/vtk.cc
io/hdf5/frictionalboundary-writer.cc
io/hdf5/iteration-writer.cc
io/hdf5/patchinfo-writer.cc
io/hdf5/restart-io.cc
io/hdf5/surface-writer.cc
io/hdf5/time-writer.cc
#multi-body-problem-data/grid/cube.cc
#multi-body-problem-data/grid/cubefaces.cc
multi-body-problem-data/grid/cuboidgeometry.cc
multi-body-problem-data/grid/mygrids.cc
multi-body-problem-data/grid/simplexmanager.cc
multi-body-problem.cc
#spatial-solving/solverfactory.cc
spatial-solving/fixedpointiterator.cc
#spatial-solving/solverfactory_old.cc
time-stepping/adaptivetimestepper.cc
time-stepping/coupledtimestepper.cc
time-stepping/rate.cc
time-stepping/rate/rateupdater.cc
time-stepping/state.cc
)
set(UGW_SOURCE_FILES set(UGW_SOURCE_FILES
assemblers.cc # FIXME assemblers.cc # FIXME
io/uniform-grid-writer.cc
io/vtk.cc
one-body-problem-data/mygrid.cc one-body-problem-data/mygrid.cc
uniform-grid-writer.cc )
vtk.cc
set(SFT_SOURCE_FILES
assemblers.cc
data-structures/body.cc
data-structures/levelcontactnetwork.cc
data-structures/contactnetwork.cc
data-structures/enumparser.cc
factories/stackedblocksfactory.cc
io/vtk.cc
multi-body-problem-data/grid/cuboidgeometry.cc
multi-body-problem-data/grid/mygrids.cc
multi-body-problem-data/grid/simplexmanager.cc
#spatial-solving/solverfactory.cc
#spatial-solving/fixedpointiterator.cc
#spatial-solving/solverfactory_old.cc
#time-stepping/adaptivetimestepper.cc
#time-stepping/coupledtimestepper.cc
time-stepping/rate.cc
time-stepping/rate/rateupdater.cc
time-stepping/state.cc
solverfactorytest.cc
) )
foreach(_dim 2 3) foreach(_dim 2 3)
set(_sw_target one-body-problem-${_dim}D) set(_sw_target one-body-problem-${_dim}D)
set(_msw_target multi-body-problem-${_dim}D)
set(_ugw_target uniform-grid-writer-${_dim}D) set(_ugw_target uniform-grid-writer-${_dim}D)
set(_sft_target solverfactorytest-${_dim}D)
add_executable(${_sw_target} ${SW_SOURCE_FILES}) add_executable(${_sw_target} ${SW_SOURCE_FILES})
add_executable(${_msw_target} ${MSW_SOURCE_FILES})
add_executable(${_ugw_target} ${UGW_SOURCE_FILES}) add_executable(${_ugw_target} ${UGW_SOURCE_FILES})
add_executable(${_sft_target} ${SFT_SOURCE_FILES})
add_dune_ug_flags(${_sw_target}) add_dune_ug_flags(${_sw_target})
add_dune_ug_flags(${_msw_target})
add_dune_ug_flags(${_ugw_target}) add_dune_ug_flags(${_ugw_target})
add_dune_ug_flags(${_sft_target})
add_dune_hdf5_flags(${_sw_target}) add_dune_hdf5_flags(${_sw_target})
add_dune_hdf5_flags(${_msw_target})
set_property(TARGET ${_sw_target} APPEND PROPERTY COMPILE_DEFINITIONS "MY_DIM=${_dim}") set_property(TARGET ${_sw_target} APPEND PROPERTY COMPILE_DEFINITIONS "MY_DIM=${_dim}")
set_property(TARGET ${_msw_target} APPEND PROPERTY COMPILE_DEFINITIONS "MY_DIM=${_dim}")
#set_property(TARGET ${_msw_target} APPEND PROPERTY COMPILE_DEFINITIONS "NEW_TNNMG_COMPUTE_ITERATES_DIRECTLY=1")
set_property(TARGET ${_ugw_target} APPEND PROPERTY COMPILE_DEFINITIONS "MY_DIM=${_dim}") set_property(TARGET ${_ugw_target} APPEND PROPERTY COMPILE_DEFINITIONS "MY_DIM=${_dim}")
set_property(TARGET ${_sft_target} APPEND PROPERTY COMPILE_DEFINITIONS "MY_DIM=${_dim}")
#set_property(TARGET ${_sft_target} APPEND PROPERTY COMPILE_DEFINITIONS "NEW_TNNMG_COMPUTE_ITERATES_DIRECTLY=1")
endforeach() endforeach()
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
#include <dune/fufem/assemblers/localassemblers/variablecoefficientviscosityassembler.hh> #include <dune/fufem/assemblers/localassemblers/variablecoefficientviscosityassembler.hh>
#include <dune/fufem/assemblers/localassemblers/vonmisesstressassembler.hh> #include <dune/fufem/assemblers/localassemblers/vonmisesstressassembler.hh>
#include <dune/fufem/assemblers/localassemblers/weightedmassassembler.hh> #include <dune/fufem/assemblers/localassemblers/weightedmassassembler.hh>
#include <dune/fufem/boundarypatch.hh>
#include <dune/fufem/functions/basisgridfunction.hh> #include <dune/fufem/functions/basisgridfunction.hh>
#include <dune/fufem/functions/constantfunction.hh> #include <dune/fufem/functions/constantfunction.hh>
#include <dune/fufem/functiontools/p0p1interpolation.hh> #include <dune/fufem/functiontools/p0p1interpolation.hh>
...@@ -24,17 +23,28 @@ ...@@ -24,17 +23,28 @@
#include "assemblers.hh" #include "assemblers.hh"
template <class GridView, int dimension> template <class GridView, int dimension>
MyAssembler<GridView, dimension>::MyAssembler(GridView const &_gridView) MyAssembler<GridView, dimension>::MyAssembler(GridView const &_gridView) :
: cellBasis(_gridView), cellBasis(_gridView),
vertexBasis(_gridView), vertexBasis(_gridView),
gridView(_gridView), gridView(_gridView),
cellAssembler(cellBasis, cellBasis), cellAssembler(cellBasis, cellBasis),
vertexAssembler(vertexBasis, vertexBasis) {} vertexAssembler(vertexBasis, vertexBasis) {}
template <class GridView, int dimension>
template <class LocalBoundaryFunctionalAssemblerType, class GlobalVectorType>
void MyAssembler<GridView, dimension>::assembleBoundaryFunctional(LocalBoundaryFunctionalAssemblerType& localAssembler,
GlobalVectorType& b,
const BoundaryPatch<GridView>& boundaryPatch,
bool initializeVector) const {
vertexAssembler.assembleBoundaryFunctional(localAssembler, b, boundaryPatch, initializeVector);
}
template <class GridView, int dimension> template <class GridView, int dimension>
void MyAssembler<GridView, dimension>::assembleFrictionalBoundaryMass( void MyAssembler<GridView, dimension>::assembleFrictionalBoundaryMass(
BoundaryPatch<GridView> const &frictionalBoundary, BoundaryPatch<GridView> const &frictionalBoundary,
ScalarMatrix &frictionalBoundaryMass) const { ScalarMatrix &frictionalBoundaryMass) const {
BoundaryMassAssembler<Grid, BoundaryPatch<GridView>, LocalVertexBasis, BoundaryMassAssembler<Grid, BoundaryPatch<GridView>, LocalVertexBasis,
LocalVertexBasis, Dune::FieldMatrix<double, 1, 1>> const LocalVertexBasis, Dune::FieldMatrix<double, 1, 1>> const
frictionalBoundaryMassAssembler(frictionalBoundary); frictionalBoundaryMassAssembler(frictionalBoundary);
...@@ -44,9 +54,9 @@ void MyAssembler<GridView, dimension>::assembleFrictionalBoundaryMass( ...@@ -44,9 +54,9 @@ void MyAssembler<GridView, dimension>::assembleFrictionalBoundaryMass(
template <class GridView, int dimension> template <class GridView, int dimension>
void MyAssembler<GridView, dimension>::assembleMass( void MyAssembler<GridView, dimension>::assembleMass(
Dune::VirtualFunction<LocalVector, LocalScalarVector> const & Dune::VirtualFunction<LocalVector, LocalScalarVector> const & densityFunction,
densityFunction, Matrix &M) const {
Matrix &M) const {
// NOTE: We treat the weight as a constant function // NOTE: We treat the weight as a constant function
QuadratureRuleKey quadKey(dimension, 0); QuadratureRuleKey quadKey(dimension, 0);
...@@ -58,8 +68,11 @@ void MyAssembler<GridView, dimension>::assembleMass( ...@@ -58,8 +68,11 @@ void MyAssembler<GridView, dimension>::assembleMass(
} }
template <class GridView, int dimension> template <class GridView, int dimension>
void MyAssembler<GridView, dimension>::assembleElasticity(double E, double nu, void MyAssembler<GridView, dimension>::assembleElasticity(
Matrix &A) const { double E,
double nu,
Matrix &A) const {
StVenantKirchhoffAssembler<Grid, LocalVertexBasis, LocalVertexBasis> const StVenantKirchhoffAssembler<Grid, LocalVertexBasis, LocalVertexBasis> const
localStiffness(E, nu); localStiffness(E, nu);
vertexAssembler.assembleOperator(localStiffness, A); vertexAssembler.assembleOperator(localStiffness, A);
...@@ -67,9 +80,10 @@ void MyAssembler<GridView, dimension>::assembleElasticity(double E, double nu, ...@@ -67,9 +80,10 @@ void MyAssembler<GridView, dimension>::assembleElasticity(double E, double nu,
template <class GridView, int dimension> template <class GridView, int dimension>
void MyAssembler<GridView, dimension>::assembleViscosity( void MyAssembler<GridView, dimension>::assembleViscosity(
Dune::VirtualFunction<LocalVector, LocalScalarVector> const &shearViscosity, Dune::VirtualFunction<LocalVector, LocalScalarVector> const &shearViscosity,
Dune::VirtualFunction<LocalVector, LocalScalarVector> const &bulkViscosity, Dune::VirtualFunction<LocalVector, LocalScalarVector> const &bulkViscosity,
Matrix &C) const { Matrix &C) const {
// NOTE: We treat the weights as constant functions // NOTE: We treat the weights as constant functions
QuadratureRuleKey shearViscosityKey(dimension, 0); QuadratureRuleKey shearViscosityKey(dimension, 0);
QuadratureRuleKey bulkViscosityKey(dimension, 0); QuadratureRuleKey bulkViscosityKey(dimension, 0);
...@@ -83,8 +97,9 @@ void MyAssembler<GridView, dimension>::assembleViscosity( ...@@ -83,8 +97,9 @@ void MyAssembler<GridView, dimension>::assembleViscosity(
template <class GridView, int dimension> template <class GridView, int dimension>
void MyAssembler<GridView, dimension>::assembleBodyForce( void MyAssembler<GridView, dimension>::assembleBodyForce(
Dune::VirtualFunction<LocalVector, LocalVector> const &gravityField, Dune::VirtualFunction<LocalVector, LocalVector> const &gravityField,
Vector &f) const { Vector &f) const {
L2FunctionalAssembler<Grid, LocalVertexBasis, LocalVector> L2FunctionalAssembler<Grid, LocalVertexBasis, LocalVector>
gravityFunctionalAssembler(gravityField); gravityFunctionalAssembler(gravityField);
vertexAssembler.assembleFunctional(gravityFunctionalAssembler, f); vertexAssembler.assembleFunctional(gravityFunctionalAssembler, f);
...@@ -92,9 +107,11 @@ void MyAssembler<GridView, dimension>::assembleBodyForce( ...@@ -92,9 +107,11 @@ void MyAssembler<GridView, dimension>::assembleBodyForce(
template <class GridView, int dimension> template <class GridView, int dimension>
void MyAssembler<GridView, dimension>::assembleNeumann( void MyAssembler<GridView, dimension>::assembleNeumann(
BoundaryPatch<GridView> const &neumannBoundary, Vector &f, BoundaryPatch<GridView> const &neumannBoundary,
Dune::VirtualFunction<double, double> const &neumann, Vector &f,
double relativeTime) const { Dune::VirtualFunction<double, double> const &neumann,
double relativeTime) const {
LocalVector localNeumann(0); LocalVector localNeumann(0);
neumann.evaluate(relativeTime, localNeumann[0]); neumann.evaluate(relativeTime, localNeumann[0]);
NeumannBoundaryAssembler<Grid, LocalVector> neumannBoundaryAssembler( NeumannBoundaryAssembler<Grid, LocalVector> neumannBoundaryAssembler(
...@@ -106,9 +123,11 @@ void MyAssembler<GridView, dimension>::assembleNeumann( ...@@ -106,9 +123,11 @@ void MyAssembler<GridView, dimension>::assembleNeumann(
template <class GridView, int dimension> template <class GridView, int dimension>
void MyAssembler<GridView, dimension>::assembleWeightedNormalStress( void MyAssembler<GridView, dimension>::assembleWeightedNormalStress(
BoundaryPatch<GridView> const &frictionalBoundary, BoundaryPatch<GridView> const &frictionalBoundary,
ScalarVector &weightedNormalStress, double youngModulus, ScalarVector &weightedNormalStress,
double poissonRatio, Vector const &displacement) const { double youngModulus,
double poissonRatio,
Vector const &displacement) const {
BasisGridFunction<VertexBasis, Vector> displacementFunction(vertexBasis, BasisGridFunction<VertexBasis, Vector> displacementFunction(vertexBasis,
displacement); displacement);
...@@ -136,41 +155,13 @@ void MyAssembler<GridView, dimension>::assembleWeightedNormalStress( ...@@ -136,41 +155,13 @@ void MyAssembler<GridView, dimension>::assembleWeightedNormalStress(
std::fmin(normals[i] * nodalTractionAverage[i], 0) * weights[i]; std::fmin(normals[i] * nodalTractionAverage[i], 0) * weights[i];
} }
template <class GridView, int dimension>
auto MyAssembler<GridView, dimension>::assembleFrictionNonlinearity(
Config::FrictionModel frictionModel,
BoundaryPatch<GridView> const &frictionalBoundary,
GlobalFrictionData<dimension> const &frictionInfo,
ScalarVector const &weightedNormalStress) const
-> std::shared_ptr<GlobalFriction<Matrix, Vector>> {
// Lumping of the nonlinearity
ScalarVector weights;
{
NeumannBoundaryAssembler<Grid, typename ScalarVector::block_type>
frictionalBoundaryAssembler(std::make_shared<
ConstantFunction<LocalVector, typename ScalarVector::block_type>>(
1));
vertexAssembler.assembleBoundaryFunctional(frictionalBoundaryAssembler,
weights, frictionalBoundary);
}
switch (frictionModel) {
case Config::Truncated:
return std::make_shared<GlobalRateStateFriction<
Matrix, Vector, TruncatedRateState, GridView>>(
frictionalBoundary, frictionInfo, weights, weightedNormalStress);
case Config::Regularised:
return std::make_shared<GlobalRateStateFriction<
Matrix, Vector, RegularisedRateState, GridView>>(
frictionalBoundary, frictionInfo, weights, weightedNormalStress);
default:
assert(false);
}
}
template <class GridView, int dimension> template <class GridView, int dimension>
void MyAssembler<GridView, dimension>::assembleVonMisesStress( void MyAssembler<GridView, dimension>::assembleVonMisesStress(
double youngModulus, double poissonRatio, Vector const &u, double youngModulus,
ScalarVector &stress) const { double poissonRatio,
Vector const &u,
ScalarVector &stress) const {
auto const gridDisplacement = auto const gridDisplacement =
std::make_shared<BasisGridFunction<VertexBasis, Vector> const>( std::make_shared<BasisGridFunction<VertexBasis, Vector> const>(
vertexBasis, u); vertexBasis, u);
......
...@@ -12,79 +12,96 @@ ...@@ -12,79 +12,96 @@
#include <dune/fufem/functionspacebases/p0basis.hh> #include <dune/fufem/functionspacebases/p0basis.hh>
#pragma clang diagnostic pop #pragma clang diagnostic pop
#include <dune/fufem/functionspacebases/p1nodalbasis.hh> #include <dune/fufem/functionspacebases/p1nodalbasis.hh>
#include <dune/fufem/boundarypatch.hh>
#include <dune/tectonic/globalfriction.hh> #include <dune/tectonic/globalfriction.hh>
#include <dune/tectonic/globalfrictiondata.hh> #include <dune/tectonic/globalfrictiondata.hh>
#include "enums.hh" #include "data-structures/enums.hh"
template <class GridView, int dimension> class MyAssembler { template <class GridView, int dimension>
class MyAssembler {
public: public:
using ScalarMatrix = Dune::BCRSMatrix<Dune::FieldMatrix<double, 1, 1>>; using ScalarMatrix = Dune::BCRSMatrix<Dune::FieldMatrix<double, 1, 1>>;
using Matrix = using Matrix =
Dune::BCRSMatrix<Dune::FieldMatrix<double, dimension, dimension>>; Dune::BCRSMatrix<Dune::FieldMatrix<double, dimension, dimension>>;
using ScalarVector = Dune::BlockVector<Dune::FieldVector<double, 1>>; using ScalarVector = Dune::BlockVector<Dune::FieldVector<double, 1>>;
using Vector = Dune::BlockVector<Dune::FieldVector<double, dimension>>; using Vector = Dune::BlockVector<Dune::FieldVector<double, dimension>>;
using CellBasis = P0Basis<GridView, double>; using CellBasis = P0Basis<GridView, double>;
using VertexBasis = P1NodalBasis<GridView, double>; using VertexBasis = P1NodalBasis<GridView, double>;
CellBasis const cellBasis; CellBasis const cellBasis;
VertexBasis const vertexBasis; VertexBasis const vertexBasis;
GridView const &gridView; GridView const &gridView;
private: private:
using Grid = typename GridView::Grid; using Grid = typename GridView::Grid;
using LocalVector = typename Vector::block_type; using LocalVector = typename Vector::block_type;
using LocalScalarVector = typename ScalarVector::block_type; using LocalScalarVector = typename ScalarVector::block_type;
using LocalCellBasis = typename CellBasis::LocalFiniteElement; using LocalCellBasis = typename CellBasis::LocalFiniteElement;
using LocalVertexBasis = typename VertexBasis::LocalFiniteElement; using LocalVertexBasis = typename VertexBasis::LocalFiniteElement;
Assembler<CellBasis, CellBasis> cellAssembler; Assembler<CellBasis, CellBasis> cellAssembler;
Assembler<VertexBasis, VertexBasis> vertexAssembler; Assembler<VertexBasis, VertexBasis> vertexAssembler;
public: public:
MyAssembler(GridView const &gridView); MyAssembler(GridView const &gridView);
void assembleFrictionalBoundaryMass( template <class LocalBoundaryFunctionalAssemblerType, class GlobalVectorType>
BoundaryPatch<GridView> const &frictionalBoundary, void assembleBoundaryFunctional(LocalBoundaryFunctionalAssemblerType& localAssembler,
ScalarMatrix &frictionalBoundaryMass) const; GlobalVectorType& b,
const BoundaryPatch<GridView>& boundaryPatch,
void assembleMass(Dune::VirtualFunction< bool initializeVector=true) const;
LocalVector, LocalScalarVector> const &densityFunction,
Matrix &M) const; void assembleFrictionalBoundaryMass(
BoundaryPatch<GridView> const &frictionalBoundary,
void assembleElasticity(double E, double nu, Matrix &A) const; ScalarMatrix &frictionalBoundaryMass) const;
void assembleViscosity( void assembleMass(
Dune::VirtualFunction<LocalVector, LocalScalarVector> const & Dune::VirtualFunction<
shearViscosity, LocalVector, LocalScalarVector> const &densityFunction,
Dune::VirtualFunction<LocalVector, LocalScalarVector> const & Matrix &M) const;
bulkViscosity,
Matrix &C) const; void assembleElasticity(
double E,
void assembleBodyForce( double nu,
Dune::VirtualFunction<LocalVector, LocalVector> const &gravityField, Matrix &A) const;
Vector &f) const;
void assembleViscosity(
void assembleNeumann(BoundaryPatch<GridView> const &neumannBoundary, Dune::VirtualFunction<LocalVector, LocalScalarVector> const & shearViscosity,
Vector &f, Dune::VirtualFunction<LocalVector, LocalScalarVector> const & bulkViscosity,
Dune::VirtualFunction<double, double> const &neumann, Matrix &C) const;
double relativeTime) const;
void assembleBodyForce(
void assembleWeightedNormalStress( Dune::VirtualFunction<LocalVector, LocalVector> const &gravityField,
BoundaryPatch<GridView> const &frictionalBoundary, Vector &f) const;
ScalarVector &weightedNormalStress, double youngModulus,
double poissonRatio, Vector const &displacement) const; void assembleNeumann(
BoundaryPatch<GridView> const &neumannBoundary,
std::shared_ptr<GlobalFriction<Matrix, Vector>> assembleFrictionNonlinearity( Vector &f,
Config::FrictionModel frictionModel, Dune::VirtualFunction<double, double> const &neumann,
BoundaryPatch<GridView> const &frictionalBoundary, double relativeTime) const;
GlobalFrictionData<dimension> const &frictionInfo,
ScalarVector const &weightedNormalStress) const; void assembleWeightedNormalStress(
BoundaryPatch<GridView> const &frictionalBoundary,
void assembleVonMisesStress(double youngModulus, double poissonRatio, ScalarVector &weightedNormalStress,
Vector const &u, ScalarVector &stress) const; double youngModulus,
double poissonRatio,
Vector const &displacement) const;
auto assembleFrictionNonlinearity(
Config::FrictionModel frictionModel,
BoundaryPatch<GridView> const &frictionalBoundary,
GlobalFrictionData<dimension> const &frictionInfo,
ScalarVector const &weightedNormalStress) const
-> std::shared_ptr<GlobalFriction<Matrix, Vector>>;
void assembleVonMisesStress(
double youngModulus,
double poissonRatio,
Vector const &u,
ScalarVector &stress) const;
}; };
#endif #endif
...@@ -3,5 +3,20 @@ ...@@ -3,5 +3,20 @@
#endif #endif
#include "explicitgrid.hh" #include "explicitgrid.hh"
#include "explicitvectors.hh"
template class MyAssembler<GridView, MY_DIM>; #include <dune/fufem/assemblers/localassemblers/neumannboundaryassembler.hh>
#include <dune/fufem/boundarypatch.hh>
#include "assemblers.hh"
template class MyAssembler<DefLeafGridView, MY_DIM>;
using MyNeumannBoundaryAssembler = NeumannBoundaryAssembler<DeformedGrid, typename ScalarVector::block_type>;
template void MyAssembler<DefLeafGridView, MY_DIM>::assembleBoundaryFunctional<MyNeumannBoundaryAssembler, ScalarVector>(
MyNeumannBoundaryAssembler& localAssembler,
ScalarVector& b,
const BoundaryPatch<DefLeafGridView>& boundaryPatch,
bool initializeVector) const;
#ifndef SRC_BOUNDARYCONDITION_HH
#define SRC_BOUNDARYCONDITION_HH
#include <dune/common/bitsetvector.hh>
#include <dune/common/function.hh>
#include <dune/fufem/boundarypatch.hh>
template <class GridView, int dims>
class BoundaryCondition {
public:
using BoundaryPatch = BoundaryPatch<GridView>;
private:
using Function = Dune::VirtualFunction<double, double>;
const std::string tag_; // store type of boundary condition, e.g. dirichlet, neumann, friction, etc
std::shared_ptr<BoundaryPatch> boundaryPatch_;
std::shared_ptr<Dune::BitSetVector<dims>> boundaryNodes_;
std::shared_ptr<Function> boundaryFunction_;
public:
BoundaryCondition(const std::string& tag = "") :
tag_(tag)
{}
BoundaryCondition(std::shared_ptr<BoundaryPatch> patch, std::shared_ptr<Function> function, const std::string& tag = "") :
tag_(tag),
boundaryPatch_(patch),
boundaryFunction_(function)
{}
void setBoundaryPatch(const GridView& gridView, std::shared_ptr<Dune::BitSetVector<dims>> nodes) {
boundaryNodes_ = nodes;
boundaryPatch_ = std::make_shared<BoundaryPatch>(gridView, *nodes);
}
void setBoundaryPatch(std::shared_ptr<BoundaryPatch> patch) {
boundaryPatch_ = patch;
}
void setBoundaryPatch(const BoundaryPatch& patch) {
boundaryPatch_ = std::make_shared<BoundaryPatch>(patch);
}
void setBoundaryFunction(std::shared_ptr<Function> function) {
boundaryFunction_ = function;
}
void set(std::shared_ptr<BoundaryPatch> patch, std::shared_ptr<Function> function) {
boundaryPatch_ = patch;
boundaryFunction_ = function;
}
const std::string& tag() const {
return tag_;
}
const std::shared_ptr<BoundaryPatch>& boundaryPatch() const {
return boundaryPatch_;
}
const std::shared_ptr<Dune::BitSetVector<dims>>& boundaryNodes() const {
return boundaryNodes_;
}
const std::shared_ptr<Function>& boundaryFunction() const {
return boundaryFunction_;
}
};
#endif
#ifndef MY_DIM
#error MY_DIM unset
#endif
#include "../explicitgrid.hh"
template class ContactNetwork<Grid, MY_DIM>;