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
/** \file
* \brief implement universally usable, unique partitioning of entities (vertex, edge, face, element)
* in a Dune grid; it is a general problem in parallel calculation to assign entities in a unique
* way to processors; thus, we need a unique criterion; here, we will use the rule that an entity
* is always assigned to the process with the lowest rank.
*
*
* In particular, it is the objective to provide this functionality in a unique way so that it can
* be used in a wide range of an application's needs: e.g., it can be used to assign faces,
* situated on the inter processor boundary, in a unique way, i.e. the face is always assigned to
* the process with the lower rank. A concrete application of this mechanism is the implementation
* of the transparent integral boundary condition to remove redundant triangular faces of the
* fictitious boundary surface. Indeed, the implementation of the UniqueEntityPartition class has
* been motivated by this need. However, its usage is much wider. It will also be the underlying
* infrastructure to calculate global, consecutive, zero-starting indices for grid entities over all
* the processes over which the grid is partitioned.
*
*
* \author Benedikt Oswald, Patrick Leidenberger
*
* \warning None
*
* \attention
*
* \bug
*
* \todo
*/
#ifndef ENTITY_PARTITONING_HH
#define ENTITY_PARTITONING_HH
/** \brief Include standard header files. */
#include <vector>
#include <iostream>
#include <fstream>
#include <map>
#include <utility>
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/** Include base class functionality for the communication interface */
#include <dune/grid/common/datahandleif.hh>
/*********************************************************************************************/
/* calculate unique partitioning for all entities of a given codim in a given GridView, */
/* assuming they all have the same geometry, i.e. codim, type */
/*********************************************************************************************/
template<class GridView, int CODIM>
class UniqueEntityPartition
{
private:
/* A DataHandle class to cacluate the minimum of a std::vector which is accompanied by an index set */
template<class IS, class V> // mapper type and vector type
class MinimumExchange : public Dune::CommDataHandleIF<MinimumExchange<IS,V>,typename V::value_type>
{
public:
//! export type of data for message buffer
typedef typename V::value_type DataType;
//! returns true if data for this codim should be communicated
bool contains (int dim, int codim) const
{
return(codim==CODIM);
}
//! returns true if size per entity of given dim and codim is a constant
bool fixedsize (int dim, int codim) const
{
return(true);
}
/*! how many objects of type DataType have to be sent for a given entity
*
* Note: Only the sender side needs to know this size. */
template<class EntityType>
size_t size (EntityType& e) const
{
return(1);
}
/*! pack data from user to message buffer */
template<class MessageBuffer, class EntityType>
void gather (MessageBuffer& buff, const EntityType& e) const
{
buff.write(v_[indexset_.index(e)]);
}
/*! unpack data from message buffer to user
n is the number of objects sent by the sender
*/
template<class MessageBuffer, class EntityType>
void scatter (MessageBuffer& buff, const EntityType& e, size_t n)
{
DataType x; buff.read(x);
if (x>=0) // other is -1 means, he does not want it
{
v_[indexset_.index(e)] = std::min(x,v_[indexset_.index(e)]);
}
}
//! constructor
MinimumExchange (const IS& indexset, V& v)
: indexset_(indexset),
v_(v)
{
;
}
private:
const IS& indexset_;
V& v_;
};
public:
/** declare often uses types */
typedef typename GridView::Traits::template Codim<CODIM>::Iterator Iterator;
typedef typename GridView::Traits::template Codim<CODIM>::Entity Entity;
/*! \brief Constructor needs to know the grid function space
*/
UniqueEntityPartition (const GridView& gridview)
: gridview_(gridview),
assignment_(gridview.size(CODIM)),
rank_(gridview_.comm().rank())
{
/** extract types from the GridView data type */
typedef typename GridView::IndexSet IndexSet;
// assign own rank to entities that I might have
for(auto it = gridview_.template begin<0>();it!=gridview_.template end<0>(); ++it)
#if DUNE_VERSION_NEWER(DUNE_GRID,2,4)
for (int i=0; i<it->subEntities(CODIM); i++)
#else
for (int i=0; i<it->template count<CODIM>(); i++)
#endif
{
assignment_[gridview_.indexSet().template subIndex(*it,i,CODIM)]
= ( (it->template subEntity<CODIM>(i)->partitionType()==Dune::InteriorEntity) || (it->template subEntity<CODIM>(i)->partitionType()==Dune::BorderEntity) )
? rank_ // set to own rank
: - 1; // it is a ghost entity, I will not possibly own it.
}
MinimumExchange<IndexSet,std::vector<int> > dh(gridview_.indexSet(),assignment_);
gridview_.communicate(dh,Dune::All_All_Interface,Dune::ForwardCommunication);
/* convert vector of minimum ranks to assignment vector */
for (size_t i=0; i<assignment_.size(); i++)
assignment_[i] = (assignment_[i] == rank_) ? 1 : 0;
/** answer question if entity belongs to me, to this process */
bool owner(size_t i)
{
return assignment_[i];
}
size_t numOwners() const
{
return std::accumulate(assignment_.begin(), assignment_.end(), 0);
}
/** answer question if entity belongs to me, to this process */
bool owner(const Entity& entity)
{
return(assignment_[gridview_.indexSet().template index(entity)]);
}
private:
/** declare private data members */
const GridView& gridview_;
std::vector<int> assignment_;
int rank_;
};
#endif /** ENTITY_PARTITONING_HH */