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 1730 additions and 204 deletions
#ifndef SRC_MULTI_BODY_PROBLEM_DATA_MYBODY_HH
#define SRC_MULTI_BODY_PROBLEM_DATA_MYBODY_HH
#include <dune/common/fvector.hh>
#include <dune/fufem/functions/constantfunction.hh>
#include <dune/tectonic/body.hh>
#include <dune/tectonic/gravity.hh>
#include "cuboidgeometry.hh"
#include "segmented-function.hh"
template <int dimension> class MyBody : public Body<dimension> {
using typename Body<dimension>::ScalarFunction;
using typename Body<dimension>::VectorField;
public:
MyBody(Dune::ParameterTree const &parset)
: poissonRatio_(parset.get<double>("body.poissonRatio")),
youngModulus_(3.0 * parset.get<double>("body.bulkModulus") *
(1.0 - 2.0 * poissonRatio_)),
shearViscosityField_(
parset.get<double>("body.elastic.shearViscosity"),
parset.get<double>("body.viscoelastic.shearViscosity")),
bulkViscosityField_(
parset.get<double>("body.elastic.bulkViscosity"),
parset.get<double>("body.viscoelastic.bulkViscosity")),
densityField_(parset.get<double>("body.elastic.density"),
parset.get<double>("body.viscoelastic.density")),
gravityField_(densityField_, MyGeometry::zenith,
parset.get<double>("gravity")) {}
double getPoissonRatio() const override { return poissonRatio_; }
double getYoungModulus() const override { return youngModulus_; }
ScalarFunction const &getShearViscosityField() const override {
return shearViscosityField_;
}
ScalarFunction const &getBulkViscosityField() const override {
return bulkViscosityField_;
}
ScalarFunction const &getDensityField() const override {
return densityField_;
}
VectorField const &getGravityField() const override { return gravityField_; }
private:
double const poissonRatio_;
double const youngModulus_;
SegmentedFunction const shearViscosityField_;
SegmentedFunction const bulkViscosityField_;
SegmentedFunction const densityField_;
Gravity<dimension> const gravityField_;
};
#endif
#ifndef SRC_ONE_BODY_PROBLEM_DATA_MYGLOBALFRICTIONDATA_HH
#define SRC_ONE_BODY_PROBLEM_DATA_MYGLOBALFRICTIONDATA_HH
#include <dune/common/function.hh>
#include <dune/tectonic/globalfrictiondata.hh>
#include "patchfunction.hh"
template <class LocalVector>
class MyGlobalFrictionData : public GlobalFrictionData<LocalVector::dimension> {
private:
using typename GlobalFrictionData<LocalVector::dimension>::VirtualFunction;
public:
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"), segment),
b_(parset.get<double>("strengthening.b"),
parset.get<double>("weakening.b"), segment),
mu0_(parset.get<double>("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_;
double const L_;
double const V0_;
PatchFunction const a_;
PatchFunction const b_;
double const mu0_;
};
#endif
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <dune/fufem/geometry/polyhedrondistance.hh>
#include "mygrids.hh"
#include "midpoint.hh"
#include "../diameter.hh"
#if MY_DIM == 3
SimplexManager::SimplexManager(unsigned int shift) : shift_(shift) {}
#endif
// back-to-front, front-to-back, front-to-back
void SimplexManager::addFromVerticesFBB(unsigned int U, unsigned int V,
unsigned int W) {
#if MY_DIM == 3
unsigned int const U2 = U + shift_;
unsigned int const V2 = V + shift_;
unsigned int const W2 = W + shift_;
simplices_.push_back({ U, V, W, U2 });
simplices_.push_back({ V, V2, W2, U2 });
simplices_.push_back({ W, W2, U2, V });
#else
simplices_.push_back({ U, V, W });
#endif
}
// back-to-front, back-to-front, front-to-back
void SimplexManager::addFromVerticesFFB(unsigned int U, unsigned int V,
unsigned int W) {
#if MY_DIM == 3
unsigned int const U2 = U + shift_;
unsigned int const V2 = V + shift_;
unsigned int const W2 = W + shift_;
simplices_.push_back({ U, V, W, U2 });
simplices_.push_back({ V, V2, W, U2 });
simplices_.push_back({ V2, W, U2, W2 });
#else
simplices_.push_back({ U, V, W });
#endif
}
auto SimplexManager::getSimplices() -> SimplexList const & {
return simplices_;
}
// Fix: 3D case (still Elias code)
template <class Grid> GridsConstructor<Grid>::GridsConstructor(std::vector<std::shared_ptr<CuboidGeometry>> const &cuboidGeometries_) :
cuboidGeometries(cuboidGeometries_)
{
size_t const gridCount = cuboidGeometries.size();
grids.resize(gridCount);
gridFactories.resize(gridCount);
for (size_t idx=0; idx<grids.size(); idx++) {
const auto& cuboidGeometry = *cuboidGeometries[idx];
const auto& A = cuboidGeometry.A;
const auto& B = cuboidGeometry.B;
const auto& C = cuboidGeometry.C;
const auto& D = cuboidGeometry.D;
unsigned int const vc = 4;
#if MY_DIM == 3
Dune::FieldMatrix<double, 2 * vc, MY_DIM> vertices;
#else
Dune::FieldMatrix<double, vc, MY_DIM> vertices;
#endif
for (size_t i = 0; i < 2; ++i) {
#if MY_DIM == 3
size_t numXYplanes = 2;
#else
size_t numXYplanes = 1;
#endif
size_t k = 0;
for (size_t j = 1; j <= numXYplanes; ++j) {
vertices[k++][i] = A[i];
vertices[k++][i] = B[i];
vertices[k++][i] = C[i];
vertices[k++][i] = D[i];
assert(k == j * vc);
}
}
#if MY_DIM == 3
for (size_t k = 0; k < vc; ++k) {
vertices[k][2] = -cuboidGeometry.depth / 2.0;
vertices[k + vc][2] = cuboidGeometry.depth / 2.0;
}
#endif
for (size_t i = 0; i < vertices.N(); ++i)
gridFactories[idx].insertVertex(vertices[i]);
Dune::GeometryType cell;
#if MY_DIM == 3
cell = Dune::GeometryTypes::tetrahedron;
#else
cell = Dune::GeometryTypes::triangle;
#endif
#if MY_DIM == 3
SimplexManager sm(vc);
#else
SimplexManager sm;
#endif
sm.addFromVerticesFFB(1, 2, 0);
sm.addFromVerticesFFB(2, 3, 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);
gridFactories[idx].insertElement(cell, simplices[i]);
}
grids[idx] = std::shared_ptr<Grid>(gridFactories[idx].createGrid());
}
}
template <class Grid>
std::vector<std::shared_ptr<Grid>>& GridsConstructor<Grid>::getGrids() {
return grids;
}
template <class Grid>
template <class GridView>
MyFaces<GridView> GridsConstructor<Grid>::constructFaces(
GridView const &gridView, CuboidGeometry const &cuboidGeometry) {
return MyFaces<GridView>(gridView, cuboidGeometry);
}
template <class GridView>
template <class Vector>
bool MyFaces<GridView>::xyCollinear(Vector const &a, Vector const &b,
Vector const &c) {
return isClose2((b[0] - a[0]) * (c[1] - a[1]), (b[1] - a[1]) * (c[0] - a[0]));
}
template <class GridView>
template <class Vector>
bool MyFaces<GridView>::xyBoxed(Vector const &v1, Vector const &v2,
Vector const &x) {
auto const minmax0 = std::minmax(v1[0], v2[0]);
auto const minmax1 = std::minmax(v1[1], v2[1]);
if (minmax0.first - 1e-14 * cuboidGeometry.lengthScale > x[0] or
x[0] > minmax0.second + 1e-14 * cuboidGeometry.lengthScale)
return false;
if (minmax1.first - 1e-14 * cuboidGeometry.lengthScale > x[1] or
x[1] > minmax1.second + 1e-14 * cuboidGeometry.lengthScale)
return false;
return true;
}
template <class GridView>
template <class Vector>
bool MyFaces<GridView>::xyBetween(Vector const &v1, Vector const &v2,
Vector const &x) {
return xyCollinear(v1, v2, x) && xyBoxed(v1, v2, x);
}
template <class GridView>
MyFaces<GridView>::MyFaces(GridView const &gridView, CuboidGeometry const &cuboidGeometry_)
:
#if MY_DIM == 3
lower(gridView),
right(gridView),
upper(gridView),
left(gridView),
front(gridView),
back(gridView),
#else
lower(gridView),
right(gridView),
upper(gridView),
left(gridView),
#endif
cuboidGeometry(cuboidGeometry_)
{
lower.insertFacesByProperty([&](typename GridView::Intersection const &in) {
return xyBetween(cuboidGeometry.A, cuboidGeometry.B, in.geometry().center());
});
right.insertFacesByProperty([&](typename GridView::Intersection const &in) {
return xyBetween(cuboidGeometry.B, cuboidGeometry.C, in.geometry().center());
});
upper.insertFacesByProperty([&](typename GridView::Intersection const &in) {
return xyBetween(cuboidGeometry.D, cuboidGeometry.C, in.geometry().center());
});
left.insertFacesByProperty([&](typename GridView::Intersection const &in) {
return xyBetween(cuboidGeometry.A, cuboidGeometry.D, in.geometry().center());
});
#if MY_DIM == 3
front.insertFacesByProperty([&](typename GridView::Intersection const &in) {
return isClose(cuboidGeometry.depth / 2.0, in.geometry().center()[2]);
});
back.insertFacesByProperty([&](typename GridView::Intersection const &in) {
return isClose(-cuboidGeometry.depth / 2.0, in.geometry().center()[2]);
});
#endif
}
double computeAdmissibleDiameter(double distance, double smallestDiameter, double lengthScale) {
return (distance / 0.0125 / lengthScale + 1.0) * smallestDiameter;
}
template <class Grid, class LocalVector>
void refine(Grid &grid, ConvexPolyhedron<LocalVector> const &weakPatch,
double smallestDiameter, double lengthScale) {
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 * lengthScale);
auto const admissibleDiameter =
computeAdmissibleDiameter(weakeningRegionDistance, smallestDiameter, lengthScale);
if (diameter(geometry) <= admissibleDiameter)
continue;
needRefine = true;
grid.mark(1, e);
}
if (!needRefine)
break;
grid.preAdapt();
grid.adapt();
grid.postAdapt();
}
}
#include "mygrids_tmpl.cc"
#ifndef SRC_MULTI_BODY_PROBLEM_DATA_MYGRIDS_HH
#define SRC_MULTI_BODY_PROBLEM_DATA_MYGRIDS_HH
#include <dune/common/fmatrix.hh>
#include <dune/grid/common/gridfactory.hh>
#include <dune/fufem/boundarypatch.hh>
#include <dune/fufem/geometry/convexpolyhedron.hh>
#include "cuboidgeometry.hh"
template <class GridView> struct MyFaces {
BoundaryPatch<GridView> lower;
BoundaryPatch<GridView> right;
BoundaryPatch<GridView> upper;
BoundaryPatch<GridView> left;
#if MY_DIM == 3
BoundaryPatch<GridView> front;
BoundaryPatch<GridView> back;
#endif
MyFaces(GridView const &gridView, CuboidGeometry const &cuboidGeometry_);
private:
CuboidGeometry const &cuboidGeometry;
bool isClose(double a, double b) {
return std::abs(a - b) < 1e-14 * cuboidGeometry.lengthScale;
};
bool isClose2(double a, double b) {
return std::abs(a - b) <
1e-14 * cuboidGeometry.lengthScale * cuboidGeometry.lengthScale;
};
template <class Vector>
bool xyBoxed(Vector const &v1, Vector const &v2, Vector const &x);
template <class Vector>
bool xyCollinear(Vector const &a, Vector const &b, Vector const &c);
template <class Vector>
bool xyBetween(Vector const &v1, Vector const &v2, Vector const &x);
};
class SimplexManager {
public:
using SimplexList = std::vector<std::vector<unsigned int>>;
#if MY_DIM == 3
SimplexManager(unsigned int shift);
#endif
void addFromVerticesFBB(unsigned int U, unsigned int V, unsigned int W);
void addFromVerticesFFB(unsigned int U, unsigned int V, unsigned int W);
SimplexList const &getSimplices();
private:
SimplexList simplices_;
#if MY_DIM == 3
unsigned int const shift_;
#endif
};
template <class Grid> class GridsConstructor {
public:
GridsConstructor(std::vector<std::shared_ptr<CuboidGeometry>> const &cuboidGeometries_);
std::vector<std::shared_ptr<Grid>>& getGrids();
template <class GridView>
MyFaces<GridView> constructFaces(GridView const &gridView, CuboidGeometry const &cuboidGeometry);
private:
std::vector<std::shared_ptr<CuboidGeometry>> const &cuboidGeometries;
std::vector<Dune::GridFactory<Grid>> gridFactories;
std::vector<std::shared_ptr<Grid>> grids;
};
double computeAdmissibleDiameter(double distance, double smallestDiameter, double lengthScale);
template <class Grid, class LocalVector>
void refine(Grid &grid, ConvexPolyhedron<LocalVector> const &weakPatch,
double smallestDiameter, double lengthScale);
#endif
#ifndef MY_DIM
#error MY_DIM unset
#endif
#include "../explicitgrid.hh"
#include "../explicitvectors.hh"
#include "cuboidgeometry.hh"
template class GridsConstructor<Grid>;
template struct MyFaces<GridView>;
template struct MyFaces<LevelGridView>;
template MyFaces<GridView> GridsConstructor<Grid>::constructFaces(
GridView const &gridView, CuboidGeometry const &CuboidGeometry_);
template MyFaces<LevelGridView> GridsConstructor<Grid>::constructFaces(
LevelGridView const &gridView, CuboidGeometry const &CuboidGeometry_);
template void refine<Grid, LocalVector>(
Grid &grid, ConvexPolyhedron<LocalVector> const &weakPatch,
double smallestDiameter, double lengthScale);
#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_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>
#include <dune/common/parametertree.hh>
#include "cuboidgeometry.hh"
class SegmentedFunction
: public Dune::VirtualFunction<Dune::FieldVector<double, MY_DIM>,
Dune::FieldVector<double, 1>> {
private:
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, MY_DIM> const &z) const {
return liesBelow(MyGeometry::K, MyGeometry::M, z);
};
double const _v1;
double const _v2;
public:
SegmentedFunction(double v1, double v2) : _v1(v1), _v2(v2) {}
void evaluate(Dune::FieldVector<double, MY_DIM> const &x,
Dune::FieldVector<double, 1> &y) const {
y = insideRegion2(x) ? _v2 : _v1;
}
};
#endif
#ifndef SRC_MULTI_BODY_PROBLEM_DATA_WEAKPATCH_HH
#define SRC_MULTI_BODY_PROBLEM_DATA_WEAKPATCH_HH
#include "cuboidgeometry.hh"
template <class LocalVector>
ConvexPolyhedron<LocalVector> getWeakPatch(Dune::ParameterTree const &parset, CuboidGeometry const &cuboidGeometry) {
ConvexPolyhedron<LocalVector> weakPatch;
#if MY_DIM == 3
weakPatch.vertices.resize(4);
weakPatch.vertices[0] = weakPatch.vertices[2] = cuboidGeometry.X;
weakPatch.vertices[1] = weakPatch.vertices[3] = cuboidGeometry.Y;
for (size_t k = 0; k < 2; ++k) {
weakPatch.vertices[k][2] = -cuboidGeometry.depth / 2.0;
weakPatch.vertices[k + 2][2] = cuboidGeometry.depth / 2.0;
}
switch (parset.get<Config::PatchType>("patchType")) {
case Config::Rectangular:
break;
case Config::Trapezoidal:
weakPatch.vertices[1][0] += 0.05 * cuboidGeometry.lengthScale;
weakPatch.vertices[3][0] -= 0.05 * cuboidGeometry.lengthScale;
break;
default:
assert(false);
}
#else
weakPatch.vertices.resize(2);
weakPatch.vertices[0] = cuboidGeometry.X;
weakPatch.vertices[1] = cuboidGeometry.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 <memory>
#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/contact/common/deformedcontinuacomplex.hh>
#include <dune/contact/common/couplingpair.hh>
#include <dune/contact/assemblers/nbodyassembler.hh>
//#include <dune/contact/assemblers/dualmortarcoupling.hh>
#include <dune/contact/projections/normalprojection.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 "multi-body-problem-data/bc.hh"
#include "multi-body-problem-data/mybody.hh"
#include "multi-body-problem-data/cuboidgeometry.hh"
#include "multi-body-problem-data/myglobalfrictiondata.hh"
#include "multi-body-problem-data/mygrids.hh"
#include "multi-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"
// for getcwd
#include <unistd.h>
#include <dune/grid/io/file/vtk/vtkwriter.hh>
#define USE_OLD_TNNMG
size_t const dims = MY_DIM;
template <class GridView>
void writeToVTK(const GridView& gridView, const std::string path, const std::string name) {
Dune::VTKWriter<GridView> vtkwriter(gridView);
//std::ofstream lStream( "garbage.txt" );
std::streambuf* lBufferOld = std::cout.rdbuf();
//std::cout.rdbuf(lStream.rdbuf());
vtkwriter.pwrite(name, path, path);
std::cout.rdbuf( lBufferOld );
}
Dune::ParameterTree getParameters(int argc, char *argv[]) {
Dune::ParameterTree parset;
Dune::ParameterTreeParser::readINITree("/home/mi/podlesny/software/dune/dune-tectonic/src/multi-body-problem.cfg", parset);
Dune::ParameterTreeParser::readINITree(
Dune::Fufem::formatString("/home/mi/podlesny/software/dune/dune-tectonic/src/multi-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);
char buffer[256];
char *val = getcwd(buffer, sizeof(buffer));
if (val) {
std::cout << buffer << std::endl;
std::cout << argv[0] << std::endl;
}
auto const parset = getParameters(argc, argv);
using MyAssembler = MyAssembler<LeafGridView, dims>;
using Matrix = MyAssembler::Matrix;
using Vector = MyAssembler::Vector;
using LocalVector = Vector::block_type;
using ScalarMatrix = MyAssembler::ScalarMatrix;
using ScalarVector = MyAssembler::ScalarVector;
using field_type = Matrix::field_type;
// set up material properties of all bodies
MyBody<dims> const body(parset);
// set up cuboid geometries
const size_t bodyCount = parset.get<int>("problem.bodyCount");
std::vector<std::shared_ptr<CuboidGeometry>> cuboidGeometries(bodyCount);
double const length = 1.00;
double const width = 0.27;
double const weakLength = 0.20;
#if MY_DIM == 3
double const depth = 0.60;
// TODO: replace with make_shared
cuboidGeometries[0] = std::shared_ptr<CuboidGeometry>(new CuboidGeometry({0,0,0}, {0.2,width,0}, weakLength, length, width, depth));
for (size_t i=1; i<bodyCount; i++) {
cuboidGeometries[i] = std::shared_ptr<CuboidGeometry>(new CuboidGeometry(cuboidGeometries[i-1]->D, {0.6,i*width,0}, weakLength, length, width, depth));
}
#else
// TODO: replace with make_shared
cuboidGeometries[0] = std::shared_ptr<CuboidGeometry>(new CuboidGeometry({0,0}, {0.2,width}, weakLength, length, width));
for (size_t i=1; i<bodyCount; i++) {
cuboidGeometries[i] = std::shared_ptr<CuboidGeometry>(new CuboidGeometry(cuboidGeometries[i-1]->D, {0.6,i*width}, weakLength, length, width));
}
#endif
// set up (deformed) grids
GridsConstructor<Grid> gridConstructor(cuboidGeometries);
auto& grids = gridConstructor.getGrids();
using DeformedGridComplex = DeformedContinuaComplex<Grid, Vector>;
using DeformedGrid = DeformedGridComplex::DeformedGridType;
Dune::Contact::DeformedContinuaComplex<Grid, Vector> deformedGrids(grids);
using LeafGridView = DeformedGrid::LeafGridView;
using LevelGridView = DeformedGrid::LevelGridView;
std::vector<std::shared_ptr<LeafGridView>> leafViews(deformedGrids.size());
std::vector<std::shared_ptr<LevelGridView>> levelViews(deformedGrids.size());
std::vector<int> leafVertexCounts(deformedGrids.size());
using LeafFaces = MyFaces<LeafGridView>;
using LevelFaces = MyFaces<LevelGridView>;
std::vector<std::shared_ptr<LeafFaces>> leafFaces(deformedGrids.size());
std::vector<std::shared_ptr<LevelFaces>> levelFaces(deformedGrids.size());
std::vector<ConvexPolyhedron<LocalVector>> weakPatches(deformedGrids.size());
for (size_t i=0; i<deformedGrids.size(); i++) {
auto const &cuboidGeometry = *cuboidGeometries[i];
// define weak patch and refine grid
weakPatches[i] = getWeakPatch<LocalVector>(parset.sub("boundary.friction.weakening"), cuboidGeometry);
refine(*grids[i], weakPatch, parset.get<double>("boundary.friction.smallestDiameter"), cuboidGeometry.lengthScale);
writeToVTK(grids[i]->leafGridView(), "", "grid" + std::to_string(i));
// determine minDiameter and maxDiameter
double minDiameter = std::numeric_limits<double>::infinity();
double maxDiameter = 0.0;
for (auto &&e : elements(grids[i]->leafGridView())) {
auto const geometry = e.geometry();
auto const diam = diameter(geometry);
minDiameter = std::min(minDiameter, diam);
maxDiameter = std::max(maxDiameter, diam);
}
std::cout << "Grid" << i << " min diameter: " << minDiameter << std::endl;
std::cout << "Grid" << i << " max diameter: " << maxDiameter << std::endl;
leafViews[i] = std::make_shared<LeafGridView>(grids[i]->leafGridView());
levelViews[i] = std::make_shared<LevelGridView>(grids[i]->levelGridView(0));
leafVertexCounts[i] = leafViews[i]->size(dims);
leafFaces[i] = std::make_shared<LeafFaces>(*leafViews[i], cuboidGeometry);
levelFaces[i] = std::make_shared<LevelFaces>(*levelViews[i], cuboidGeometry);
}
// set up contact couplings
using LeafBoundaryPatch = BoundaryPatch<LeafGridView>;
using LevelBoundaryPatch = BoundaryPatch<LevelGridView>;
using CouplingPair = Dune::Contact::CouplingPair<DeformedGrid, DeformedGrid, field_type>;
std::vector<std::shared_ptr<CouplingPair>> couplings(bodyCount-1);
for (size_t i=0; i<couplings.size(); i++) {
auto nonmortarPatch = std::make_shared<LevelBoundaryPatch>(levelFaces[i]->upper);
auto mortarPatch = std::make_shared<LevelBoundaryPatch>(levelFaces[i+1]->lower);
auto contactProjection = std::make_shared<Dune::Contact::NormalProjection<LeafBoundaryPatch>>();
std::shared_ptr<CouplingPair::BackEndType> backend = nullptr;
couplings[i]->set(i, i+1, nonmortarPatch, mortarPatch, 0.1, Dune::Contact::CouplingPairBase::STICK_SLIP, contactProjection, backend);
}
// set up dune-contact nBodyAssembler
std::vector<const DeformedGrid*> const_grids(bodyCount);
for (size_t i=0; i<const_grids.size(); i++) {
const_grids[i] = grids[i].get();
}
Dune::Contact::NBodyAssembler<DeformedGrid, Vector> nBodyAssembler(bodyCount, bodyCount-1);
nBodyAssembler.setGrids(const_grids);
for (size_t i=0; i<couplings.size(); i++) {
nBodyAssembler.setCoupling(*couplings[i], i);
}
nBodyAssembler.assembleTransferOperator();
nBodyAssembler.assembleObstacle();
// set up boundary conditions
std::vector<BoundaryPatch<LeafGridView>> neumannBoundaries(bodyCount);
std::vector<BoundaryPatch<LeafGridView>> frictionalBoundaries(bodyCount);
std::vector<BoundaryPatch<LeafGridView>> surfaces(bodyCount);
// Dirichlet boundary
std::vector<Dune::BitSetVector<dims>> noNodes(bodyCount);
std::vector<Dune::BitSetVector<dims>> dirichletNodes(bodyCount);
// set up functions for time-dependent boundary conditions
using Function = Dune::VirtualFunction<double, double>;
const Function& velocityDirichletFunction = VelocityDirichletCondition();
const Function& neumannFunction = NeumannCondition();
for (size_t i=0; i<grids.size(); i++) {
const auto& leafVertexCount = leafVertexCounts[i];
std::cout << "Grid" << i << " Number of DOFs: " << leafVertexCount << std::endl;
// Neumann boundary
auto& neumannBoundary = neumannBoundaries[i];
neumannBoundary = BoundaryPatch<LeafGridView>(*leafViews[i]);
// friction boundary
auto& frictionalBoundary = frictionalBoundaries[i];
if (i==0) {
frictionalBoundary = BoundaryPatch<LeafGridView>(leafFaces[i]->upper);
} else if (i==bodyCount-1) {
frictionalBoundary = BoundaryPatch<LeafGridView>(leafFaces[i]->lower);
} else {
frictionalBoundary = BoundaryPatch<LeafGridView>(leafFaces[i]->lower);
frictionalBoundary.addPatch(BoundaryPatch<LeafGridView>(leafFaces[i]->upper));
}
//surfaces[i] = BoundaryPatch<GridView>(myFaces.upper);
// TODO: Dirichlet Boundary
noNodes[i] = Dune::BitSetVector<dims>(leafVertexCount);
dirichletNodes[i] = Dune::BitSetVector<dims>(leafVertexCount);
auto& gridDirichletNodes = dirichletNodes[i];
for (int j=0; j<leafVertexCount; j++) {
if (leafFaces[i]->right.containsVertex(j))
gridDirichletNodes[j][0] = true;
if (leafFaces[i]->lower.containsVertex(j))
gridDirichletNodes[j][0] = true;
#if MY_DIM == 3
if (leafFaces[i]->front.containsVertex(j) || leafFaces[i]->back.containsVertex(j))
gridDirichletNodes[j][2] = true;
#endif
}
}
// set up individual assemblers for each body, assemble problem (matrices, forces, rhs)
std::vector<std::shared_ptr<MyAssembler>> assemblers(bodyCount);
Matrices<Matrix> matrices(bodyCount);
std::vector<Vector> gravityFunctionals(bodyCount);
std::vector<std::function<void(double, Vector&)>> externalForces(bodyCount);
for (size_t i=0; i<assemblers.size(); i++) {
auto& assembler = assemblers[i];
assembler = std::make_shared<MyAssembler>(*leafViews[i]);
assembler->assembleElasticity(body.getYoungModulus(), body.getPoissonRatio(), *matrices.elasticity[i]);
assembler->assembleViscosity(body.getShearViscosityField(), body.getBulkViscosityField(), *matrices.damping[i]);
assembler->assembleMass(body.getDensityField(), *matrices.mass[i]);
ScalarMatrix relativeFrictionalBoundaryMass;
assembler->assembleFrictionalBoundaryMass(frictionalBoundaries[i], relativeFrictionalBoundaryMass);
relativeFrictionalBoundaryMass /= frictionalBoundaries[i].area();
EnergyNorm<ScalarMatrix, ScalarVector> const stateEnergyNorm(relativeFrictionalBoundaryMass);
// assemble forces
assembler->assembleBodyForce(body.getGravityField(), gravityFunctionals[i]);
// Problem formulation: right-hand side
externalForces[i] =
[&](double _relativeTime, Vector &_ell) {
assembler->assembleNeumann(neumannBoundaries[i], _ell, neumannFunction,
_relativeTime);
_ell += gravityFunctionals[i];
};
}
/* Jonny 2bcontact
// make dirichlet bitfields containing dirichlet information for both grids
int size = rhs[0].size() + rhs[1].size();
Dune::BitSetVector<dims> totalDirichletNodes(size);
for (size_t i=0; i<dirichletNodes[0].size(); i++)
for (int j=0; j<dims; j++)
totalDirichletNodes[i][j] = dirichletNodes[0][i][j];
int offset = rhs[0].size();
for (size_t i=0; i<dirichletNodes[1].size(); i++)
for (int j=0; j<dims; j++)
totalDirichletNodes[offset + i][j] = dirichletNodes[1][i][j];
// assemble separate linear elasticity problems
std::array<MatrixType,2> stiffnessMatrix;
std::array<const MatrixType*, 2> submat;
for (size_t i=0; i<2; i++) {
OperatorAssembler<P1Basis,P1Basis> globalAssembler(*p1Basis[i],*p1Basis[i]);
double s = (i==0) ? E0 : E1;
StVenantKirchhoffAssembler<GridType, P1Basis::LocalFiniteElement, P1Basis::LocalFiniteElement> localAssembler(s, nu);
globalAssembler.assemble(localAssembler, stiffnessMatrix[i]);
submat[i] = &stiffnessMatrix[i];
}
MatrixType bilinearForm;
contactAssembler.assembleJacobian(submat, bilinearForm);
*/
using MyProgramState = ProgramState<Vector, ScalarVector>;
MyProgramState programState(leafVertexCounts);
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, leafVertexCounts)
: nullptr;*/
/*
if (firstRestart > 0) // automatically adjusts the time and timestep
restartIO->read(firstRestart, programState);
else
programState.setupInitialConditions(parset, nBodyAssembler, externalForces,
matrices, assemblers, dirichletNodes,
noNodes, frictionalBoundaries, body);
*/
// assemble friction
std::vector<std::shared_ptr<MyGlobalFrictionData<LocalVector>>> frictionInfo(weakPatches.size());
std::vector<std::shared_ptr<GlobalFriction<Matrix, Vector>>> globalFriction(weakPatches.size());
for (size_t i=0; i<frictionInfo.size(); i++) {
frictionInfo[i] = std::make_shared<MyGlobalFrictionData<LocalVector>>(parset.sub("boundary.friction"), weakPatches[i]);
globalFriction[i] = assemblers[i]->assembleFrictionNonlinearity(parset.get<Config::FrictionModel>("boundary.friction.frictionModel"), frictionalBoundary, frictionInfo, programState.weightedNormalStress);
globalFriction[i]->updateAlpha(programState.alpha[i]);
}
/*
Vector vertexCoordinates(leafVertexCount);
{
Dune::MultipleCodimMultipleGeomTypeMapper<
GridView, Dune::MCMGVertexLayout> const vertexMapper(leafView, Dune::mcmgVertexLayout());
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;
}
}
# -*- mode:conf -*-
gravity = 9.81 # [m/s^2]
[io]
data.write = true
printProgress = false
restarts.first = 0
restarts.spacing= 20
restarts.write = true
vtk.write = false
[problem]
finalTime = 1000 # [s]
bodyCount = 2
[body]
bulkModulus = 0.5e5 # [Pa]
poissonRatio = 0.3 # [1]
[body.elastic]
density = 900 # [kg/m^3]
shearViscosity = 1e3 # [Pas]
bulkViscosity = 1e3 # [Pas]
[body.viscoelastic]
density = 1000 # [kg/m^3]
shearViscosity = 1e4 # [Pas]
bulkViscosity = 1e4 # [Pas]
[boundary.friction]
C = 10 # [Pa]
mu0 = 0.7 # [ ]
V0 = 5e-5 # [m/s]
L = 2.25e-5 # [m]
initialAlpha = 0 # [ ]
stateModel = AgeingLaw
frictionModel = Regularised
[boundary.friction.weakening]
a = 0.002 # [ ]
b = 0.017 # [ ]
[boundary.friction.strengthening]
a = 0.020 # [ ]
b = 0.005 # [ ]
[timeSteps]
scheme = newmark
[u0.solver]
maximumIterations = 100000
verbosity = quiet
[a0.solver]
maximumIterations = 100000
verbosity = quiet
[v.solver]
maximumIterations = 100000
verbosity = quiet
[v.fpi]
maximumIterations = 10000
lambda = 0.5
[solver.tnnmg.linear]
maxiumumIterations = 100000
pre = 3
cycle = 1 # 1 = V, 2 = W, etc.
post = 3
[solver.tnnmg.main]
pre = 1
multi = 5 # number of multigrid steps
post = 0
...@@ -31,9 +31,14 @@ ...@@ -31,9 +31,14 @@
#include <dune/fufem/formatstring.hh> #include <dune/fufem/formatstring.hh>
#include <dune/solvers/norms/energynorm.hh> #include <dune/solvers/norms/energynorm.hh>
/*
#include <dune/solvers/solvers/loopsolver.hh> #include <dune/solvers/solvers/loopsolver.hh>
#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/geocoordinate.hh>
#include <dune/tectonic/myblockproblem.hh> #include <dune/tectonic/myblockproblem.hh>
...@@ -62,13 +67,18 @@ ...@@ -62,13 +67,18 @@
#include "time-stepping/updaters.hh" #include "time-stepping/updaters.hh"
#include "vtk.hh" #include "vtk.hh"
// for getcwd
#include <unistd.h>
#define USE_OLD_TNNMG
size_t const dims = MY_DIM; size_t const dims = MY_DIM;
Dune::ParameterTree getParameters(int argc, char *argv[]) { Dune::ParameterTree getParameters(int argc, char *argv[]) {
Dune::ParameterTree parset; Dune::ParameterTree parset;
Dune::ParameterTreeParser::readINITree("one-body-problem.cfg", parset); Dune::ParameterTreeParser::readINITree("/home/mi/podlesny/software/dune/dune-tectonic/src/one-body-problem.cfg", parset);
Dune::ParameterTreeParser::readINITree( Dune::ParameterTreeParser::readINITree(
Dune::Fufem::formatString("one-body-problem-%dD.cfg", dims), parset); Dune::Fufem::formatString("/home/mi/podlesny/software/dune/dune-tectonic/src/one-body-problem-%dD.cfg", dims), parset);
Dune::ParameterTreeParser::readOptions(argc, argv, parset); Dune::ParameterTreeParser::readOptions(argc, argv, parset);
return parset; return parset;
} }
...@@ -79,6 +89,14 @@ void handleSignal(int signum) { terminationRequested = true; } ...@@ -79,6 +89,14 @@ void handleSignal(int signum) { terminationRequested = true; }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
try { try {
Dune::MPIHelper::instance(argc, argv); Dune::MPIHelper::instance(argc, argv);
char buffer[256];
char *val = getcwd(buffer, sizeof(buffer));
if (val) {
std::cout << buffer << std::endl;
std::cout << argv[0] << std::endl;
}
auto const parset = getParameters(argc, argv); auto const parset = getParameters(argc, argv);
MyGeometry::render(); MyGeometry::render();
...@@ -140,6 +158,7 @@ int main(int argc, char *argv[]) { ...@@ -140,6 +158,7 @@ int main(int argc, char *argv[]) {
#endif #endif
} }
// Set up functions for time-dependent boundary conditions // Set up functions for time-dependent boundary conditions
using Function = Dune::VirtualFunction<double, double>; using Function = Dune::VirtualFunction<double, double>;
Function const &velocityDirichletFunction = VelocityDirichletCondition(); Function const &velocityDirichletFunction = VelocityDirichletCondition();
...@@ -184,8 +203,10 @@ int main(int argc, char *argv[]) { ...@@ -184,8 +203,10 @@ int main(int argc, char *argv[]) {
auto const writeData = parset.get<bool>("io.data.write"); auto const writeData = parset.get<bool>("io.data.write");
bool const handleRestarts = writeRestarts or firstRestart > 0; bool const handleRestarts = writeRestarts or firstRestart > 0;
/*
auto dataFile = auto dataFile =
writeData ? std::make_unique<HDF5::File>("output.h5") : nullptr; writeData ? std::make_unique<HDF5::File>("output.h5") : nullptr;
auto restartFile = handleRestarts auto restartFile = handleRestarts
? std::make_unique<HDF5::File>( ? std::make_unique<HDF5::File>(
"restarts.h5", "restarts.h5",
...@@ -214,7 +235,7 @@ int main(int argc, char *argv[]) { ...@@ -214,7 +235,7 @@ int main(int argc, char *argv[]) {
Vector vertexCoordinates(leafVertexCount); Vector vertexCoordinates(leafVertexCount);
{ {
Dune::MultipleCodimMultipleGeomTypeMapper< Dune::MultipleCodimMultipleGeomTypeMapper<
GridView, Dune::MCMGVertexLayout> const vertexMapper(leafView); GridView, Dune::MCMGVertexLayout> const vertexMapper(leafView, Dune::mcmgVertexLayout());
for (auto &&v : vertices(leafView)) for (auto &&v : vertices(leafView))
vertexCoordinates[vertexMapper.index(v)] = geoToPoint(v.geometry()); vertexCoordinates[vertexMapper.index(v)] = geoToPoint(v.geometry());
} }
...@@ -229,6 +250,7 @@ int main(int argc, char *argv[]) { ...@@ -229,6 +250,7 @@ int main(int argc, char *argv[]) {
MyVTKWriter<MyVertexBasis, typename MyAssembler::CellBasis> const vtkWriter( MyVTKWriter<MyVertexBasis, typename MyAssembler::CellBasis> const vtkWriter(
myAssembler.cellBasis, myAssembler.vertexBasis, "obs"); myAssembler.cellBasis, myAssembler.vertexBasis, "obs");
IterationRegister iterationCount; IterationRegister iterationCount;
auto const report = [&](bool initial = false) { auto const report = [&](bool initial = false) {
if (writeData) { if (writeData) {
...@@ -261,6 +283,7 @@ int main(int argc, char *argv[]) { ...@@ -261,6 +283,7 @@ int main(int argc, char *argv[]) {
}; };
report(true); report(true);
// Set up TNNMG solver // Set up TNNMG solver
using NonlinearFactory = SolverFactory< using NonlinearFactory = SolverFactory<
dims, dims,
...@@ -321,6 +344,8 @@ int main(int argc, char *argv[]) { ...@@ -321,6 +344,8 @@ int main(int argc, char *argv[]) {
break; break;
} }
} }
*/
} catch (Dune::Exception &e) { } catch (Dune::Exception &e) {
Dune::derr << "Dune reported error: " << e << std::endl; Dune::derr << "Dune reported error: " << e << std::endl;
} catch (std::exception &e) { } catch (std::exception &e) {
......
...@@ -3,10 +3,14 @@ ...@@ -3,10 +3,14 @@
#include <dune/common/parametertree.hh> #include <dune/common/parametertree.hh>
#include <dune/matrix-vector/axpy.hh>
#include <dune/fufem/boundarypatch.hh> #include <dune/fufem/boundarypatch.hh>
#include <dune/tnnmg/nonlinearities/zerononlinearity.hh> #include <dune/tnnmg/nonlinearities/zerononlinearity.hh>
#include <dune/tnnmg/problem-classes/blocknonlineartnnmgproblem.hh> #include <dune/tnnmg/problem-classes/blocknonlineartnnmgproblem.hh>
#include <dune/contact/assemblers/nbodyassembler.hh>
#include <dune/tectonic/body.hh> #include <dune/tectonic/body.hh>
#include "assemblers.hh" #include "assemblers.hh"
...@@ -18,32 +22,45 @@ template <class VectorTEMPLATE, class ScalarVectorTEMPLATE> class ProgramState { ...@@ -18,32 +22,45 @@ template <class VectorTEMPLATE, class ScalarVectorTEMPLATE> class ProgramState {
using Vector = VectorTEMPLATE; using Vector = VectorTEMPLATE;
using ScalarVector = ScalarVectorTEMPLATE; using ScalarVector = ScalarVectorTEMPLATE;
ProgramState(int leafVertexCount) ProgramState(const std::vector<int>& leafVertexCounts)
: u(leafVertexCount), : bodyCount(leafVertexCounts.size()) {
v(leafVertexCount), u.resize(bodyCount);
a(leafVertexCount), v.resize(bodyCount);
alpha(leafVertexCount), a.resize(bodyCount);
weightedNormalStress(leafVertexCount) {} alpha.resize(bodyCount);
weightedNormalStress.resize(bodyCount);
for (size_t i=0; i<bodyCount; i++) {
size_t leafVertexCount = leafVertexCounts[i];
u[i].resize(leafVertexCount);
v[i].resize(leafVertexCount);
a[i].resize(leafVertexCount);
alpha[i].resize(leafVertexCount);
weightedNormalStress[i].resize(leafVertexCount);
}
}
// Set up initial conditions // Set up initial conditions
template <class Matrix, class GridView> template <class Matrix, class GridView>
void setupInitialConditions( void setupInitialConditions(
Dune::ParameterTree const &parset, const Dune::ParameterTree& parset,
std::function<void(double, Vector &)> externalForces, const Dune::Contact::NBodyAssembler<typename GridView::Grid, Vector>& nBodyAssembler,
Matrices<Matrix> const matrices, std::vector<std::function<void(double, Vector &)>> externalForces,
MyAssembler<GridView, Vector::block_type::dimension> const &myAssembler, const Matrices<Matrix>& matrices,
Dune::BitSetVector<Vector::block_type::dimension> const &dirichletNodes, const std::vector<std::shared_ptr<MyAssembler<GridView, Vector::block_type::dimension>>>& assemblers,
Dune::BitSetVector<Vector::block_type::dimension> const &noNodes, const std::vector<Dune::BitSetVector<Vector::block_type::dimension>>& dirichletNodes,
BoundaryPatch<GridView> const &frictionalBoundary, const std::vector<Dune::BitSetVector<Vector::block_type::dimension>>& noNodes,
Body<Vector::block_type::dimension> const &body) { const std::vector<BoundaryPatch<GridView>>& frictionalBoundaries,
const Body<Vector::block_type::dimension>& body) {
using LocalVector = typename Vector::block_type; using LocalVector = typename Vector::block_type;
using LocalMatrix = typename Matrix::block_type; using LocalMatrix = typename Matrix::block_type;
auto constexpr dims = LocalVector::dimension; auto constexpr dims = LocalVector::dimension;
/*
// Solving a linear problem with a multigrid solver // Solving a linear problem with a multigrid solver
auto const solveLinearProblem = [&]( auto const solveLinearProblem = [&](
Dune::BitSetVector<dims> const &_dirichletNodes, Matrix const &_matrix, Dune::BitSetVector<dims> const &_dirichletNodes, const std::vector<std::shared_ptr<Matrix>>& _matrix,
Vector const &_rhs, Vector &_x, Vector const &_rhs, Vector &_x,
Dune::ParameterTree const &_localParset) { Dune::ParameterTree const &_localParset) {
...@@ -54,7 +71,7 @@ template <class VectorTEMPLATE, class ScalarVectorTEMPLATE> class ProgramState { ...@@ -54,7 +71,7 @@ template <class VectorTEMPLATE, class ScalarVectorTEMPLATE> class ProgramState {
ZeroNonlinearity<LocalVector, LocalMatrix> zeroNonlinearity; ZeroNonlinearity<LocalVector, LocalMatrix> zeroNonlinearity;
LinearFactory factory(parset.sub("solver.tnnmg"), // FIXME LinearFactory factory(parset.sub("solver.tnnmg"), // FIXME
myAssembler.gridView.grid(), _dirichletNodes); assemblers.gridView.grid(), _dirichletNodes);
typename LinearFactory::ConvexProblem convexProblem( typename LinearFactory::ConvexProblem convexProblem(
1.0, _matrix, zeroNonlinearity, _rhs, _x); 1.0, _matrix, zeroNonlinearity, _rhs, _x);
...@@ -62,7 +79,11 @@ template <class VectorTEMPLATE, class ScalarVectorTEMPLATE> class ProgramState { ...@@ -62,7 +79,11 @@ template <class VectorTEMPLATE, class ScalarVectorTEMPLATE> class ProgramState {
auto multigridStep = factory.getStep(); auto multigridStep = factory.getStep();
multigridStep->setProblem(_x, problem); multigridStep->setProblem(_x, problem);
//multigridStep->setProblem(_x);
EnergyNorm<Matrix, Vector> const norm(_matrix); EnergyNorm<Matrix, Vector> const norm(_matrix);
LoopSolver<Vector> solver( LoopSolver<Vector> solver(
multigridStep.get(), _localParset.get<size_t>("maximumIterations"), multigridStep.get(), _localParset.get<size_t>("maximumIterations"),
_localParset.get<double>("tolerance"), &norm, _localParset.get<double>("tolerance"), &norm,
...@@ -71,17 +92,28 @@ template <class VectorTEMPLATE, class ScalarVectorTEMPLATE> class ProgramState { ...@@ -71,17 +92,28 @@ template <class VectorTEMPLATE, class ScalarVectorTEMPLATE> class ProgramState {
solver.preprocess(); solver.preprocess();
solver.solve(); solver.solve();
Vector totalX = multigridStep->getSol();
// cleanup
delete(multigridStep);
nBodyAssembler.postprocess(totalX, x);
}; };
*/
timeStep = 0; timeStep = 0;
relativeTime = 0.0; relativeTime = 0.0;
relativeTau = 1e-6; relativeTau = 1e-6;
Vector ell0(u.size()); std::vector<Vector> ell0(bodyCount);
externalForces(relativeTime, ell0); for (size_t i=0; i<bodyCount; i++) {
// Initial velocity
v[i] = 0.0;
// Initial velocity ell0[i].resize(u[i].size());
v = 0.0; externalForces[i](relativeTime, ell0[i]);
}
// Initial displacement: Start from a situation of minimal stress, // Initial displacement: Start from a situation of minimal stress,
// which is automatically attained in the case [v = 0 = a]. // which is automatically attained in the case [v = 0 = a].
...@@ -91,29 +123,35 @@ template <class VectorTEMPLATE, class ScalarVectorTEMPLATE> class ProgramState { ...@@ -91,29 +123,35 @@ template <class VectorTEMPLATE, class ScalarVectorTEMPLATE> class ProgramState {
// Initial acceleration: Computed in agreement with Ma = ell0 - Au // Initial acceleration: Computed in agreement with Ma = ell0 - Au
// (without Dirichlet constraints), again assuming dPhi(v = 0) = 0 // (without Dirichlet constraints), again assuming dPhi(v = 0) = 0
Vector accelerationRHS = ell0; std::vector<Vector> accelerationRHS = ell0;
Arithmetic::subtractProduct(accelerationRHS, matrices.elasticity, u); for (size_t i=0; i<bodyCount; i++) {
solveLinearProblem(noNodes, matrices.mass, accelerationRHS, a, // Initial state
parset.sub("a0.solver")); alpha[i] = parset.get<double>("boundary.friction.initialAlpha");
// Initial normal stress
assemblers[i]->assembleWeightedNormalStress(
frictionalBoundaries[i], weightedNormalStress[i], body.getYoungModulus(),
body.getPoissonRatio(), u[i]);
// Initial state Dune::MatrixVector::subtractProduct(accelerationRHS[i], *matrices.elasticity[i], u[i]);
alpha = parset.get<double>("boundary.friction.initialAlpha"); }
// Initial normal stress solveLinearProblem(noNodes, matrices.mass, accelerationRHS, a,
myAssembler.assembleWeightedNormalStress( parset.sub("a0.solver"));
frictionalBoundary, weightedNormalStress, body.getYoungModulus(),
body.getPoissonRatio(), u);
} }
public: public:
Vector u; std::vector<Vector> u;
Vector v; std::vector<Vector> v;
Vector a; std::vector<Vector> a;
ScalarVector alpha; std::vector<ScalarVector> alpha;
ScalarVector weightedNormalStress; std::vector<ScalarVector> weightedNormalStress;
double relativeTime; double relativeTime;
double relativeTau; double relativeTau;
size_t timeStep; size_t timeStep;
private:
const size_t bodyCount;
}; };
#endif #endif
...@@ -8,6 +8,19 @@ ...@@ -8,6 +8,19 @@
#include <dune/solvers/norms/energynorm.hh> #include <dune/solvers/norms/energynorm.hh>
#include <dune/solvers/solvers/loopsolver.hh> #include <dune/solvers/solvers/loopsolver.hh>
#include <dune/contact/assemblers/nbodyassembler.hh>
#include <dune/contact/common/dualbasisadapter.hh>
#include <dune/localfunctions/lagrange/pqkfactory.hh>
#include <dune/functions/gridfunctions/gridfunction.hh>
#include <dune/geometry/quadraturerules.hh>
#include <dune/geometry/type.hh>
#include <dune/geometry/referenceelements.hh>
#include <dune/fufem/functions/basisgridfunction.hh>
#include "../enums.hh" #include "../enums.hh"
#include "../enumparser.hh" #include "../enumparser.hh"
...@@ -19,11 +32,13 @@ void FixedPointIterationCounter::operator+=( ...@@ -19,11 +32,13 @@ void FixedPointIterationCounter::operator+=(
multigridIterations += other.multigridIterations; multigridIterations += other.multigridIterations;
} }
template <class Factory, class Updaters, class ErrorNorm> template <class DeformedGrid, class Factory, class Updaters, class ErrorNorm>
FixedPointIterator<Factory, Updaters, ErrorNorm>::FixedPointIterator( FixedPointIterator<DeformedGrid, Factory, Updaters, ErrorNorm>::FixedPointIterator(
const Dune::Contact::NBodyAssembler<DeformedGrid, Vector>& nBodyAssembler,
Factory &factory, Dune::ParameterTree const &parset, Factory &factory, Dune::ParameterTree const &parset,
std::shared_ptr<Nonlinearity> globalFriction, ErrorNorm const &errorNorm) std::shared_ptr<Nonlinearity> globalFriction, ErrorNorm const &errorNorm)
: step_(factory.getStep()), : nBodyAssembler_(nBodyAssembler),
step_(factory.getStep()),
parset_(parset), parset_(parset),
globalFriction_(globalFriction), globalFriction_(globalFriction),
fixedPointMaxIterations_(parset.get<size_t>("v.fpi.maximumIterations")), fixedPointMaxIterations_(parset.get<size_t>("v.fpi.maximumIterations")),
...@@ -34,9 +49,9 @@ FixedPointIterator<Factory, Updaters, ErrorNorm>::FixedPointIterator( ...@@ -34,9 +49,9 @@ FixedPointIterator<Factory, Updaters, ErrorNorm>::FixedPointIterator(
verbosity_(parset.get<Solver::VerbosityMode>("v.solver.verbosity")), verbosity_(parset.get<Solver::VerbosityMode>("v.solver.verbosity")),
errorNorm_(errorNorm) {} errorNorm_(errorNorm) {}
template <class Factory, class Updaters, class ErrorNorm> template <class DeformedGrid,class Factory, class Updaters, class ErrorNorm>
FixedPointIterationCounter FixedPointIterationCounter
FixedPointIterator<Factory, Updaters, ErrorNorm>::run( FixedPointIterator<DeformedGrid, Factory, Updaters, ErrorNorm>::run(
Updaters updaters, Matrix const &velocityMatrix, Vector const &velocityRHS, Updaters updaters, Matrix const &velocityMatrix, Vector const &velocityRHS,
Vector &velocityIterate) { Vector &velocityIterate) {
EnergyNorm<Matrix, Vector> energyNorm(velocityMatrix); EnergyNorm<Matrix, Vector> energyNorm(velocityMatrix);
...@@ -46,7 +61,7 @@ FixedPointIterator<Factory, Updaters, ErrorNorm>::run( ...@@ -46,7 +61,7 @@ FixedPointIterator<Factory, Updaters, ErrorNorm>::run(
size_t fixedPointIteration; size_t fixedPointIteration;
size_t multigridIterations = 0; size_t multigridIterations = 0;
ScalarVector alpha; std::vector<ScalarVector> alpha;
updaters.state_->extractAlpha(alpha); updaters.state_->extractAlpha(alpha);
for (fixedPointIteration = 0; fixedPointIteration < fixedPointMaxIterations_; for (fixedPointIteration = 0; fixedPointIteration < fixedPointMaxIterations_;
++fixedPointIteration) { ++fixedPointIteration) {
...@@ -56,15 +71,22 @@ FixedPointIterator<Factory, Updaters, ErrorNorm>::run( ...@@ -56,15 +71,22 @@ FixedPointIterator<Factory, Updaters, ErrorNorm>::run(
velocityRHS, velocityIterate); velocityRHS, velocityIterate);
BlockProblem velocityProblem(parset_, convexProblem); BlockProblem velocityProblem(parset_, convexProblem);
step_->setProblem(velocityIterate, velocityProblem); step_->setProblem(velocityIterate, velocityProblem);
//step_->setProblem(velocityIterate);
velocityProblemSolver.preprocess(); velocityProblemSolver.preprocess();
velocityProblemSolver.solve(); velocityProblemSolver.solve();
multigridIterations += velocityProblemSolver.getResult().iterations; multigridIterations += velocityProblemSolver.getResult().iterations;
Vector v_m; std::vector<Vector> v_m;
updaters.rate_->extractOldVelocity(v_m); updaters.rate_->extractOldVelocity(v_m);
v_m *= 1.0 - lambda_;
Arithmetic::addProduct(v_m, lambda_, velocityIterate); for (size_t i=0; i<v_m.size(); i++) {
v_m[i] *= 1.0 - lambda_;
Arithmetic::addProduct(v_m[i], lambda_, velocityIterate[i]);
}
// compute relative velocities on contact boundaries
relativeVelocities(v_m);
// solve a state problem // solve a state problem
updaters.state_->solve(v_m); updaters.state_->solve(v_m);
...@@ -97,4 +119,270 @@ std::ostream &operator<<(std::ostream &stream, ...@@ -97,4 +119,270 @@ std::ostream &operator<<(std::ostream &stream,
<< ")"; << ")";
} }
template <class DeformedGrid, class Factory, class Updaters, class ErrorNorm>
void FixedPointIterator<DeformedGrid, Factory, Updaters, ErrorNorm>::relativeVelocities(std::vector<Vector>& v_m) const {
// adaptation of DualMortarCoupling::setup()
const size_t dim = DeformedGrid::dimension;
typedef typename DeformedGrid::LeafGridView GridView;
//cache of local bases
typedef Dune::PQkLocalFiniteElementCache<typename DeformedGrid::ctype, field_type, dim,1> FiniteElementCache1;
FiniteElementCache1 cache1;
// cache for the dual functions on the boundary
using DualCache = Dune::Contact::DualBasisAdapter<GridView, field_type>;
std::unique_ptr<DualCache> dualCache;
dualCache = std::make_unique< Dune::Contact::DualBasisAdapterGlobal<GridView, field_type> >();
// define FE grid functions
std::vector<BasisGridFunction<> > gridFunctions(nBodyAssembler_.nGrids());
for (size_t i=0; i<gridFunctions.size(); i++) {
}
const auto& contactCouplings = nBodyAssembler_.getContactCouplings();
for (size_t i=0; i<contactCouplings.size(); i++) {
auto contactCoupling = contactCouplings[i];
auto glue = contactCoupling->getGlue();
// loop over all intersections
for (const auto& rIs : intersections(glue)) {
const auto& inside = rIs.inside();
if (!nonmortarBoundary_.contains(rIs.inside(),rIs.indexInInside()))
continue;
const auto& outside = rIs.outside();
// types of the elements supporting the boundary segments in question
Dune::GeometryType nonmortarEType = inside.type();
Dune::GeometryType mortarEType = outside.type();
const auto& domainRefElement = Dune::ReferenceElements<ctype, dim>::general(nonmortarEType);
const auto& targetRefElement = Dune::ReferenceElements<ctype, dim>::general(mortarEType);
int noOfMortarVec = targetRefElement.size(dim);
Dune::GeometryType nmFaceType = domainRefElement.type(rIs.indexInInside(),1);
Dune::GeometryType mFaceType = targetRefElement.type(rIs.indexInOutside(),1);
// Select a quadrature rule
// 2 in 2d and for integration over triangles in 3d. If one (or both) of the two faces involved
// are quadrilaterals, then the quad order has to be risen to 3 (4).
int quadOrder = 2 + (!nmFaceType.isSimplex()) + (!mFaceType.isSimplex());
const auto& quadRule = Dune::QuadratureRules<ctype, dim-1>::rule(rIs.type(), quadOrder);
const auto& mortarFiniteElement = cache1.get(mortarEType);
dualCache->bind(inside, rIs.indexInInside());
std::vector<Dune::FieldVector<field_type,1> > mortarQuadValues, dualQuadValues;
const auto& rGeom = rIs.geometry();
const auto& rGeomOutside = rIs.geometryOutside();
const auto& rGeomInInside = rIs.geometryInInside();
const auto& rGeomInOutside = rIs.geometryInOutside();
int nNonmortarFaceNodes = domainRefElement.size(rIs.indexInInside(),1,dim);
std::vector<int> nonmortarFaceNodes;
for (int i=0; i<nNonmortarFaceNodes; i++) {
int faceIdxi = domainRefElement.subEntity(rIs.indexInInside(), 1, i, dim);
nonmortarFaceNodes.push_back(faceIdxi);
}
for (const auto& quadPt : quadRule) {
// compute integration element of overlap
ctype integrationElement = rGeom.integrationElement(quadPt.position());
// quadrature point positions on the reference element
Dune::FieldVector<ctype,dim> nonmortarQuadPos = rGeomInInside.global(quadPt.position());
Dune::FieldVector<ctype,dim> mortarQuadPos = rGeomInOutside.global(quadPt.position());
// The current quadrature point in world coordinates
Dune::FieldVector<field_type,dim> nonmortarQpWorld = rGeom.global(quadPt.position());
Dune::FieldVector<field_type,dim> mortarQpWorld = rGeomOutside.global(quadPt.position());;
// the gap direction (normal * gapValue)
Dune::FieldVector<field_type,dim> gapVector = mortarQpWorld - nonmortarQpWorld;
//evaluate all shapefunctions at the quadrature point
//nonmortarFiniteElement.localBasis().evaluateFunction(nonmortarQuadPos,nonmortarQuadValues);
mortarFiniteElement.localBasis().evaluateFunction(mortarQuadPos,mortarQuadValues);
dualCache->evaluateFunction(nonmortarQuadPos,dualQuadValues);
// loop over all Lagrange multiplier shape functions
for (int j=0; j<nNonmortarFaceNodes; j++) {
int globalDomainIdx = indexSet0.subIndex(inside,nonmortarFaceNodes[j],dim);
int rowIdx = globalToLocal[globalDomainIdx];
weakObstacle_[rowIdx][0] += integrationElement * quadPt.weight()
* dualQuadValues[nonmortarFaceNodes[j]] * (gapVector*avNormals[globalDomainIdx]);
// loop over all mortar shape functions
for (int k=0; k<noOfMortarVec; k++) {
int colIdx = indexSet1.subIndex(outside, k, dim);
if (!mortarBoundary_.containsVertex(colIdx))
continue;
// Integrate over the product of two shape functions
field_type mortarEntry = integrationElement* quadPt.weight()* dualQuadValues[nonmortarFaceNodes[j]]* mortarQuadValues[k];
Dune::MatrixVector::addToDiagonal(mortarLagrangeMatrix_[rowIdx][colIdx], mortarEntry);
}
}
}
}
///////////////////////////////////
// reducing nonmortar boundary
/////////////////////////////////
// Get all fine grid boundary segments that are totally covered by the grid-glue segments
typedef std::pair<int,int> Pair;
std::map<Pair,ctype> coveredArea, fullArea;
// initialize with area of boundary faces
for (const auto& bIt : nonmortarBoundary_) {
const Pair p(indexSet0.index(bIt.inside()),bIt.indexInInside());
fullArea[p] = bIt.geometry().volume();
coveredArea[p] = 0;
}
// sum up the remote intersection areas to find out which are totally covered
for (const auto& rIs : intersections(glue))
coveredArea[Pair(indexSet0.index(rIs.inside()),rIs.indexInInside())] += rIs.geometry().volume();
// add all fine grid faces that are totally covered by the contact mapping
for (const auto& bIt : nonmortarBoundary_) {
const auto& inside = bIt.inside();
if(coveredArea[Pair(indexSet0.index(inside),bIt.indexInInside())]/
fullArea[Pair(indexSet0.index(inside),bIt.indexInInside())] >= coveredArea_)
boundaryWithMapping.addFace(inside, bIt.indexInInside());
}
//writeBoundary(boundaryWithMapping,debugPath_ + "relevantNonmortar");
/** \todo replace by all fine grid segments which are totally covered by the RemoteIntersections. */
//for (const auto& rIs : intersections(glue))
// boundaryWithMapping.addFace(rIs.inside(),rIs.indexInInside());
printf("contact mapping could be built for %d of %d boundary segments.\n",
boundaryWithMapping.numFaces(), nonmortarBoundary_.numFaces());
nonmortarBoundary_ = boundaryWithMapping;
mortarBoundary_.setup(gridView1);
for (const auto& rIs : intersections(glue))
if (nonmortarBoundary_.contains(rIs.inside(),rIs.indexInInside()))
mortarBoundary_.addFace(rIs.outside(),rIs.indexInOutside());
// Assemble the diagonal matrix coupling the nonmortar side with the lagrange multiplyers there
assembleNonmortarLagrangeMatrix();
// The weak obstacle vector
weakObstacle_.resize(nonmortarBoundary_.numVertices());
weakObstacle_ = 0;
// ///////////////////////////////////////////////////////////
// Get the occupation structure for the mortar matrix
// ///////////////////////////////////////////////////////////
/** \todo Also restrict mortar indices and don't use the whole grid level. */
Dune::MatrixIndexSet mortarIndices(nonmortarBoundary_.numVertices(), grid1_->size(dim));
// Create mapping from the global set of block dofs to the ones on the contact boundary
std::vector<int> globalToLocal;
nonmortarBoundary_.makeGlobalToLocal(globalToLocal);
// loop over all intersections
for (const auto& rIs : intersections(glue)) {
if (!nonmortarBoundary_.contains(rIs.inside(),rIs.indexInInside()))
continue;
const auto& inside = rIs.inside();
const auto& outside = rIs.outside();
const auto& domainRefElement = Dune::ReferenceElements<ctype, dim>::general(inside.type());
const auto& targetRefElement = Dune::ReferenceElements<ctype, dim>::general(outside.type());
int nDomainVertices = domainRefElement.size(dim);
int nTargetVertices = targetRefElement.size(dim);
for (int j=0; j<nDomainVertices; j++) {
int localDomainIdx = globalToLocal[indexSet0.subIndex(inside,j,dim)];
// if the vertex is not contained in the restricted contact boundary then dismiss it
if (localDomainIdx == -1)
continue;
for (int k=0; k<nTargetVertices; k++) {
int globalTargetIdx = indexSet1.subIndex(outside,k,dim);
if (!mortarBoundary_.containsVertex(globalTargetIdx))
continue;
mortarIndices.add(localDomainIdx, globalTargetIdx);
}
}
}
mortarIndices.exportIdx(mortarLagrangeMatrix_);
// Clear it
mortarLagrangeMatrix_ = 0;
//cache of local bases
FiniteElementCache1 cache1;
std::unique_ptr<DualCache> dualCache;
dualCache = std::make_unique< Dune::Contact::DualBasisAdapterGlobal<GridView0, field_type> >();
std::vector<Dune::FieldVector<ctype,dim> > avNormals;
avNormals = nonmortarBoundary_.getNormals();
}
// ///////////////////////////////////////
// Compute M = D^{-1} \hat{M}
// ///////////////////////////////////////
Dune::BCRSMatrix<MatrixBlock>& M = mortarLagrangeMatrix_;
Dune::BDMatrix<MatrixBlock>& D = nonmortarLagrangeMatrix_;
// First compute D^{-1}
D.invert();
// Then the matrix product D^{-1} \hat{M}
for (auto rowIt = M.begin(); rowIt != M.end(); ++rowIt) {
const auto rowIndex = rowIt.index();
for (auto& entry : *rowIt)
entry.leftmultiply(D[rowIndex][rowIndex]);
}
// weakObstacles in transformed basis = D^{-1}*weakObstacle_
for(size_t rowIdx=0; rowIdx<weakObstacle_.size(); rowIdx++)
weakObstacle_[rowIdx] *= D[rowIdx][rowIdx][0][0];
gridGlueBackend_->clear();
}
#include "fixedpointiterator_tmpl.cc" #include "fixedpointiterator_tmpl.cc"
...@@ -9,20 +9,22 @@ ...@@ -9,20 +9,22 @@
template <class Vector, class Matrix, class Function, int dimension> template <class Vector, class Matrix, class Function, int dimension>
std::shared_ptr<RateUpdater<Vector, Matrix, Function, dimension>> std::shared_ptr<RateUpdater<Vector, Matrix, Function, dimension>>
initRateUpdater(Config::scheme scheme, initRateUpdater(Config::scheme scheme,
Function const &velocityDirichletFunction, const std::vector<Function>& velocityDirichletFunctions,
Dune::BitSetVector<dimension> const &velocityDirichletNodes, const std::vector<Dune::BitSetVector<dimension>>& velocityDirichletNodes,
Matrices<Matrix> const &matrices, Vector const &u_initial, const Matrices<Matrix>& matrices,
Vector const &v_initial, Vector const &a_initial) { const std::vector<Vector>& u_initial,
const std::vector<Vector>& v_initial,
const std::vector<Vector>& a_initial) {
switch (scheme) { switch (scheme) {
case Config::Newmark: case Config::Newmark:
return std::make_shared<Newmark<Vector, Matrix, Function, dimension>>( return std::make_shared<Newmark<Vector, Matrix, Function, dimension>>(
matrices, u_initial, v_initial, a_initial, velocityDirichletNodes, matrices, u_initial, v_initial, a_initial, velocityDirichletNodes,
velocityDirichletFunction); velocityDirichletFunctions);
case Config::BackwardEuler: case Config::BackwardEuler:
return std::make_shared< return std::make_shared<
BackwardEuler<Vector, Matrix, Function, dimension>>( BackwardEuler<Vector, Matrix, Function, dimension>>(
matrices, u_initial, v_initial, a_initial, velocityDirichletNodes, matrices, u_initial, v_initial, a_initial, velocityDirichletNodes,
velocityDirichletFunction); velocityDirichletFunctions);
default: default:
assert(false); assert(false);
} }
......
...@@ -9,8 +9,10 @@ ...@@ -9,8 +9,10 @@
template <class Vector, class Matrix, class Function, int dimension> template <class Vector, class Matrix, class Function, int dimension>
std::shared_ptr<RateUpdater<Vector, Matrix, Function, dimension>> std::shared_ptr<RateUpdater<Vector, Matrix, Function, dimension>>
initRateUpdater(Config::scheme scheme, initRateUpdater(Config::scheme scheme,
Function const &velocityDirichletFunction, const std::vector<Function>& velocityDirichletFunctions,
Dune::BitSetVector<dimension> const &velocityDirichletNodes, const std::vector<Dune::BitSetVector<dimension>>& velocityDirichletNodes,
Matrices<Matrix> const &matrices, Vector const &u_initial, const Matrices<Matrix>& matrices,
Vector const &v_initial, Vector const &a_initial); const std::vector<Vector>& u_initial,
const std::vector<Vector>& v_initial,
const std::vector<Vector>& a_initial);
#endif #endif
#include <dune/solvers/common/arithmetic.hh> #include <dune/matrix-vector/axpy.hh>
#include <dune/istl/matrixindexset.hh>
#include "backward_euler.hh" #include "backward_euler.hh"
template <class Vector, class Matrix, class Function, size_t dim> template <class Vector, class Matrix, class Function, size_t dim>
BackwardEuler<Vector, Matrix, Function, dim>::BackwardEuler( BackwardEuler<Vector, Matrix, Function, dim>::BackwardEuler(
Matrices<Matrix> const &_matrices, Vector const &_u_initial, const Matrices<Matrix>& _matrices, const std::vector<Vector>& _u_initial,
Vector const &_v_initial, Vector const &_a_initial, const std::vector<Vector>& _v_initial, const std::vector<Vector>& _a_initial,
Dune::BitSetVector<dim> const &_dirichletNodes, const std::vector<Dune::BitSetVector<dim>>& _dirichletNodes,
Function const &_dirichletFunction) const std::vector<Function>& _dirichletFunctions)
: RateUpdater<Vector, Matrix, Function, dim>( : RateUpdater<Vector, Matrix, Function, dim>(
_matrices, _u_initial, _v_initial, _a_initial, _dirichletNodes, _matrices, _u_initial, _v_initial, _a_initial, _dirichletNodes,
_dirichletFunction) {} _dirichletFunctions) {}
template <class Vector, class Matrix, class Function, size_t dim> template <class Vector, class Matrix, class Function, size_t dim>
void BackwardEuler<Vector, Matrix, Function, dim>::setup( void BackwardEuler<Vector, Matrix, Function, dim>::setup(const std::vector<Vector>& ell,
Vector const &ell, double _tau, double relativeTime, Vector &rhs, double _tau,
Vector &iterate, Matrix &AM) { double relativeTime,
this->dirichletFunction.evaluate(relativeTime, this->dirichletValue); std::vector<Vector>& rhs, std::vector<Vector>& iterate,
this->tau = _tau; std::vector<Matrix>& AM) {
for (size_t i=0; i<this->u.size(); i++) {
/* We start out with the formulation this->dirichletFunctions[i].evaluate(relativeTime, this->dirichletValues[i]);
this->tau = _tau;
M a + C v + A u = ell
/* We start out with the formulation
Backward Euler means
M a + C v + A u = ell
a1 = 1.0/tau ( v1 - v0 )
u1 = tau v1 + u0 Backward Euler means
in summary, we get at time t=1 a1 = 1.0/tau ( v1 - v0 )
u1 = tau v1 + u0
M [1.0/tau ( v1 - v0 )] + C v1
+ A [tau v1 + u0] = ell in summary, we get at time t=1
or M [1.0/tau ( v1 - v0 )] + C v1
+ A [tau v1 + u0] = ell
1.0/tau M v1 + C v1 + tau A v1
= [1.0/tau M + C + tau A] v1 or
= ell + 1.0/tau M v0 - A u0
*/ 1.0/tau M v1 + C v1 + tau A v1
= [1.0/tau M + C + tau A] v1
// set up LHS (for fixed tau, we'd only really have to do this once) = ell + 1.0/tau M v0 - A u0
{ */
Dune::MatrixIndexSet indices(this->matrices.elasticity.N(),
this->matrices.elasticity.M()); // set up LHS (for fixed tau, we'd only really have to do this once)
indices.import(this->matrices.elasticity); Matrix& LHS = AM[i];
indices.import(this->matrices.mass); {
indices.import(this->matrices.damping); Dune::MatrixIndexSet indices(this->matrices.elasticity[i]->N(),
indices.exportIdx(AM); this->matrices.elasticity[i]->M());
indices.import(*this->matrices.elasticity[i]);
indices.import(*this->matrices.mass[i]);
indices.import(*this->matrices.damping[i]);
indices.exportIdx(LHS);
}
LHS = 0.0;
Dune::MatrixVector::addProduct(LHS, 1.0 / this->tau, *this->matrices.mass[i]);
Dune::MatrixVector::addProduct(LHS, 1.0, *this->matrices.damping[i]);
Dune::MatrixVector::addProduct(LHS, this->tau, *this->matrices.elasticity[i]);
// set up RHS
{
Vector& rhss = rhs[i];
rhss = ell[i];
Dune::MatrixVector::addProduct(rhss, 1.0 / this->tau, *this->matrices.mass[i],
this->v_o[i]);
Dune::MatrixVector::subtractProduct(rhss, *this->matrices.elasticity[i], this->u_o[i]);
}
iterate = this->v_o;
const Dune::BitSetVector<dim>& dirichletNodess = this->dirichletNodes[i];
for (size_t k = 0; k < dirichletNodess.size(); ++k)
for (size_t j = 0; j < dim; ++j)
if (this->dirichletNodes[k][j])
iterate[k][j] = (j == 0) ? this->dirichletValue : 0;
} }
AM = 0.0;
Arithmetic::addProduct(AM, 1.0 / this->tau, this->matrices.mass);
Arithmetic::addProduct(AM, 1.0, this->matrices.damping);
Arithmetic::addProduct(AM, this->tau, this->matrices.elasticity);
// set up RHS
{
rhs = ell;
Arithmetic::addProduct(rhs, 1.0 / this->tau, this->matrices.mass,
this->v_o);
Arithmetic::subtractProduct(rhs, this->matrices.elasticity, this->u_o);
}
iterate = this->v_o;
for (size_t i = 0; i < this->dirichletNodes.size(); ++i)
for (size_t j = 0; j < dim; ++j)
if (this->dirichletNodes[i][j])
iterate[i][j] = (j == 0) ? this->dirichletValue : 0;
} }
template <class Vector, class Matrix, class Function, size_t dim> template <class Vector, class Matrix, class Function, size_t dim>
void BackwardEuler<Vector, Matrix, Function, dim>::postProcess( void BackwardEuler<Vector, Matrix, Function, dim>::postProcess(
Vector const &iterate) { const std::vector<Vector>& iterate) {
this->postProcessCalled = true; this->postProcessCalled = true;
this->v = iterate; this->v = iterate;
this->u = this->u_o; this->u = this->u_o;
Arithmetic::addProduct(this->u, this->tau, this->v);
this->a = this->v; for (size_t i=0; i<this->u.size(); i++) {
this->a -= this->v_o; Dune::MatrixVector::addProduct(this->u[i], this->tau, this->v[i]);
this->a /= this->tau;
Vector& ai = this->a[i];
ai = this->v[i];
ai -= this->v_o[i];
ai /= this->tau;
}
} }
template <class Vector, class Matrix, class Function, size_t dim> template <class Vector, class Matrix, class Function, size_t dim>
......
...@@ -4,14 +4,15 @@ ...@@ -4,14 +4,15 @@
template <class Vector, class Matrix, class Function, size_t dim> template <class Vector, class Matrix, class Function, size_t dim>
class BackwardEuler : public RateUpdater<Vector, Matrix, Function, dim> { class BackwardEuler : public RateUpdater<Vector, Matrix, Function, dim> {
public: public:
BackwardEuler(Matrices<Matrix> const &_matrices, Vector const &_u_initial, BackwardEuler(const Matrices<Matrix> &_matrices, const std::vector<Vector> &_u_initial,
Vector const &_v_initial, Vector const &_a_initial, const std::vector<Vector> &_v_initial, const std::vector<Vector> &_a_initial,
Dune::BitSetVector<dim> const &_dirichletNodes, const std::vector<Dune::BitSetVector<dim> > &_dirichletNodes,
Function const &_dirichletFunction); const std::vector<Function> &_dirichletFunctions);
void setup(Vector const &, double, double, Vector &, Vector &, void setup(const std::vector<Vector>&, double, double, std::vector<Vector>&, std::vector<Vector>&,
Matrix &) override; std::vector<Matrix>&) override;
void postProcess(Vector const &) override;
void postProcess(const std::vector<Vector>&) override;
std::shared_ptr<RateUpdater<Vector, Matrix, Function, dim>> clone() std::shared_ptr<RateUpdater<Vector, Matrix, Function, dim>> clone()
const override; const override;
......
#include <dune/solvers/common/arithmetic.hh> #include <dune/matrix-vector/axpy.hh>
#include <dune/istl/matrixindexset.hh>
#include "newmark.hh" #include "newmark.hh"
template <class Vector, class Matrix, class Function, size_t dim> template <class Vector, class Matrix, class Function, size_t dim>
Newmark<Vector, Matrix, Function, dim>::Newmark( Newmark<Vector, Matrix, Function, dim>::Newmark(
Matrices<Matrix> const &_matrices, Vector const &_u_initial, const Matrices<Matrix>& _matrices, const std::vector<Vector>& _u_initial,
Vector const &_v_initial, Vector const &_a_initial, const std::vector<Vector>& _v_initial, const std::vector<Vector>& _a_initial,
Dune::BitSetVector<dim> const &_dirichletNodes, const std::vector<Dune::BitSetVector<dim>>& _dirichletNodes,
Function const &_dirichletFunction) const std::vector<Function>& _dirichletFunctions)
: RateUpdater<Vector, Matrix, Function, dim>( : RateUpdater<Vector, Matrix, Function, dim>(
_matrices, _u_initial, _v_initial, _a_initial, _dirichletNodes, _matrices, _u_initial, _v_initial, _a_initial, _dirichletNodes,
_dirichletFunction) {} _dirichletFunctions) {}
template <class Vector, class Matrix, class Function, size_t dim> template <class Vector, class Matrix, class Function, size_t dim>
void Newmark<Vector, Matrix, Function, dim>::setup(Vector const &ell, void Newmark<Vector, Matrix, Function, dim>::setup(const std::vector<Vector>& ell,
double _tau, double _tau,
double relativeTime, double relativeTime,
Vector &rhs, Vector &iterate, std::vector<Vector>& rhs, std::vector<Vector>& iterate,
Matrix &AM) { std::vector<Matrix>& AM) {
this->dirichletFunction.evaluate(relativeTime, this->dirichletValue); for (size_t i=0; i<this->u.size(); i++) {
this->tau = _tau; this->dirichletFunctions[i].evaluate(relativeTime, this->dirichletValues[i]);
this->tau = _tau;
/* We start out with the formulation /* We start out with the formulation
M a + C v + A u = ell M a + C v + A u = ell
...@@ -41,58 +43,64 @@ void Newmark<Vector, Matrix, Function, dim>::setup(Vector const &ell, ...@@ -41,58 +43,64 @@ void Newmark<Vector, Matrix, Function, dim>::setup(Vector const &ell,
= [2/tau M + C + tau/2 A] v1 = [2/tau M + C + tau/2 A] v1
= ell + 2/tau M v0 + M a0 = ell + 2/tau M v0 + M a0
- tau/2 A v0 - A u0 - tau/2 A v0 - A u0
*/ */
// set up LHS (for fixed tau, we'd only really have to do this once) // set up LHS (for fixed tau, we'd only really have to do this once)
{ Matrix& LHS = AM[i];
Dune::MatrixIndexSet indices(this->matrices.elasticity.N(), {
this->matrices.elasticity.M()); Dune::MatrixIndexSet indices(this->matrices.elasticity[i]->N(),
indices.import(this->matrices.elasticity); this->matrices.elasticity[i]->M());
indices.import(this->matrices.mass); indices.import(*this->matrices.elasticity[i]);
indices.import(this->matrices.damping); indices.import(*this->matrices.mass[i]);
indices.exportIdx(AM); indices.import(*this->matrices.damping[i]);
indices.exportIdx(LHS);
}
LHS = 0.0;
Dune::MatrixVector::addProduct(LHS, 2.0 / this->tau, *this->matrices.mass[i]);
Dune::MatrixVector::addProduct(LHS, 1.0, *this->matrices.damping[i]);
Dune::MatrixVector::addProduct(LHS, this->tau / 2.0, *this->matrices.elasticity[i]);
// set up RHS
{
Vector& rhss = rhs[i];
rhss = ell[i];
Dune::MatrixVector::addProduct(rhss, 2.0 / this->tau, *this->matrices.mass[i],
this->v_o[i]);
Dune::MatrixVector::addProduct(rhss, *this->matrices.mass[i], this->a_o[i]);
Dune::MatrixVector::subtractProduct(rhss, this->tau / 2.0, *this->matrices.elasticity[i],
this->v_o[i]);
Dune::MatrixVector::subtractProduct(rhss, *this->matrices.elasticity[i], this->u_o[i]);
}
iterate = this->v_o;
const Dune::BitSetVector<dim>& dirichletNodess = this->dirichletNodes[i];
for (size_t k = 0; k < dirichletNodess.size(); ++k)
for (size_t j = 0; j < dim; ++j)
if (this->dirichletNodess[k][j])
iterate[k][j] = (j == 0) ? this->dirichletValue : 0;
} }
AM = 0.0;
Arithmetic::addProduct(AM, 2.0 / this->tau, this->matrices.mass);
Arithmetic::addProduct(AM, 1.0, this->matrices.damping);
Arithmetic::addProduct(AM, this->tau / 2.0, this->matrices.elasticity);
// set up RHS
{
rhs = ell;
Arithmetic::addProduct(rhs, 2.0 / this->tau, this->matrices.mass,
this->v_o);
Arithmetic::addProduct(rhs, this->matrices.mass, this->a_o);
Arithmetic::subtractProduct(rhs, this->tau / 2.0, this->matrices.elasticity,
this->v_o);
Arithmetic::subtractProduct(rhs, this->matrices.elasticity, this->u_o);
}
iterate = this->v_o;
for (size_t i = 0; i < this->dirichletNodes.size(); ++i)
for (size_t j = 0; j < dim; ++j)
if (this->dirichletNodes[i][j])
iterate[i][j] = (j == 0) ? this->dirichletValue : 0;
} }
template <class Vector, class Matrix, class Function, size_t dim> template <class Vector, class Matrix, class Function, size_t dim>
void Newmark<Vector, Matrix, Function, dim>::postProcess( void Newmark<Vector, Matrix, Function, dim>::postProcess(const std::vector<Vector>& iterate) {
Vector const &iterate) {
this->postProcessCalled = true; this->postProcessCalled = true;
this->v = iterate; this->v = iterate;
// u1 = tau/2 ( v1 + v0 ) + u0 // u1 = tau/2 ( v1 + v0 ) + u0
this->u = this->u_o; this->u = this->u_o;
Arithmetic::addProduct(this->u, this->tau / 2.0, this->v);
Arithmetic::addProduct(this->u, this->tau / 2.0, this->v_o); for (size_t i=0; i<this->u.size(); i++) {
Dune::MatrixVector::addProduct(this->u[i], this->tau / 2.0, this->v[i]);
// a1 = 2/tau ( v1 - v0 ) - a0 Dune::MatrixVector::addProduct(this->u[i], this->tau / 2.0, this->v_o[i]);
this->a = 0.0;
Arithmetic::addProduct(this->a, 2.0 / this->tau, this->v); // a1 = 2/tau ( v1 - v0 ) - a0
Arithmetic::subtractProduct(this->a, 2.0 / this->tau, this->v_o); this->a[i] = 0.0;
Arithmetic::subtractProduct(this->a, 1.0, this->a_o); Dune::MatrixVector::addProduct(this->a[i], 2.0 / this->tau, this->v[i]);
Dune::MatrixVector::subtractProduct(this->a[i], 2.0 / this->tau, this->v_o[i]);
Dune::MatrixVector::subtractProduct(this->a[i], 1.0, this->a_o[i]);
}
} }
template <class Vector, class Matrix, class Function, size_t dim> template <class Vector, class Matrix, class Function, size_t dim>
......
...@@ -4,14 +4,15 @@ ...@@ -4,14 +4,15 @@
template <class Vector, class Matrix, class Function, size_t dim> template <class Vector, class Matrix, class Function, size_t dim>
class Newmark : public RateUpdater<Vector, Matrix, Function, dim> { class Newmark : public RateUpdater<Vector, Matrix, Function, dim> {
public: public:
Newmark(Matrices<Matrix> const &_matrices, Vector const &_u_initial, Newmark(const Matrices<Matrix>& _matrices, const std::vector<Vector>& _u_initial,
Vector const &_v_initial, Vector const &_a_initial, const std::vector<Vector>& _v_initial, const std::vector<Vector>& _a_initial,
Dune::BitSetVector<dim> const &_dirichletNodes, const std::vector<Dune::BitSetVector<dim>>& _dirichletNodes,
Function const &_dirichletFunction); const std::vector<Function>& _dirichletFunctions);
void setup(Vector const &, double, double, Vector &, Vector &, void setup(const std::vector<Vector>&, double, double, std::vector<Vector>&, std::vector<Vector>&,
Matrix &) override; std::vector<Matrix>&) override;
void postProcess(Vector const &) override;
void postProcess(const std::vector<Vector>&) override;
std::shared_ptr<RateUpdater<Vector, Matrix, Function, dim>> clone() std::shared_ptr<RateUpdater<Vector, Matrix, Function, dim>> clone()
const override; const override;
......
...@@ -6,16 +6,16 @@ ...@@ -6,16 +6,16 @@
template <class Vector, class Matrix, class Function, size_t dim> template <class Vector, class Matrix, class Function, size_t dim>
RateUpdater<Vector, Matrix, Function, dim>::RateUpdater( RateUpdater<Vector, Matrix, Function, dim>::RateUpdater(
Matrices<Matrix> const &_matrices, Vector const &_u_initial, const Matrices<Matrix>& _matrices, const std::vector<Vector>& _u_initial,
Vector const &_v_initial, Vector const &_a_initial, const std::vector<Vector>& _v_initial, const std::vector<Vector>& _a_initial,
Dune::BitSetVector<dim> const &_dirichletNodes, const std::vector<Dune::BitSetVector<dim>>& _dirichletNodes,
Function const &_dirichletFunction) const std::vector<Function>& _dirichletFunctions)
: matrices(_matrices), : matrices(_matrices),
u(_u_initial), u(_u_initial),
v(_v_initial), v(_v_initial),
a(_a_initial), a(_a_initial),
dirichletNodes(_dirichletNodes), dirichletNodes(_dirichletNodes),
dirichletFunction(_dirichletFunction) {} dirichletFunctions(_dirichletFunctions) {}
template <class Vector, class Matrix, class Function, size_t dim> template <class Vector, class Matrix, class Function, size_t dim>
void RateUpdater<Vector, Matrix, Function, dim>::nextTimeStep() { void RateUpdater<Vector, Matrix, Function, dim>::nextTimeStep() {
...@@ -26,17 +26,15 @@ void RateUpdater<Vector, Matrix, Function, dim>::nextTimeStep() { ...@@ -26,17 +26,15 @@ void RateUpdater<Vector, Matrix, Function, dim>::nextTimeStep() {
} }
template <class Vector, class Matrix, class Function, size_t dim> template <class Vector, class Matrix, class Function, size_t dim>
void RateUpdater<Vector, Matrix, Function, dim>::extractDisplacement( void RateUpdater<Vector, Matrix, Function, dim>::extractDisplacement(std::vector<Vector>& displacements) const {
Vector &displacement) const {
if (!postProcessCalled) if (!postProcessCalled)
DUNE_THROW(Dune::Exception, "It seems you forgot to call postProcess!"); DUNE_THROW(Dune::Exception, "It seems you forgot to call postProcess!");
displacement = u; displacements = u;
} }
template <class Vector, class Matrix, class Function, size_t dim> template <class Vector, class Matrix, class Function, size_t dim>
void RateUpdater<Vector, Matrix, Function, dim>::extractVelocity( void RateUpdater<Vector, Matrix, Function, dim>::extractVelocity(std::vector<Vector>& velocity) const {
Vector &velocity) const {
if (!postProcessCalled) if (!postProcessCalled)
DUNE_THROW(Dune::Exception, "It seems you forgot to call postProcess!"); DUNE_THROW(Dune::Exception, "It seems you forgot to call postProcess!");
...@@ -44,14 +42,12 @@ void RateUpdater<Vector, Matrix, Function, dim>::extractVelocity( ...@@ -44,14 +42,12 @@ void RateUpdater<Vector, Matrix, Function, dim>::extractVelocity(
} }
template <class Vector, class Matrix, class Function, size_t dim> template <class Vector, class Matrix, class Function, size_t dim>
void RateUpdater<Vector, Matrix, Function, dim>::extractOldVelocity( void RateUpdater<Vector, Matrix, Function, dim>::extractOldVelocity(std::vector<Vector>& oldVelocity) const {
Vector &oldVelocity) const {
oldVelocity = v_o; oldVelocity = v_o;
} }
template <class Vector, class Matrix, class Function, size_t dim> template <class Vector, class Matrix, class Function, size_t dim>
void RateUpdater<Vector, Matrix, Function, dim>::extractAcceleration( void RateUpdater<Vector, Matrix, Function, dim>::extractAcceleration(std::vector<Vector>& acceleration) const {
Vector &acceleration) const {
if (!postProcessCalled) if (!postProcessCalled)
DUNE_THROW(Dune::Exception, "It seems you forgot to call postProcess!"); DUNE_THROW(Dune::Exception, "It seems you forgot to call postProcess!");
......