UniqueBorderPartition.hpp 2.77 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#pragma once

#include <cassert>
#include <set>

#include <dune/common/unused.hh>
#include <dune/grid/common/datahandleif.hh>

namespace AMDiS
{
  /// \brief Determine for each border entity which processor owns it
  /**
   * All entities must be uniquely owned by exactly one processor, but they can
   * exist on multiple processors. For interior, overlap, and ghost entities the
   * assignment is trivial: interior: owner, otherwise not owner.
   *
   * For border entities (codim != 0) the ownership is not known a priory and must
   * be communicated. Here we assign the entity to the processor with the highest rank.
   **/
  template <class Grid>
  class UniqueBorderPartitionDataHandle
      : public Dune::CommDataHandleIF<UniqueBorderPartitionDataHandle<Grid>, int>
  {
    using IdSet = typename Grid::GlobalIdSet;
    using IdType = typename IdSet::IdType;

  public:
    using EntitySet = std::set<IdType>;

  public:
    /// \brief Construct a UniqueBorderPartition DataHandle to be used in a GridView
    /// communicator.
    /**
     * \param rank            The own processor rank
     * \param borderEntities  A set of entity ids filled with all border entities
     *                        owned by this processor after communication.
     * \param idSet           The id set of entity ids to store in borderEntities,
     *                        typically the grid globalIdSet.
     *
     * NOTE: Since idSet is stored by reference it must not go out of scope
     * until all calls to \ref gather and \ref scatter are finished.
     **/
    UniqueBorderPartitionDataHandle(int rank, EntitySet& borderEntities, IdSet const& idSet)
      : myrank_(rank)
      , borderEntities_(&borderEntities)
      , idSet_(idSet)
    {}

    // Communicate all entities except for grid elements
    bool contains(int /*dim*/, int codim) const { return codim != 0; }

    // communicate exactly one integer, the rank
    bool fixedSize(int /*dim*/, int /*codim*/) const { return true; }

    // Always contains one int, the rank
    template <class Entity>
    std::size_t size(Entity const& e) const { return 1; }

    template <class MessageBuffer, class Entity>
    void gather(MessageBuffer& buff, Entity const& e) const
    {
      buff.write(myrank_);
      // insert all border entities
      borderEntities_->insert(idSet_.id(e));
    }

    template <class MessageBuffer, class Entity>
    void scatter(MessageBuffer& buff, Entity const& e, std::size_t n)
    {
      DUNE_UNUSED_PARAMETER(n); // n == 1
      assert(n == 1);

      int rank = 0;
      buff.read(rank);
      // remove all border entities with rank < myrank_
      if (rank < myrank_)
        borderEntities_->erase(idSet_.id(e));
    }

  private:
    int myrank_;
    EntitySet* borderEntities_;
    IdSet const& idSet_;
  };

} // end namespace AMDiS