From db42041f0ca3a9871bcaf52d4f8e392ce842cc0e Mon Sep 17 00:00:00 2001 From: Elias Pipping <elias.pipping@fu-berlin.de> Date: Wed, 22 Oct 2014 15:33:27 +0200 Subject: [PATCH] [Algorit] Grid and patch construction overhaul (1) Determine distance from patch properly (also in general polygon cases) (2) Move refine() (3) Rewrite the logic of the patch (allow it to be a polygon) --- dune/tectonic/closestpointprojection.hh | 114 ----------- src/distances.hh | 33 +++ src/polyhedrondistance.hh | 215 ++++++++++++++++++++ src/sand-wedge-data/myglobalfrictiondata.hh | 15 +- src/sand-wedge-data/mygrid.cc | 35 ++++ src/sand-wedge-data/mygrid.hh | 9 + src/sand-wedge-data/mygrid_tmpl.cc | 5 + src/sand-wedge-data/patchfunction.hh | 31 +-- src/sand-wedge-data/weakpatch.hh | 21 ++ src/sand-wedge.cc | 77 +------ 10 files changed, 344 insertions(+), 211 deletions(-) delete mode 100644 dune/tectonic/closestpointprojection.hh create mode 100644 src/distances.hh create mode 100644 src/polyhedrondistance.hh create mode 100644 src/sand-wedge-data/weakpatch.hh diff --git a/dune/tectonic/closestpointprojection.hh b/dune/tectonic/closestpointprojection.hh deleted file mode 100644 index 75a513e9..00000000 --- a/dune/tectonic/closestpointprojection.hh +++ /dev/null @@ -1,114 +0,0 @@ -// Based on the class from dune-contact - -#ifndef CLOSEST_POINT_PROJECTION_HH -#define CLOSEST_POINT_PROJECTION_HH - -template <class Coordinate> struct BoundarySegment { - int nVertices; - std::vector<Coordinate> vertices; -}; - -template <class Coordinate> -Coordinate computeClosestPoint(const Coordinate &target, - const BoundarySegment<Coordinate> &segment, - int gaussSeidelIterations) { - /** - * The functional to be minimized is: 0.5*norm(\sum_i lambda_i corner_i - - *target)^2 - * where lambda_i are barycentric coordinates, i.e. 0\leq lambda_i \leq 1 and - *\sum_i lambda_i=1 - * - * The resulting quadratic minimization problem is given by 0.5 - *Lambda^T*A*Lambda - l^T*Lambda - * with - * A_ij = (corner_i,corner_j) and l_i = (corner_i, target) - */ - int nCorners = segment.nVertices; - double A[nCorners][nCorners]; - - for (int i = 0; i < nCorners; i++) - for (int j = 0; j <= i; j++) - A[i][j] = segment.vertices[i] * segment.vertices[j]; - - // make symmetric - for (int i = 0; i < nCorners; i++) - for (int j = i + 1; j < nCorners; j++) - A[i][j] = A[j][i]; - - std::vector<double> l(nCorners); - for (int i = 0; i < nCorners; i++) - l[i] = target * segment.vertices[i]; - - // choose a feasible initial solution - std::vector<double> sol(nCorners); - for (int i = 0; i < nCorners; i++) - sol[i] = 1.0 / nCorners; - - // use a Gauß-Seidel like method for possibly non-convex quadratic problems - // with simplex constraints. - for (int i = 0; i < gaussSeidelIterations; i++) { - - // compute the residual - std::vector<double> rhs = l; - - // compute rhs -= A*sol_ - for (int k = 0; k < nCorners; k++) - for (int j = 0; j < nCorners; j++) - rhs[k] -= A[k][j] * sol[j]; - - // use the edge vectors as search directions - double alpha = 0.0; - for (int j1 = 0; j1 < (nCorners - 1); ++j1) - for (int j2 = j1 + 1; j2 < nCorners; ++j2) { - // compute matrix entry and rhs for edge direction - double a = A[j1][j1] - A[j1][j2] - A[j2][j1] + A[j2][j2]; - double b = rhs[j1] - rhs[j2]; - - // compute minimizer for correction - if (a > 0) { - alpha = b / a; - // project alpha such that we stay positiv - if ((sol[j2] - alpha) < -1e-14) { - alpha = sol[j2]; - } else if ((alpha < -1e-14) && ((sol[j1] + alpha) < -1e-14)) { - alpha = -sol[j1]; - } - } else { - // if concave the minimum is achieved at one of the boundaries, - // i.e. at sol_[j2] or -sol_[j1] - - double sum = sol[j1] + sol[j2]; - - double lValue = 0.5 * A[j1][j1] * sum * sum - rhs[j1] * sum; - double uValue = 0.5 * A[j2][j2] * sum * sum - rhs[j2] * sum; - - alpha = (lValue < uValue) ? sol[j2] : -sol[j1]; - } - // apply correction - sol[j1] += alpha; - sol[j2] -= alpha; - - // update the local residual for corrections - for (int p = 0; p < nCorners; p++) - rhs[p] -= (A[p][j1] - A[p][j2]) * alpha; - } - } - - double eps = 1e-5; - double sum = 0; - for (size_t i = 0; i < sol.size(); i++) { - if (sol[i] < -eps) - DUNE_THROW(Dune::Exception, "No barycentric coords " << sol[1] << " nr. " - << i); - sum += sol[i]; - } - if (sum > 1 + eps) - DUNE_THROW(Dune::Exception, "No barycentric coords, sum: " << sum); - - Coordinate projected(0); - for (int i = 0; i < nCorners; i++) - projected.axpy(sol[i], segment.vertices[i]); - - return projected; -} -#endif diff --git a/src/distances.hh b/src/distances.hh new file mode 100644 index 00000000..2f01e5ab --- /dev/null +++ b/src/distances.hh @@ -0,0 +1,33 @@ +#ifndef SRC_DISTANCES_HH +#define SRC_DISTANCES_HH + +#include "polyhedrondistance.hh" +#include "sand-wedge-data/mygeometry.hh" + +template <class Geometry> double diameter(Geometry const &geometry) { + auto const numCorners = geometry.corners(); + std::vector<typename Geometry::GlobalCoordinate> corners(numCorners); + + double diameter = 0.0; + for (int i = 0; i < numCorners; ++i) { + corners[i] = geometry.corner(i); + for (int j = 0; j < i; ++j) + diameter = std::max(diameter, (corners[i] - corners[j]).two_norm()); + } + return diameter; +} + +template <class Geometry> +double distanceToWeakeningRegion( + Geometry const &g, + ConvexPolyhedron<typename Geometry::GlobalCoordinate> const &weakPatch) { + using Coordinate = typename Geometry::GlobalCoordinate; + + ConvexPolyhedron<Coordinate> bsg; + bsg.vertices.resize(g.corners()); + for (size_t i = 0; i < bsg.vertices.size(); ++i) + bsg.vertices[i] = g.corner(i); + + return distance(bsg, weakPatch, 1e-6 * MyGeometry::lengthScale); +} +#endif diff --git a/src/polyhedrondistance.hh b/src/polyhedrondistance.hh new file mode 100644 index 00000000..885735f6 --- /dev/null +++ b/src/polyhedrondistance.hh @@ -0,0 +1,215 @@ +#ifndef SRC_POLYHEDRONDISTANCE_HH +#define SRC_POLYHEDRONDISTANCE_HH + +// Based on the closest point projection from dune-contact + +#include <dune/common/dynmatrix.hh> +#include <dune/solvers/common/arithmetic.hh> + +template <class Coordinate> struct ConvexPolyhedron { + std::vector<Coordinate> vertices; + + template <class DynamicVector> + Coordinate barycentricToGlobal(DynamicVector const &b) const { + assert(b.size() == vertices.size()); + Coordinate r(0); + for (size_t i = 0; i < b.size(); i++) + Arithmetic::addProduct(r, b[i], vertices[i]); + return r; + } + + template <class DynamicVector> + void sanityCheck(DynamicVector const &b, double tol) const { + double sum = 0; + for (size_t i = 0; i < b.size(); i++) { + if (b[i] < -tol) + DUNE_THROW(Dune::Exception, "No barycentric coords " << b[1] << " nr. " + << i); + sum += b[i]; + } + if (sum > 1 + tol) + DUNE_THROW(Dune::Exception, "No barycentric coords, sum: " << sum); + } +}; + +template <class Coordinate, class Matrix> +void populateMatrix(ConvexPolyhedron<Coordinate> const &segment, + Matrix &matrix) { + size_t const nCorners = segment.vertices.size(); + for (size_t i = 0; i < nCorners; i++) + for (size_t j = 0; j <= i; j++) + matrix[i][j] = segment.vertices[i] * segment.vertices[j]; + // make symmetric + for (size_t i = 0; i < nCorners; i++) + for (size_t j = i + 1; j < nCorners; j++) + matrix[i][j] = matrix[j][i]; +} + +/** + * The functional to be minimized is + * + * 0.5*norm(\sum_i lambda_i corner_i - target)^2 + * + * where lambda_i are barycentric coordinates, i.e. + * + * 0 \le lambda_i \le 1 and \sum_i lambda_i=1 + * + * The resulting quadratic minimization problem is given by + * + * 0.5 lambda^T*A*lambda - l^T*lambda + * + * with A_ij = (corner_i,corner_j) and l_i = (corner_i, target) + */ +template <class Coordinate> +void approximate(Coordinate const &target, Dune::DynamicMatrix<double> const &A, + Dune::DynamicVector<double> const &l, + ConvexPolyhedron<Coordinate> const &segment, + Dune::DynamicVector<double> &sol) { + size_t nCorners = segment.vertices.size(); + + // compute the residual + Dune::DynamicVector<double> rhs = l; + // compute rhs -= A*sol_ + for (size_t k = 0; k < nCorners; k++) + for (size_t j = 0; j < nCorners; j++) + rhs[k] -= A[k][j] * sol[j]; + + // use the edge vectors as search directions + double alpha = 0.0; + for (size_t j1 = 0; j1 < nCorners - 1; ++j1) { + for (size_t j2 = j1 + 1; j2 < nCorners; ++j2) { + // compute matrix entry and rhs for edge direction + double a = A[j1][j1] - A[j1][j2] - A[j2][j1] + A[j2][j2]; + double b = rhs[j1] - rhs[j2]; + + // compute minimizer for correction + if (a > 0) { + alpha = b / a; + + double const largestAlpha = sol[j2]; + double const smallestAlpha = -sol[j1]; + + // project alpha such that we stay positive + if (alpha > largestAlpha) + alpha = largestAlpha; + else if (alpha < smallestAlpha) + alpha = smallestAlpha; + } else { + // if the quadratic term vanishes, we have a linear function, which + // attains its extrema on the boundary + double sum = sol[j1] + sol[j2]; + + double lValue = 0.5 * A[j1][j1] * sum * sum - rhs[j1] * sum; + double uValue = 0.5 * A[j2][j2] * sum * sum - rhs[j2] * sum; + + alpha = lValue < uValue ? sol[j2] : -sol[j1]; + } + // apply correction + sol[j1] += alpha; + sol[j2] -= alpha; + + // update the local residual for corrections + for (size_t p = 0; p < nCorners; p++) + rhs[p] -= (A[p][j1] - A[p][j2]) * alpha; + } + } +} + +// Point-to-Polyhedron +template <class Coordinate> +double distance(const Coordinate &target, + const ConvexPolyhedron<Coordinate> &segment, + double correctionTolerance) { + size_t nCorners = segment.vertices.size(); + double const barycentricTolerance = 1e-14; + + Dune::DynamicMatrix<double> A(nCorners, nCorners); + populateMatrix(segment, A); + + Dune::DynamicVector<double> l(nCorners); + for (size_t i = 0; i < nCorners; i++) + l[i] = target * segment.vertices[i]; + + // choose a feasible initial solution + Dune::DynamicVector<double> sol(nCorners); + for (size_t i = 0; i < nCorners; i++) + sol[i] = 1.0 / nCorners; + + Coordinate oldCoordinates = segment.barycentricToGlobal(sol); + Coordinate newCoordinates; + + size_t maxIterations = 1000; + size_t iterations; + for (iterations = 0; iterations < maxIterations; ++iterations) { + approximate(target, A, l, segment, sol); + + newCoordinates = segment.barycentricToGlobal(sol); + if ((oldCoordinates - newCoordinates).two_norm() < correctionTolerance) + break; + + oldCoordinates = newCoordinates; + } + assert(iterations < maxIterations); + + segment.sanityCheck(sol, barycentricTolerance); + return (target - newCoordinates).two_norm(); +} + +// Polyhedron-to-Polyhedron +template <class Coordinate> +double distance(const ConvexPolyhedron<Coordinate> &s1, + const ConvexPolyhedron<Coordinate> &s2, + double valueCorrectionTolerance) { + size_t nCorners1 = s1.vertices.size(); + size_t nCorners2 = s2.vertices.size(); + double const barycentricTolerance = 1e-14; + + // choose feasible initial solutions + Dune::DynamicVector<double> sol1(nCorners1); + for (size_t i = 0; i < s1.vertices.size(); i++) + sol1[i] = 1.0 / s1.vertices.size(); + auto c1 = s1.barycentricToGlobal(sol1); + + Dune::DynamicVector<double> sol2(nCorners2); + for (size_t i = 0; i < nCorners2; i++) + sol2[i] = 1.0 / nCorners2; + auto c2 = s2.barycentricToGlobal(sol2); + + double oldDistance = (c2 - c1).two_norm(); + + Dune::DynamicMatrix<double> A1(nCorners1, nCorners1); + populateMatrix(s1, A1); + + Dune::DynamicMatrix<double> A2(nCorners2, nCorners2); + populateMatrix(s2, A2); + + size_t maxIterations = 1000; + size_t iterations; + for (iterations = 0; iterations < maxIterations; ++iterations) { + Dune::DynamicVector<double> l2(nCorners2); + for (size_t i = 0; i < nCorners2; i++) + l2[i] = c1 * s2.vertices[i]; + + approximate(c1, A2, l2, s2, sol2); + c2 = s2.barycentricToGlobal(sol2); + + Dune::DynamicVector<double> l1(nCorners1); + for (size_t i = 0; i < nCorners1; i++) + l1[i] = c2 * s1.vertices[i]; + approximate(c2, A1, l1, s1, sol1); + c1 = s1.barycentricToGlobal(sol1); + + double const newDistance = (c2 - c1).two_norm(); + assert(newDistance - oldDistance <= 1e-12); // debugging + if (oldDistance - newDistance <= valueCorrectionTolerance) { + s1.sanityCheck(sol1, barycentricTolerance); + s2.sanityCheck(sol2, barycentricTolerance); + return newDistance; + } + + oldDistance = newDistance; + } + assert(false); +} + +#endif diff --git a/src/sand-wedge-data/myglobalfrictiondata.hh b/src/sand-wedge-data/myglobalfrictiondata.hh index 64db619c..2b14abce 100644 --- a/src/sand-wedge-data/myglobalfrictiondata.hh +++ b/src/sand-wedge-data/myglobalfrictiondata.hh @@ -2,27 +2,26 @@ #define SRC_SAND_WEDGE_DATA_MYGLOBALFRICTIONDATA_HH #include <dune/common/function.hh> -#include <dune/common/fvector.hh> #include <dune/tectonic/globalfrictiondata.hh> -#include "mygeometry.hh" #include "patchfunction.hh" -template <int dimension> -class MyGlobalFrictionData : public GlobalFrictionData<dimension> { +template <class LocalVector> +class MyGlobalFrictionData : public GlobalFrictionData<LocalVector::dimension> { private: - using typename GlobalFrictionData<dimension>::VirtualFunction; + using typename GlobalFrictionData<LocalVector::dimension>::VirtualFunction; public: - MyGlobalFrictionData(Dune::ParameterTree const &parset) + MyGlobalFrictionData(Dune::ParameterTree const &parset, + ConvexPolyhedron<LocalVector> const &segment) : C_(parset.get<double>("C")), L_(parset.get<double>("L")), V0_(parset.get<double>("V0")), a_(parset.get<double>("strengthening.a"), - parset.get<double>("weakening.a")), + parset.get<double>("weakening.a"), segment), b_(parset.get<double>("strengthening.b"), - parset.get<double>("weakening.b")), + parset.get<double>("weakening.b"), segment), mu0_(parset.get<double>("mu0")) {} double virtual const &C() const override { return C_; } diff --git a/src/sand-wedge-data/mygrid.cc b/src/sand-wedge-data/mygrid.cc index 604d2db6..aa4175cb 100644 --- a/src/sand-wedge-data/mygrid.cc +++ b/src/sand-wedge-data/mygrid.cc @@ -4,6 +4,7 @@ #include "mygrid.hh" #include "midpoint.hh" +#include "../distances.hh" #if MY_DIM == 3 SimplexManager::SimplexManager(unsigned int shift) : shift_(shift) {} @@ -187,4 +188,38 @@ MyFaces<GridView>::MyFaces(GridView const &gridView) }); } +double computeAdmissibleDiameter(double distance, double smallestDiameter) { + return (distance / 0.0125 / MyGeometry::lengthScale + 1.0) * smallestDiameter; +} + +template <class Grid, class LocalVector> +void refine(Grid &grid, ConvexPolyhedron<LocalVector> const &weakPatch, + double smallestDiameter) { + bool needRefine = true; + while (true) { + needRefine = false; + for (auto it = grid.template leafbegin<0>(); + it != grid.template leafend<0>(); ++it) { + auto const geometry = it->geometry(); + + auto const weakeningRegionDistance = + distanceToWeakeningRegion(geometry, weakPatch); + auto const admissibleDiameter = + computeAdmissibleDiameter(weakeningRegionDistance, smallestDiameter); + + if (diameter(geometry) <= admissibleDiameter) + continue; + + needRefine = true; + grid.mark(1, *it); + } + if (!needRefine) + break; + + grid.preAdapt(); + grid.adapt(); + grid.postAdapt(); + } +} + #include "mygrid_tmpl.cc" diff --git a/src/sand-wedge-data/mygrid.hh b/src/sand-wedge-data/mygrid.hh index 2a208eca..01b17053 100644 --- a/src/sand-wedge-data/mygrid.hh +++ b/src/sand-wedge-data/mygrid.hh @@ -11,6 +11,8 @@ #include <dune/fufem/boundarypatch.hh> #pragma clang diagnostic pop +#include "../polyhedrondistance.hh" + #include "mygeometry.hh" template <class GridView> struct MyFaces { @@ -78,4 +80,11 @@ template <class Grid> class GridConstructor { private: Dune::GridFactory<Grid> gridFactory; }; + +double computeAdmissibleDiameter(double distance, double smallestDiameter); + +template <class Grid, class LocalVector> +void refine(Grid &grid, ConvexPolyhedron<LocalVector> const &weakPatch, + double smallestDiameter); + #endif diff --git a/src/sand-wedge-data/mygrid_tmpl.cc b/src/sand-wedge-data/mygrid_tmpl.cc index 0ffd11dc..c076d610 100644 --- a/src/sand-wedge-data/mygrid_tmpl.cc +++ b/src/sand-wedge-data/mygrid_tmpl.cc @@ -3,6 +3,7 @@ #endif #include "explicitgrid.hh" +#include "explicitvectors.hh" template class GridConstructor<Grid>; @@ -10,3 +11,7 @@ template struct MyFaces<GridView>; template MyFaces<GridView> GridConstructor<Grid>::constructFaces( GridView const &gridView); + +template void refine<Grid, LocalVector>( + Grid &grid, ConvexPolyhedron<LocalVector> const &weakPatch, + double smallestDiameter); diff --git a/src/sand-wedge-data/patchfunction.hh b/src/sand-wedge-data/patchfunction.hh index 864ee8c8..25099d52 100644 --- a/src/sand-wedge-data/patchfunction.hh +++ b/src/sand-wedge-data/patchfunction.hh @@ -5,36 +5,27 @@ #include <dune/common/fvector.hh> #include <dune/common/parametertree.hh> +#include "../polyhedrondistance.hh" + class PatchFunction : public Dune::VirtualFunction<Dune::FieldVector<double, MY_DIM>, Dune::FieldVector<double, 1>> { private: - bool static isBetween(double x, double lower, double upper) { - return lower <= x and x <= upper; - } + using Polyhedron = ConvexPolyhedron<Dune::FieldVector<double, MY_DIM>>; - bool static isClose(double a, double b) { - return std::abs(a - b) < MyGeometry::lengthScale * 1e-14; - }; - - bool insideRegion2(Dune::FieldVector<double, MY_DIM> const &z) const { - assert(isClose(0, z[1])); - return isBetween(z[0], _X[0], _Y[0]); - } - - Dune::FieldVector<double, MY_DIM> const &_X; - Dune::FieldVector<double, MY_DIM> const &_Y; - - double const _v1; - double const _v2; + double const v1_; + double const v2_; + Polyhedron const &segment_; public: - PatchFunction(double v1, double v2) - : _X(MyGeometry::X), _Y(MyGeometry::Y), _v1(v1), _v2(v2) {} + 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 = insideRegion2(x) ? _v2 : _v1; + y = distance(x, segment_, 1e-6 * MyGeometry::lengthScale) <= 1e-5 ? v2_ + : v1_; } }; + #endif diff --git a/src/sand-wedge-data/weakpatch.hh b/src/sand-wedge-data/weakpatch.hh new file mode 100644 index 00000000..a6162ebe --- /dev/null +++ b/src/sand-wedge-data/weakpatch.hh @@ -0,0 +1,21 @@ +#ifndef SRC_SAND_WEDGE_DATA_WEAKPATCH_HH +#define SRC_SAND_WEDGE_DATA_WEAKPATCH_HH + +template <class LocalVector> ConvexPolyhedron<LocalVector> getWeakPatch() { + ConvexPolyhedron<LocalVector> weakPatch; +#if MY_DIM == 3 + weakPatch.vertices.resize(4); + weakPatch.vertices[0] = weakPatch.vertices[2] = MyGeometry::X; + weakPatch.vertices[1] = weakPatch.vertices[3] = MyGeometry::Y; + for (size_t k = 0; k < 2; ++k) { + weakPatch.vertices[k][2] = -MyGeometry::depth / 2.0; + weakPatch.vertices[k + 2][2] = MyGeometry::depth / 2.0; + } +#else + weakPatch.vertices.resize(2); + weakPatch.vertices[0] = MyGeometry::X; + weakPatch.vertices[1] = MyGeometry::Y; +#endif + return weakPatch; +}; +#endif diff --git a/src/sand-wedge.cc b/src/sand-wedge.cc index fcb31bdd..042ad384 100644 --- a/src/sand-wedge.cc +++ b/src/sand-wedge.cc @@ -58,6 +58,7 @@ #include "assemblers.hh" #include "tobool.hh" #include "coupledtimestepper.hh" +#include "distances.hh" #include "enumparser.hh" #include "enums.hh" #include "fixedpointiterator.hh" @@ -68,6 +69,7 @@ #include "sand-wedge-data/myglobalfrictiondata.hh" #include "sand-wedge-data/mygrid.hh" #include "sand-wedge-data/special_writer.hh" +#include "sand-wedge-data/weakpatch.hh" #include "solverfactory.hh" #include "state.hh" #include "timestepping.hh" @@ -82,47 +84,6 @@ void initPython() { Python::run("sys.path.append('" datadir "')"); } -template <class Geometry> double diameter(Geometry const &geometry) { - auto const numCorners = geometry.corners(); - std::vector<typename Geometry::GlobalCoordinate> corners(numCorners); - for (int i = 0; i < numCorners; ++i) - corners[i] = geometry.corner(i); - - TwoNorm<typename Geometry::GlobalCoordinate> twoNorm; - - double diameter = 0.0; - for (int i = 0; i < numCorners; ++i) - for (int j = 0; j < i; ++j) - diameter = std::max(diameter, twoNorm.diff(corners[i], corners[j])); - return diameter; -} - -#include <dune/tectonic/closestpointprojection.hh> - -// we assume the weakening region to be a line segment for now -template <class Geometry> double distanceToWeakeningRegion(Geometry const &g) { - TwoNorm<typename Geometry::GlobalCoordinate> twoNorm; - - BoundarySegment<typename Geometry::GlobalCoordinate> bs; - bs.nVertices = 2; - bs.vertices.resize(bs.nVertices); - bs.vertices[0] = MyGeometry::X; - bs.vertices[1] = MyGeometry::Y; - - double distance = std::numeric_limits<double>::infinity(); - auto const numCorners = g.corners(); - for (int i = 0; i < numCorners; ++i) { - auto const corner = g.corner(i); - auto const projection = computeClosestPoint(corner, bs, 10); // FIXME - distance = std::min(distance, twoNorm.diff(corner, projection)); - } - return distance; -} - -double computeAdmissibleDiameter(double distance, double smallestDiameter) { - return (distance / 0.0125 / MyGeometry::lengthScale + 1.0) * smallestDiameter; -} - int main(int argc, char *argv[]) { try { Dune::ParameterTree parset; @@ -142,38 +103,15 @@ int main(int argc, char *argv[]) { using ScalarVector = MyAssembler::ScalarVector; using LocalScalarVector = ScalarVector::block_type; + auto weakPatch = getWeakPatch<LocalVector>(); + // {{{ Set up grid GridConstructor<Grid> gridConstructor; auto grid = gridConstructor.getGrid(); - auto const smallestDiameter = - parset.get<double>("boundary.friction.smallestDiameter"); - bool needRefine = true; - - while (true) { - needRefine = false; - for (auto it = grid->template leafbegin<0>(); - it != grid->template leafend<0>(); ++it) { - auto const geometry = it->geometry(); - - auto const weakeningRegionDistance = - distanceToWeakeningRegion(geometry); - auto const admissibleDiameter = computeAdmissibleDiameter( - weakeningRegionDistance, smallestDiameter); - - if (diameter(geometry) <= admissibleDiameter) - continue; + refine(*grid, weakPatch, + parset.get<double>("boundary.friction.smallestDiameter")); - needRefine = true; - grid->mark(1, *it); - } - if (!needRefine) - break; - - grid->preAdapt(); - grid->adapt(); - grid->postAdapt(); - } auto const refinements = grid->maxLevel(); double minDiameter = std::numeric_limits<double>::infinity(); @@ -318,7 +256,8 @@ int main(int argc, char *argv[]) { myAssembler.assembleNormalStress(frictionalBoundary, normalStress, body.getYoungModulus(), body.getPoissonRatio(), u_initial); - MyGlobalFrictionData<dims> frictionInfo(parset.sub("boundary.friction")); + MyGlobalFrictionData<LocalVector> frictionInfo( + parset.sub("boundary.friction"), weakPatch); auto myGlobalFriction = myAssembler.assembleFrictionNonlinearity( parset.get<Config::FrictionModel>("boundary.friction.frictionModel"), frictionalBoundary, frictionInfo, normalStress); -- GitLab