Skip to content
Snippets Groups Projects
stackedblocksfactory.cc 10.2 KiB
Newer Older
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <dune/fufem/geometry/convexpolyhedron.hh>

#include <dune/contact/projections/normalprojection.hh>

podlesny's avatar
podlesny committed
#include "../problem-data/bc.hh"
#include "../problem-data/grid/cuboidgeometry.hh"
#include "../problem-data/myglobalfrictiondata.hh"
podlesny's avatar
podlesny committed
#include "../utils/diameter.hh"

#include "stackedblocksfactory.hh"


podlesny's avatar
.  
podlesny committed
template <class HostGridType, class VectorType>
void StackedBlocksFactory<HostGridType, VectorType>::setBodies() {

    // set up cuboid geometries
    double const length = 1.00;
podlesny's avatar
.  
podlesny committed
    double const height = 0.27;
    double const weakLength = 0.60;
podlesny's avatar
.  
podlesny committed
    std::vector<GlobalCoords> origins(this->bodyCount_);

    const auto& subParset = this->parset_.sub("boundary.friction.weakening");

#if MY_DIM == 3
        double const depth = 0.60;

podlesny's avatar
.  
podlesny committed
        auto weakBound = [&] (const GlobalCoords& origin) {
            GlobalCoords h = {origin[0] + weakLength, origin[1], origin[2]};
            return h;
        };

        origins[0] = {0,0,0};
podlesny's avatar
.  
podlesny committed
        GlobalCoords lowerWeakOrigin = {0.2, 0, 0};
        GlobalCoords upperWeakOrigin = {0.2, height, 0};

        cuboidGeometries_[0] = std::make_shared<CuboidGeometry>(origins[0], length, height, depth);
        cuboidGeometries_[0]->addWeakeningPatch(subParset, upperWeakOrigin, weakBound(upperWeakOrigin));

        for (size_t i=1; i<this->bodyCount_-1; i++) {
podlesny's avatar
.  
podlesny committed
            origins[i] = cuboidGeometries_[i-1]->upperLeft();
            GlobalCoords lowerWeakOrigin_i = lowerWeakOrigin + origins[i];
            GlobalCoords upperWeakOrigin_i = upperWeakOrigin + origins[i];
podlesny's avatar
.  
podlesny committed
            cuboidGeometries_[i] = std::make_shared<CuboidGeometry>(origins[i], length, height, depth);
            cuboidGeometries_[i]->addWeakeningPatch(subParset, upperWeakOrigin_i, weakBound(upperWeakOrigin_i));
            cuboidGeometries_[i]->addWeakeningPatch(subParset, lowerWeakOrigin_i, weakBound(lowerWeakOrigin_i));
podlesny's avatar
.  
podlesny committed

        const size_t idx = this->bodyCount_-1;
podlesny's avatar
.  
podlesny committed
        origins[idx] = cuboidGeometries_[idx-1]->upperLeft();
        lowerWeakOrigin += origins[idx];
podlesny's avatar
.  
podlesny committed
        cuboidGeometries_[idx] = std::make_shared<CuboidGeometry>(origins[idx], length, height, depth);
        cuboidGeometries_[idx]->addWeakeningPatch(subParset, lowerWeakOrigin, weakBound(lowerWeakOrigin));
podlesny's avatar
.  
podlesny committed
        auto weakBound = [&] (const GlobalCoords& origin) {
            GlobalCoords h = {origin[0] + weakLength, origin[1]};
            return h;
        };

        origins[0] = {0,0};
podlesny's avatar
.  
podlesny committed
        GlobalCoords lowerWeakOrigin = {0.2, 0};
        GlobalCoords upperWeakOrigin = {0.2, height};

        cuboidGeometries_[0] = std::make_shared<CuboidGeometry>(origins[0], length, height);
        cuboidGeometries_[0]->addWeakeningPatch(subParset, upperWeakOrigin, weakBound(upperWeakOrigin));

        for (size_t i=1; i<this->bodyCount_-1; i++) {
podlesny's avatar
.  
podlesny committed
            origins[i] = cuboidGeometries_[i-1]->upperLeft();
podlesny's avatar
podlesny committed
            auto height_i = height/3.0;

podlesny's avatar
.  
podlesny committed
            GlobalCoords lowerWeakOrigin_i = lowerWeakOrigin + origins[i];
podlesny's avatar
podlesny committed
            GlobalCoords upperWeakOrigin_i = {upperWeakOrigin[0], height_i};
            upperWeakOrigin_i += origins[i];
podlesny's avatar
podlesny committed
            cuboidGeometries_[i] = std::make_shared<CuboidGeometry>(origins[i], length, height_i);
podlesny's avatar
.  
podlesny committed


            cuboidGeometries_[i]->addWeakeningPatch(subParset, upperWeakOrigin_i, weakBound(upperWeakOrigin_i));
            cuboidGeometries_[i]->addWeakeningPatch(subParset, lowerWeakOrigin_i, weakBound(lowerWeakOrigin_i));
podlesny's avatar
.  
podlesny committed

        const size_t idx = this->bodyCount_-1;
podlesny's avatar
.  
podlesny committed
        origins[idx] = cuboidGeometries_[idx-1]->upperLeft();
        lowerWeakOrigin += origins[idx];
podlesny's avatar
.  
podlesny committed
        cuboidGeometries_[idx] = std::make_shared<CuboidGeometry>(origins[idx], length, height);
        cuboidGeometries_[idx]->addWeakeningPatch(subParset, lowerWeakOrigin, weakBound(lowerWeakOrigin));
#else
#error CuboidGeometry only supports 2D and 3D!"
#endif

    // set up reference grids
podlesny's avatar
.  
podlesny committed
    gridConstructor_ = std::make_unique<GridsConstructor<HostGridType>>(cuboidGeometries_);
    auto& grids = gridConstructor_->getGrids();

    for (size_t i=0; i<this->bodyCount_; i++) {
        const auto& cuboidGeometry = *cuboidGeometries_[i];

        // define weak patch and refine grid
podlesny's avatar
.  
podlesny committed
        const auto& weakeningRegions = cuboidGeometry.weakeningRegions();
        for (size_t j=0; j<weakeningRegions.size(); j++) {
podlesny's avatar
podlesny committed
            refine(*grids[i], weakeningRegions[j], this->parset_.template get<double>("boundary.friction.smallestDiameter"), CuboidGeometry::lengthScale());
podlesny's avatar
.  
podlesny committed
        }

        // 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;
    }

    for (size_t i=0; i<this->bodyCount_; i++) {
podlesny's avatar
.  
podlesny committed
        this->bodies_[i] = std::make_shared<typename Base::LeafBody>(bodyData_, grids[i]);
podlesny's avatar
.  
podlesny committed
template <class HostGridType, class VectorType>
void StackedBlocksFactory<HostGridType, VectorType>::setCouplings() {
    for (size_t i=0; i<this->bodyCount_; i++) {
        const auto& cuboidGeometry = *cuboidGeometries_[i];
podlesny's avatar
.  
podlesny committed

        leafFaces_[i] = std::make_shared<LeafFaces>(this->bodies_[i]->gridView(), cuboidGeometry);
        levelFaces_[i] = std::make_shared<LevelFaces>(this->bodies_[i]->grid()->levelGridView(0), cuboidGeometry);
    }

    auto contactProjection = std::make_shared<Dune::Contact::NormalProjection<LeafBoundaryPatch>>();
podlesny's avatar
.  
podlesny committed
    std::shared_ptr<typename Base::FrictionCouplingPair::BackEndType> backend = nullptr;
podlesny's avatar
.  
podlesny committed


    for (size_t i=0; i<this->couplings_.size(); i++) {
      auto& coupling = this->couplings_[i];
podlesny's avatar
.  
podlesny committed
      coupling = std::make_shared<typename Base::FrictionCouplingPair>();

      nonmortarPatch_[i] = std::make_shared<LevelBoundaryPatch>(levelFaces_[i]->upper);
      mortarPatch_[i] = std::make_shared<LevelBoundaryPatch>(levelFaces_[i+1]->lower);
podlesny's avatar
.  
podlesny committed
      weakPatches_[i] = std::make_shared<WeakeningRegion>(cuboidGeometries_[i]->weakeningRegions()[0]);
podlesny's avatar
.  
podlesny committed
      coupling->set(i, i+1, nonmortarPatch_[i], mortarPatch_[i], 0.1, Base::FrictionCouplingPair::CouplingType::STICK_SLIP, contactProjection, backend);
podlesny's avatar
.  
podlesny committed
      coupling->setWeakeningPatch(weakPatches_[i]);
podlesny's avatar
podlesny committed
      coupling->setFrictionData(std::make_shared<MyGlobalFrictionData<GlobalCoords>>(this->parset_.sub("boundary.friction"), *weakPatches_[i], CuboidGeometry::lengthScale()));
podlesny's avatar
.  
podlesny committed
template <class HostGridType, class VectorType>
void StackedBlocksFactory<HostGridType, VectorType>::setLevelBodies() {
    const size_t nBodies = this->bodyCount_;
podlesny's avatar
.  
podlesny committed
    size_t maxLevel = 0;
    std::vector<size_t> maxLevels(nBodies);
    for (size_t i=0; i<nBodies; i++) {
        const size_t bodyMaxLevel = this->bodies_[i]->grid()->maxLevel();
        maxLevels[i] = bodyMaxLevel;
        maxLevel = std::max(maxLevel, bodyMaxLevel);
    }
podlesny's avatar
.  
podlesny committed
    for (int l=maxLevel; l>=0; l--) {
        this->contactNetwork_.addLevel(maxLevels, l);
podlesny's avatar
.  
podlesny committed
        for (size_t i=0; i<nBodies; i++) {
            maxLevels[i]--;
        }
    }
}
podlesny's avatar
.  
podlesny committed
template <class HostGridType, class VectorType>
void StackedBlocksFactory<HostGridType, VectorType>::setBoundaryConditions() {
    using LeafBoundaryCondition = BoundaryCondition<LeafGridView, dim>;
podlesny's avatar
.  
podlesny committed
    using Function = Dune::VirtualFunction<double, double>;
    std::shared_ptr<Function> neumannFunction = std::make_shared<NeumannCondition>();
    std::shared_ptr<Function> velocityDirichletFunction = std::make_shared<VelocityDirichletCondition>();
podlesny's avatar
podlesny committed
    const double lengthScale = CuboidGeometry::lengthScale();
podlesny's avatar
.  
podlesny committed

podlesny's avatar
.  
podlesny committed
    for (size_t i=0; i<this->bodyCount_; i++) {
        const auto& body = this->contactNetwork_.body(i);
        const auto& leafVertexCount = body->nVertices();

        // Neumann boundary
        std::shared_ptr<LeafBoundaryCondition> neumannBoundary = std::make_shared<LeafBoundaryCondition>(std::make_shared<LeafBoundaryPatch>(body->gridView()), neumannFunction, "neumann");
        body->addBoundaryCondition(neumannBoundary);

        // upper Dirichlet Boundary
        // identify Dirichlet nodes on leaf level
        if (i==this->bodyCount_-1) {
            std::shared_ptr<Dune::BitSetVector<dim>> velocityDirichletNodes = std::make_shared<Dune::BitSetVector<dim>>(leafVertexCount);
            for (int j=0; j<leafVertexCount; j++) {
                if (leafFaces_[i]->upper.containsVertex(j))
                    (*velocityDirichletNodes)[j][0] = true;
            }
podlesny's avatar
.  
podlesny committed

podlesny's avatar
.  
podlesny committed
            std::shared_ptr<LeafBoundaryCondition> velocityDirichletBoundary = std::make_shared<LeafBoundaryCondition>("dirichlet");
podlesny's avatar
.  
podlesny committed

podlesny's avatar
.  
podlesny committed
            velocityDirichletBoundary->setBoundaryPatch(body->gridView(), velocityDirichletNodes);
            velocityDirichletBoundary->setBoundaryFunction(velocityDirichletFunction);
            body->addBoundaryCondition(velocityDirichletBoundary);
        } else {
podlesny's avatar
.  
podlesny committed

podlesny's avatar
.  
podlesny committed
        }
podlesny's avatar
podlesny committed
    }

    // lower Dirichlet Boundary
podlesny's avatar
.  
podlesny committed
    const auto& firstBody = this->contactNetwork_.body(0);
    const auto& firstLeafVertexCount = firstBody->nVertices();
    std::shared_ptr<Dune::BitSetVector<dim>> zeroDirichletNodes = std::make_shared<Dune::BitSetVector<dim>>(firstLeafVertexCount);
podlesny's avatar
podlesny committed
    for (int j=0; j<firstLeafVertexCount; j++) {
podlesny's avatar
.  
podlesny committed
        if (leafFaces_[0]->lower.containsVertex(j)) {
podlesny's avatar
.  
podlesny committed
            for (size_t d=0; d<dim; d++) {
podlesny's avatar
.  
podlesny committed
              (*zeroDirichletNodes)[j][d] = true;
            }
        }
podlesny's avatar
.  
podlesny committed

        #if MY_DIM == 3 //TODO: wrong, needs revision
        if (leafFaces_[0]->front.containsVertex(j) || leafFaces_[0]->back.containsVertex(j))
            (*zeroDirichletNodes)[j][2] = true;
        #endif
podlesny's avatar
podlesny committed

    std::shared_ptr<LeafBoundaryCondition> zeroDirichletBoundary = std::make_shared<LeafBoundaryCondition>("dirichlet");
podlesny's avatar
.  
podlesny committed
    zeroDirichletBoundary->setBoundaryPatch(firstBody->gridView(), zeroDirichletNodes);
podlesny's avatar
podlesny committed

    std::shared_ptr<Function> zeroFunction = std::make_shared<NeumannCondition>();
    zeroDirichletBoundary->setBoundaryFunction(zeroFunction);
    firstBody->addBoundaryCondition(zeroDirichletBoundary);
}

#include "stackedblocksfactory_tmpl.cc"