10#include <kernel/geometry/factory.hpp> 
   11#include <kernel/geometry/mesh_permutation.hpp> 
   12#include <kernel/geometry/mesh_node.hpp> 
   13#include <kernel/geometry/intern/facet_neighbors.hpp> 
   14#include <kernel/geometry/intern/standard_index_refiner.hpp> 
   15#include <kernel/geometry/intern/standard_vertex_refiner.hpp> 
   16#include <kernel/geometry/index_calculator.hpp> 
   17#include <kernel/util/dist.hpp> 
   19#include <kernel/util/random.hpp> 
   21#include <kernel/util/tiny_algebra.hpp> 
   45    template<
typename MeshType_>
 
   49      typedef typename MeshType_::CoordType CoordType;
 
   50      typedef typename MeshType_::VertexSetType VertexSetType;
 
   51      static constexpr int shape_dim = MeshType_::shape_dim;
 
   52      static constexpr int world_dim = MeshType_::world_dim;
 
   62      std::vector<CoordType> _edge_weights;
 
   79        _vtx(
_mesh.get_vertex_set())
 
  120        const auto& verts_at_edge = 
_mesh.template get_index_set<1, 0>();
 
  121        const Index num_edges = 
_mesh.get_num_entities(1);
 
  122        const Index num_vtx = 
_mesh.get_num_vertices();
 
  125        const CoordType eps = 
Math::sqrt(Math::eps<CoordType>());
 
  128        std::vector<Tiny::Vector<CoordType, world_dim>> sum_neigh(num_vtx);
 
  131        std::vector<CoordType> deg(num_vtx, CoordType(0));
 
  133        for (
Index iter = 0; iter < max_iter; ++iter)
 
  136          for (
Index i(0); i < num_vtx; ++i)
 
  138            sum_neigh[i].format();
 
  139            deg[i] = CoordType(0);
 
  143          for (
Index e(0); e < num_edges; ++e)
 
  146            const Index i = verts_at_edge(e,0);
 
  147            const Index j = verts_at_edge(e,1);
 
  149            CoordType weight = CoordType(1);
 
  154              weight = CoordType(1) / std::max((_vtx[i] - _vtx[j]).norm_euclid(), eps);
 
  158            if (!_edge_weights.empty())
 
  160              weight *= _edge_weights[e];
 
  166              sum_neigh[i].axpy(weight, _vtx[j]);
 
  171              sum_neigh[j].axpy(weight, _vtx[i]);
 
  179          CoordType max_change = 0;
 
  182          for (
Index i(0); i < num_vtx; ++i)
 
  187              auto x_old = _vtx[i];
 
  188              _vtx[i] = (CoordType(1) / deg[i]) * sum_neigh[i];
 
  191              Math::maxi(max_change, (_vtx[i] - x_old).norm_euclid_sqr());
 
  199          if (max_change < tol*tol)
 
  212        const auto& vtx_neighbors = 
_mesh.get_neighbors();
 
  214        const auto& faces_at_elem = 
_mesh.template get_index_set<shape_dim, shape_dim - 1>();
 
  216        int num_faces = faces_at_elem.num_indices;
 
  221        for (
Index i = 0; i < num_elements; ++i)
 
  224          for (
int j = 0; j < num_faces; ++j)
 
  227            if (vtx_neighbors[i][j] > num_elements)
 
  243        const auto& verts_at_face = 
_mesh.template get_index_set<shape_dim - 1, 0>();
 
  245        int vert_per_face = verts_at_face.num_indices;
 
  248        for (
Index i = 0; i < 
_mesh.get_num_entities(shape_dim - 1); ++i)
 
  254            for (
int j = 0; j < vert_per_face; ++j)
 
  291    template<
typename MeshType_>
 
  297      typedef MeshType_ MeshType;
 
  301      static constexpr int world_dim = MeshType::world_dim;
 
  302      static constexpr int facet_dim = MeshType::shape_dim - 1;
 
  304      typedef typename BaseClass::CoordType CoordType;
 
  348        for(
const auto& v : halo_map)
 
  351          const TargetSet& halo_facets = v.second->template get_target_set<facet_dim>();
 
  353            this->_boundary_facets.at(halo_facets[i]) = 0;
 
  367        const Index num_edges = this->_mesh.get_num_entities(1);
 
  370        this->_edge_weights.assign(num_edges, CoordType(1.0));
 
  371        std::vector<int> multiplicity(num_edges, 1);
 
  377        for (
const auto& hm : halo_map)
 
  379          const int neighbor_rank = hm.first;
 
  380          const std::unique_ptr<MeshPartType>& part_ptr = hm.second;
 
  393          const auto& target_edges = part_ptr->template get_target_set<1>();
 
  395          for (
Index k(0); k < target_edges.get_num_entities(); ++k)
 
  398            const Index e = target_edges[k];
 
  400            multiplicity[e] += 1;
 
  403        for (
Index e(0); e < num_edges; ++e)
 
  406          const int m = std::max(1, multiplicity[e]);
 
  407          this->_edge_weights[e] = CoordType(1.0) / CoordType(m);
 
  418        if (halo_map.empty() || 
_comm.
size() == 1) 
return;
 
  421        const std::size_t stride = std::size_t(world_dim + 1);
 
  424        std::vector<int> ranks;
 
  425        std::vector<std::vector<CoordType>> send_bufs, recv_bufs;
 
  427        ranks.
reserve(halo_map.size());
 
  428        send_bufs.resize(halo_map.size());
 
  429        recv_bufs.resize(halo_map.size());
 
  430        send_reqs.
reserve(halo_map.size());
 
  431        recv_reqs.
reserve(halo_map.size());
 
  434        for (
auto it = halo_map.begin(); it != halo_map.end(); ++it)
 
  437          const int halo_rank = it->first;
 
  438          const auto& part = it->second;
 
  445          const auto& halo_vtx  = part->template get_target_set<0>();
 
  446          const Index halo_size = halo_vtx.get_num_entities();
 
  449          const std::size_t len = std::size_t(halo_size) * stride;
 
  452          const std::size_t idx = ranks.size();
 
  453          ranks.push_back(halo_rank);
 
  454          auto& rbuf = recv_bufs[idx];
 
  462        for (std::size_t idx = 0; idx < ranks.size(); ++idx)
 
  465          const int halo_rank = ranks[idx];
 
  466          auto it = halo_map.find(halo_rank);
 
  470          const auto& halo_vtx  = it->second->template get_target_set<0>();
 
  471          const Index halo_size = halo_vtx.get_num_entities();
 
  474          const std::size_t len = std::size_t(halo_size) * stride;
 
  477          auto& sbuf = send_bufs[idx];
 
  481          for (
Index k(0); k < halo_size; ++k)
 
  483            const Index v = halo_vtx[k];
 
  484            const std::size_t base = std::size_t(k) * stride;
 
  486            for (
int d(0); d < world_dim; ++d)
 
  488              sbuf[base + std::size_t(d)] = sum_neigh[v][d];
 
  490            sbuf[base + std::size_t(world_dim)] = deg[v];
 
  498        for (std::size_t idx(0); recv_reqs.
wait_any(idx); )
 
  501          const int halo_rank = ranks.at(idx);
 
  502          auto it = halo_map.find(halo_rank);
 
  506          const auto& halo_vtx  = it->second->template get_target_set<0>();
 
  507          const Index halo_size = halo_vtx.get_num_entities();
 
  508          const auto& rbuf = recv_bufs.at(idx);
 
  511          XASSERT(rbuf.size() == std::size_t(halo_size) * stride);
 
  514          for (
Index k(0); k < halo_size; ++k)
 
  516            const Index v = halo_vtx[k];
 
  517            const std::size_t base = std::size_t(k) * stride;
 
  520            for (
int d(0); d < world_dim; ++d)
 
  522              sum_neigh[v][d] += rbuf[base + std::size_t(d)];
 
  524            deg[v] += rbuf[base + std::size_t(world_dim)];
 
#define XASSERT(expr)
Assertion macro definition.
void allreduce(const void *sendbuf, void *recvbuf, std::size_t count, const Datatype &datatype, const Operation &op) const
Blocking All-Reduce.
int size() const
Returns the size of this communicator.
Request irecv(void *buffer, std::size_t count, const Datatype &datatype, int source, int tag=0) const
Nonblocking Receive.
Request isend(const void *buffer, std::size_t count, const Datatype &datatype, int dest, int tag=0) const
Nonblocking Send.
int rank() const
Returns the rank of this process in this communicator.
Communication Request vector class.
void push_back(Request &&request)
Inserts a new request at the end of the request vector.
void reserve(std::size_t size_)
Reserves sufficient space for a specified number of requests.
bool wait_any(std::size_t &idx, Status &status)
Blocks until one of the active requests has been fulfilled.
void wait_all()
Blocks until all active requests are fulfilled.
Umbrella smoother class template.
DistributedUmbrellaSmoother(const Dist::Comm &comm, RootMeshNodeType &root_mesh_node)
Constructor.
virtual void _calc_boundary_facets() override
determines for each facet whether it is a boundary facet or an inner facet
void _calc_max(CoordType &global_max) override
calculates global maximum over all processes; is overridden in DistributedUmbrellaSmoother
RootMeshNodeType & _root_mesh_node
a reference to our root mesh node
void _init_edge_multiplicity()
Computes per-edge weights for distributed smoothing.
const Dist::Comm & _comm
a reference to our communicator
void _synchronize(std::vector< Tiny::Vector< CoordType, world_dim > > &sum_neigh, std::vector< CoordType > °) override
synchronizes the smoother over all processes; is overridden in DistributedUmbrellaSmoother
Class template for partial meshes.
Root mesh node class template.
const std::map< int, std::unique_ptr< MeshPartType > > & get_halo_map() const
Index get_num_entities() const
Returns the number of entities.
Umbrella mesh smoother with both uniform and scale-dependent neighbor averaging For more information ...
UmbrellaSmoother(MeshType_ &mesh)
Constructor.
std::vector< int > _boundary_facets
vector to store which facet is at the boundary
MeshType_ & _mesh
the mesh we want to smooth
void smooth(Index max_iter, CoordType tol, bool uniform=true)
Smooths the mesh with an umbrella operator.
virtual void _calc_boundary_vertices()
determines for each vertex whether it is a boundary vertex or an inner vertex
virtual void _calc_boundary_facets()
determines for each facet whether it is a boundary facet or an inner facet
std::vector< int > _boundary_vertices
vector to store which vertex is at the boundary
virtual void _synchronize(std::vector< Tiny::Vector< CoordType, world_dim > > &, std::vector< CoordType > &)
synchronizes the smoother over all processes; is overridden in DistributedUmbrellaSmoother
virtual void _calc_max(CoordType &)
calculates global maximum over all processes; is overridden in DistributedUmbrellaSmoother
Tiny Vector class template.
const Operation op_max(MPI_MAX)
Operation wrapper for MPI_MAX.
T_ sqrt(T_ x)
Returns the square-root of a value.
void maxi(T_ &xmax, T_ x)
Updates the maximum of a set of values.
std::uint64_t Index
Index data type.