Line data Source code
1 : /*
2 : * Copyright (c) 2013-2015: G-CSC, Goethe University Frankfurt
3 : * Author: Markus Breit
4 : *
5 : * This file is part of UG4.
6 : *
7 : * UG4 is free software: you can redistribute it and/or modify it under the
8 : * terms of the GNU Lesser General Public License version 3 (as published by the
9 : * Free Software Foundation) with the following additional attribution
10 : * requirements (according to LGPL/GPL v3 §7):
11 : *
12 : * (1) The following notice must be displayed in the Appropriate Legal Notices
13 : * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14 : *
15 : * (2) The following notice must be displayed at a prominent place in the
16 : * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17 : *
18 : * (3) The following bibliography is recommended for citation and must be
19 : * preserved in all covered files:
20 : * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21 : * parallel geometric multigrid solver on hierarchically distributed grids.
22 : * Computing and visualization in science 16, 4 (2013), 151-164"
23 : * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24 : * flexible software system for simulating pde based models on high performance
25 : * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26 : *
27 : * This program is distributed in the hope that it will be useful,
28 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 : * GNU Lesser General Public License for more details.
31 : */
32 :
33 : #ifndef __H__UG__LIB_GRID__PARALLELIZATION__UTIL__PARTITION_WEIGHTING_CALLBACKS__
34 : #define __H__UG__LIB_GRID__PARALLELIZATION__UTIL__PARTITION_WEIGHTING_CALLBACKS__
35 :
36 :
37 : #include "lib_grid/multi_grid.h"
38 : #include "lib_grid/tools/tools.h"
39 : #include "common/error.h"
40 : #include <vector>
41 :
42 : namespace ug
43 : {
44 :
45 : /**
46 : * Base class for partition weighting callbacks.
47 : **/
48 :
49 : class PartitionWeighting
50 : {
51 : public:
52 0 : PartitionWeighting() : m_sh(NULL), m_hWeight(1), m_vWeight(1) {};
53 0 : virtual ~PartitionWeighting() {};
54 :
55 0 : virtual int operator() (Edge* e1, Edge* e2) {return weigh(e1,e2);};
56 0 : virtual int operator() (Face* f1, Face* f2) {return weigh(f1,f2);};
57 0 : virtual int operator() (Volume* v1, Volume* v2) {return weigh(v1,v2);};
58 :
59 : void set_subset_handler(MGSubsetHandler* sh)
60 : {
61 : m_sh = sh;
62 : }
63 :
64 0 : void set_default_weights(int hWeight, int vWeight)
65 : {
66 0 : m_hWeight = hWeight;
67 0 : m_vWeight = vWeight;
68 0 : }
69 :
70 : private:
71 : template <class TElem>
72 0 : int weigh(TElem* e1, TElem* e2)
73 : {
74 0 : if (!this->m_sh)
75 0 : UG_THROW("Subset handler must be assigned to InterSubsetPartitionWeighting before it is used!");
76 :
77 0 : if (this->m_sh->get_level(e1) == this->m_sh->get_level(e2))
78 0 : return m_hWeight;
79 :
80 0 : return m_vWeight;
81 : }
82 :
83 :
84 : protected:
85 : MGSubsetHandler* m_sh;
86 :
87 : int m_hWeight; // horizontal weight
88 : int m_vWeight; // vertical weight
89 : };
90 :
91 :
92 : /**
93 : * First simple implementation: Preventing division between two distinct subsets.
94 : **/
95 :
96 : class InterSubsetPartitionWeighting : public PartitionWeighting
97 : {
98 : public:
99 0 : InterSubsetPartitionWeighting() : PartitionWeighting(), m_vsi1(0), m_vsi2(0), m_vweights(0) {};
100 0 : virtual ~InterSubsetPartitionWeighting() {};
101 :
102 : public:
103 0 : void set_inter_subset_weight(int si1, int si2, int weight)
104 : {
105 0 : m_vsi1.push_back(si1);
106 0 : m_vsi2.push_back(si2);
107 0 : m_vweights.push_back(weight);
108 0 : }
109 :
110 0 : virtual int operator() (Edge* e1, Edge* e2) {return weigh(e1,e2);};
111 0 : virtual int operator() (Face* f1, Face* f2) {return weigh(f1,f2);};
112 0 : virtual int operator() (Volume* v1, Volume* v2) {return weigh(v1,v2);};
113 :
114 : private:
115 : template <class TElem>
116 0 : int weigh(TElem* e1, TElem* e2)
117 : {
118 0 : if (!this->m_sh)
119 0 : UG_THROW("Subset handler must be assigned to InterSubsetPartitionWeighting before it is used!");
120 :
121 0 : if (this->m_sh->get_level(e1) == this->m_sh->get_level(e2))
122 : {
123 : // check whether elems fulfill one of the indivisibility conditions
124 0 : for (size_t i = 0; i < m_vsi1.size(); i++)
125 : {
126 0 : if (this->m_sh->get_subset_index(e1) == m_vsi1[i]
127 0 : && this->m_sh->get_subset_index(e2) == m_vsi2[i])
128 : {
129 0 : return m_vweights[i];
130 : }
131 : }
132 0 : return m_hWeight;
133 : }
134 0 : return m_vWeight;
135 : }
136 :
137 : private:
138 : std::vector<int> m_vsi1;
139 : std::vector<int> m_vsi2;
140 : std::vector<int> m_vweights;
141 : };
142 :
143 :
144 : /**
145 : * This PartitionWeighting sets out to protect specific subsets from having
146 : * vertices in any process boundaries.
147 : * To that purpose, in the weighing function, it checks both elements for
148 : * a common vertex in one of the specified subsets to protect. If such a vertex
149 : * exists, the weight for the division along the two elements is set to the
150 : * value defined via set_weight().
151 : **/
152 :
153 : class ProtectSubsetPartitionWeighting : public PartitionWeighting
154 : {
155 : public:
156 : typedef MultiGrid::traits<Vertex>::secure_container vertex_list;
157 :
158 :
159 : public:
160 0 : ProtectSubsetPartitionWeighting() : PartitionWeighting(), m_vSi(0), m_vWeights(0) {};
161 0 : virtual ~ProtectSubsetPartitionWeighting() {};
162 :
163 : public:
164 0 : void set_weight(int si, int weight)
165 : {
166 0 : m_vSi.push_back(si);
167 0 : m_vWeights.push_back(weight);
168 0 : }
169 :
170 0 : virtual int operator() (Edge* e1, Edge* e2) {return weigh(e1,e2);};
171 0 : virtual int operator() (Face* f1, Face* f2) {return weigh(f1,f2);};
172 0 : virtual int operator() (Volume* v1, Volume* v2) {return weigh(v1,v2);};
173 :
174 : private:
175 : template <class TElem>
176 0 : int weigh(TElem* e1, TElem* e2)
177 : {
178 0 : if (!this->m_sh)
179 0 : UG_THROW("Subset handler must be assigned to InterSubsetPartitionWeighting before it is used!")
180 :
181 0 : if (this->m_sh->get_level(e1) == this->m_sh->get_level(e2))
182 : {
183 : // check whether elems fulfill one of the indivisibility conditions
184 : vertex_list vl1, vl2;
185 0 : this->m_sh->grid()->associated_elements(vl1, e1);
186 0 : this->m_sh->grid()->associated_elements(vl2, e2);
187 :
188 0 : for (size_t i = 0; i < vl1.size(); i++)
189 : {
190 0 : for (size_t j = 0; j < m_vSi.size(); j++)
191 : {
192 : // check if vertex is in one of the restricted subsets
193 0 : if (this->m_sh->get_subset_index(vl1[i]) != m_vSi[j])
194 0 : continue;
195 :
196 : // if so, check that it is a shared vertex of both elems
197 0 : for (size_t k = 0; k < vl2.size(); k++)
198 : {
199 0 : if (vl1[i] == vl2[k])
200 0 : return m_vWeights[j];
201 : }
202 : }
203 : }
204 0 : return m_hWeight;
205 : }
206 0 : return m_vWeight;
207 : }
208 :
209 : private:
210 : std::vector<int> m_vSi;
211 : std::vector<int> m_vWeights;
212 : };
213 :
214 :
215 : } // end of namespace
216 :
217 :
218 : #endif /* __H__UG__LIB_GRID__PARALLELIZATION__UTIL__PARTITION_WEIGHTING_CALLBACKS__ */
|