Line data Source code
1 : /*
2 : * Copyright (c) 2012-2015: G-CSC, Goethe University Frankfurt
3 : * Author: Martin Scherer
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 : #include "periodic_boundary_manager.h"
34 :
35 : namespace ug {
36 :
37 0 : PeriodicBoundaryManager::PeriodicBoundaryManager() :
38 0 : m_pGrid(NULL)/*, m_pSH(NULL)*/ {}
39 :
40 0 : PeriodicBoundaryManager::~PeriodicBoundaryManager()
41 : {
42 : // set grid to NULL to detach groups from grid
43 0 : set_grid(NULL);
44 0 : }
45 :
46 0 : void PeriodicBoundaryManager::set_grid(Grid* g)
47 : {
48 : // group attachments
49 : Attachment<Group<Vertex>*> aGroupVRT;
50 : Attachment<Group<Edge>*> aGroupEDG;
51 : Attachment<Group<Face>*> aGroupFCE;
52 :
53 : // periodic info attachments
54 : Attachment<PeriodicStatus> aPeriodicStatus;
55 :
56 : // detach groups and unregister observer
57 0 : if(m_pGrid) {
58 : m_pGrid->detach_from_vertices(aGroupVRT);
59 0 : m_pGrid->detach_from_edges(aGroupEDG);
60 0 : m_pGrid->detach_from_faces(aGroupFCE);
61 :
62 0 : m_pGrid->detach_from_vertices(aPeriodicStatus);
63 0 : m_pGrid->detach_from_edges(aPeriodicStatus);
64 0 : m_pGrid->detach_from_faces(aPeriodicStatus);
65 :
66 0 : m_pGrid->unregister_observer(this);
67 : }
68 :
69 0 : m_pGrid = dynamic_cast<MultiGrid*>(g);
70 :
71 : // attach groups and register observer
72 0 : if(m_pGrid != NULL) {
73 0 : m_pGrid->attach_to_vertices_dv(aGroupVRT, NULL);
74 0 : m_pGrid->attach_to_edges_dv(aGroupEDG, NULL);
75 0 : m_pGrid->attach_to_faces_dv(aGroupFCE, NULL);
76 :
77 0 : m_pGrid->attach_to_vertices_dv(aPeriodicStatus, P_NOT_PERIODIC);
78 0 : m_pGrid->attach_to_edges_dv(aPeriodicStatus, P_NOT_PERIODIC);
79 0 : m_pGrid->attach_to_faces_dv(aPeriodicStatus, P_NOT_PERIODIC);
80 :
81 : // access grid with those attachments
82 0 : m_aaGroupVRT.access(*m_pGrid, aGroupVRT);
83 : m_aaGroupEDG.access(*m_pGrid, aGroupEDG);
84 : m_aaGroupFCE.access(*m_pGrid, aGroupFCE);
85 :
86 : m_aaPeriodicStatusVRT.access(*m_pGrid, aPeriodicStatus);
87 : m_aaPeriodicStatusEDG.access(*m_pGrid, aPeriodicStatus);
88 : m_aaPeriodicStatusFCE.access(*m_pGrid, aPeriodicStatus);
89 :
90 : uint options = OT_GRID_OBSERVER | OT_VERTEX_OBSERVER | OT_EDGE_OBSERVER |
91 : OT_FACE_OBSERVER;
92 0 : m_pGrid->register_observer(this, options);
93 : }
94 0 : }
95 :
96 0 : Grid* PeriodicBoundaryManager::get_grid() const {
97 0 : return m_pGrid;
98 : }
99 :
100 : //void PeriodicBoundaryManager::set_subset_handler(ISubsetHandler* sh) {
101 : // m_pSH = sh;
102 : // // very small memory overhead buys constant access time in match() methods
103 : // m_vIdentifier.resize(m_pSH->num_subsets());
104 : //}
105 :
106 : // group accessors
107 : template <>
108 : Grid::AttachmentAccessor<Vertex, Attachment<PeriodicBoundaryManager::Group<Vertex>* > >&
109 0 : PeriodicBoundaryManager::get_group_accessor() {
110 0 : return m_aaGroupVRT;
111 : }
112 :
113 : template <>
114 : Grid::AttachmentAccessor<Edge, Attachment<PeriodicBoundaryManager::Group<Edge>* > >&
115 0 : PeriodicBoundaryManager::get_group_accessor() {
116 0 : return m_aaGroupEDG;
117 : }
118 :
119 : template <>
120 : Grid::AttachmentAccessor<Face, Attachment<PeriodicBoundaryManager::Group<Face>* > >&
121 0 : PeriodicBoundaryManager::get_group_accessor() {
122 0 : return m_aaGroupFCE;
123 : }
124 :
125 : template <>
126 : const Grid::AttachmentAccessor<Vertex, Attachment<PeriodicBoundaryManager::Group<Vertex>* > >&
127 0 : PeriodicBoundaryManager::get_group_accessor() const {
128 0 : return m_aaGroupVRT;
129 : }
130 :
131 : template <>
132 : const Grid::AttachmentAccessor<Edge, Attachment<PeriodicBoundaryManager::Group<Edge>* > >&
133 0 : PeriodicBoundaryManager::get_group_accessor() const {
134 0 : return m_aaGroupEDG;
135 : }
136 :
137 : template <>
138 : const Grid::AttachmentAccessor<Face, Attachment<PeriodicBoundaryManager::Group<Face>* > >&
139 0 : PeriodicBoundaryManager::get_group_accessor() const {
140 0 : return m_aaGroupFCE;
141 : }
142 :
143 : template <>
144 : const Grid::AttachmentAccessor<Volume, Attachment<PeriodicBoundaryManager::Group<Volume>* > >&
145 0 : PeriodicBoundaryManager::get_group_accessor() const {
146 0 : UG_THROW("not impled");
147 : }
148 :
149 : // periodic status accessors
150 : template <>
151 : const Grid::AttachmentAccessor<Vertex, Attachment<PeriodicBoundaryManager::PeriodicStatus> >&
152 0 : PeriodicBoundaryManager::get_periodic_status_accessor() const {
153 0 : return m_aaPeriodicStatusVRT;
154 : }
155 :
156 : template <>
157 : Grid::AttachmentAccessor<Vertex, Attachment<PeriodicBoundaryManager::PeriodicStatus> >&
158 0 : PeriodicBoundaryManager::get_periodic_status_accessor() {
159 0 : return m_aaPeriodicStatusVRT;
160 : }
161 :
162 : template <>
163 : const Grid::AttachmentAccessor<Edge, Attachment<PeriodicBoundaryManager::PeriodicStatus> >&
164 0 : PeriodicBoundaryManager::get_periodic_status_accessor() const {
165 0 : return m_aaPeriodicStatusEDG;
166 : }
167 :
168 : template <>
169 : Grid::AttachmentAccessor<Edge, Attachment<PeriodicBoundaryManager::PeriodicStatus> >&
170 0 : PeriodicBoundaryManager::get_periodic_status_accessor() {
171 0 : return m_aaPeriodicStatusEDG;
172 : }
173 :
174 : template <>
175 : Grid::AttachmentAccessor<Face, Attachment<PeriodicBoundaryManager::PeriodicStatus> >&
176 0 : PeriodicBoundaryManager::get_periodic_status_accessor() {
177 0 : return m_aaPeriodicStatusFCE;
178 : }
179 :
180 : template <>
181 : const Grid::AttachmentAccessor<Face, Attachment<PeriodicBoundaryManager::PeriodicStatus> >&
182 0 : PeriodicBoundaryManager::get_periodic_status_accessor() const {
183 0 : return m_aaPeriodicStatusFCE;
184 : }
185 :
186 : template <>
187 : Grid::AttachmentAccessor<Volume, Attachment<PeriodicBoundaryManager::PeriodicStatus> >&
188 0 : PeriodicBoundaryManager::get_periodic_status_accessor() {
189 0 : UG_THROW("not impled");
190 : }
191 :
192 : template <>
193 : const Grid::AttachmentAccessor<Volume, Attachment<PeriodicBoundaryManager::PeriodicStatus> >&
194 0 : PeriodicBoundaryManager::get_periodic_status_accessor() const {
195 0 : UG_THROW("not impled");
196 : }
197 :
198 : ///// grid observer methods
199 0 : void PeriodicBoundaryManager::grid_to_be_destroyed(Grid* grid) {
200 :
201 : /// delete groups
202 0 : for (VertexIterator iter = m_pGrid->begin<Vertex>();
203 0 : iter != m_pGrid->end<Vertex>(); ++iter) {
204 0 : if(is_master(*iter)) delete m_aaGroupVRT[*iter];
205 : }
206 :
207 : for (EdgeIterator iter = m_pGrid->begin<Edge>();
208 0 : iter != m_pGrid->end<Edge>(); ++iter) {
209 0 : if(is_master(*iter)) delete m_aaGroupEDG[*iter];
210 : }
211 :
212 : for (FaceIterator iter = m_pGrid->begin<Face>();
213 0 : iter != m_pGrid->end<Face>(); ++iter) {
214 0 : if(is_master(*iter)) delete m_aaGroupFCE[*iter];
215 : }
216 :
217 0 : set_grid(NULL);
218 0 : }
219 :
220 0 : void PeriodicBoundaryManager::vertex_created(Grid* grid, Vertex* vrt,
221 : GridObject* pParent, bool replacesParent) {
222 0 : handle_creation_cast_wrapper(vrt, pParent, replacesParent);
223 0 : }
224 :
225 0 : void PeriodicBoundaryManager::edge_created(Grid* grid, Edge* e, GridObject* pParent,
226 : bool replacesParent) {
227 0 : handle_creation_cast_wrapper(e, pParent, replacesParent);
228 0 : }
229 :
230 0 : void PeriodicBoundaryManager::face_created(Grid* grid, Face* f, GridObject* pParent,
231 : bool replacesParent) {
232 0 : handle_creation_cast_wrapper(f, pParent, replacesParent);
233 0 : }
234 :
235 0 : void PeriodicBoundaryManager::vertex_to_be_erased(Grid* grid, Vertex* vrt,
236 : Vertex* replacedBy) {
237 0 : handle_deletion(vrt, replacedBy);
238 0 : }
239 :
240 0 : void PeriodicBoundaryManager::edge_to_be_erased(Grid* grid, Edge* e,
241 : Edge* replacedBy) {
242 0 : handle_deletion(e, replacedBy);
243 0 : }
244 :
245 0 : void PeriodicBoundaryManager::face_to_be_erased(Grid* grid, Face* f,
246 : Face* replacedBy) {
247 0 : handle_deletion(f, replacedBy);
248 0 : }
249 :
250 : /**
251 : * performs following checks on all elements in goc1 and goc2
252 : * 1. all elements given are periodic
253 : * 2. masters of groups are valid (master pointer of group valid + have at least one child)
254 : * 3. no duplicate master, slave pairs exists
255 : * 4.
256 : */
257 0 : bool PeriodicBoundaryManager::check_periodicity(
258 : const GridObjectCollection& goc1,
259 : const GridObjectCollection& goc2, ISubsetHandler* sh) {
260 :
261 : Group<Vertex>::unique_pairs s_vert;
262 : Group<Edge>::unique_pairs s_edge;
263 : Group<Face>::unique_pairs s_face;
264 :
265 : UG_ASSERT(goc1.num_levels() == goc2.num_levels(),
266 : "collections have different mg levels!")
267 :
268 0 : for (size_t lvl = 0; lvl < goc1.num_levels(); lvl++) {
269 : // check faces
270 0 : check_elements_periodicity<Face>(goc1.begin<Face>(lvl),
271 0 : goc1.end<Face>(lvl), s_face, sh);
272 0 : check_elements_periodicity<Face>(goc2.begin<Face>(lvl),
273 0 : goc2.end<Face>(lvl), s_face, sh);
274 :
275 : // check edges
276 0 : check_elements_periodicity<Edge>(goc1.begin<Edge>(lvl),
277 0 : goc1.end<Edge>(lvl), s_edge, sh);
278 0 : check_elements_periodicity<Edge>(goc2.begin<Edge>(lvl),
279 0 : goc2.end<Edge>(lvl), s_edge, sh);
280 :
281 : // check vertices
282 0 : check_elements_periodicity<Vertex>(goc1.begin<Vertex>(lvl),
283 0 : goc1.end<Vertex>(lvl), s_vert, sh);
284 0 : check_elements_periodicity<Vertex>(goc2.begin<Vertex>(lvl),
285 0 : goc2.end<Vertex>(lvl), s_vert, sh);
286 : }
287 :
288 0 : return true;
289 : }
290 :
291 :
292 : template <class elem_t>
293 0 : void PeriodicBoundaryManager::validity_check()
294 : {
295 : typedef typename Grid::traits<elem_t>::iterator iter_t;
296 : typedef typename Group<elem_t>::SlaveContainer slave_container_t;
297 : typedef typename slave_container_t::iterator slave_iter_t;
298 :
299 : Grid::AttachmentAccessor<elem_t, Attachment<PeriodicStatus> >
300 0 : aaPS = get_periodic_status_accessor<elem_t>();
301 :
302 : Grid::AttachmentAccessor<elem_t, Attachment<Group<elem_t>* > >
303 0 : aaGroup = get_group_accessor<elem_t>();
304 :
305 0 : Grid& g = *m_pGrid;
306 :
307 0 : for(iter_t i_elem = g.begin<elem_t>(); i_elem != g.end<elem_t>(); ++ i_elem)
308 : {
309 : elem_t* e = *i_elem;
310 0 : if(aaGroup[e]){
311 0 : bool isMaster = (aaGroup[e]->m_master == e);
312 : int elemSlaveCount = 0;
313 : int totalSlaveCount = 0;
314 : slave_container_t* slaveCon = &aaGroup[e]->get_slaves();
315 0 : for(slave_iter_t i = slaveCon->begin(); i != slaveCon->end(); ++i)
316 : {
317 0 : ++totalSlaveCount;
318 0 : if(*i == e)
319 0 : ++elemSlaveCount;
320 : }
321 :
322 0 : if(aaGroup[e]->m_master == NULL){
323 0 : UG_THROW("Group doesn't contain a master!\n"
324 : << " elem-info: " << ElementDebugInfo(g, e));
325 : }
326 0 : if(totalSlaveCount == 0){
327 0 : UG_THROW("Group doesn't contain slaves!\n"
328 : << " elem-info: " << ElementDebugInfo(g, e));
329 : }
330 :
331 0 : if(isMaster && (elemSlaveCount > 0)){
332 0 : UG_THROW("An element is contained both in the master list and in the"
333 : " slave list of its group!\n"
334 : << " elem-info: " << ElementDebugInfo(g, e));
335 : }
336 0 : if(elemSlaveCount > 1){
337 0 : UG_THROW("Multi-occurance of an element in a groups slave list!\n"
338 : << " elem-info: " << ElementDebugInfo(g, e));
339 : }
340 0 : if((!isMaster) && (elemSlaveCount == 0)){
341 0 : UG_THROW("An element points to a group but is not contained in that group!\n"
342 : << " elem-info: " << ElementDebugInfo(g, e));
343 : }
344 :
345 : // the element is either master or slave. now check whether the states are correct
346 0 : if(isMaster){
347 0 : if(aaPS[e] != P_MASTER){
348 0 : UG_THROW("An element is a groups master, but its state does not say so!\n"
349 : << " state: " << aaPS[e] << "\n"
350 : << " elem-info: " << ElementDebugInfo(g, e));
351 : }
352 : // make sure that all slaves have their group assigned
353 0 : for(slave_iter_t i = slaveCon->begin(); i != slaveCon->end(); ++i)
354 : {
355 0 : if(aaGroup[*i] != aaGroup[e]){
356 0 : UG_THROW("A slave element was encountered, which does not"
357 : << " point to the same group as it's master!\n"
358 : << " master: " << ElementDebugInfo(g, e) << "\n"
359 : << " slave: " << ElementDebugInfo(g, *i) << "\n");
360 : }
361 : }
362 : }
363 : else{
364 0 : if(aaPS[e] == P_SLAVE_MASTER_UNKNOWN){
365 0 : UG_THROW("P_SLAVE_MASTER_UNKNOWN is not a valid state!\n"
366 : << " elem-info: " << ElementDebugInfo(g, e));
367 : }
368 0 : else if(aaPS[e] != P_SLAVE)
369 : {
370 0 : UG_THROW("An element is a slave, but its state does not say so!\n"
371 : << " state: " << aaPS[e] << "\n"
372 : << " elem-info: " << ElementDebugInfo(g, e));
373 : }
374 :
375 0 : if(aaGroup[e] != aaGroup[aaGroup[e]->m_master]){
376 0 : UG_THROW("A master element was encountered, which does not"
377 : << " point to the same group as it's slave!\n"
378 : << " master: " << ElementDebugInfo(g, aaGroup[e]->m_master) << "\n"
379 : << " slave: " << ElementDebugInfo(g, e) << "\n");
380 : }
381 : }
382 : }
383 0 : else if(aaPS[e] != P_NOT_PERIODIC){
384 0 : UG_THROW("An element is marked as periodic but not contained in a group!\n"
385 : << " state: " << aaPS[e] << "\n"
386 : << " elem-info: " << ElementDebugInfo(g, e));
387 : }
388 : }
389 0 : }
390 :
391 0 : void PeriodicBoundaryManager::validity_check()
392 : {
393 0 : validity_check<Vertex>();
394 0 : validity_check<Edge>();
395 0 : validity_check<Face>();
396 0 : }
397 :
398 : //void PeriodicBoundaryManager::set_identifier(SmartPtr<IIdentifier> i, size_t si) {
399 : // UG_ASSERT(m_vIdentifier.capacity() >= si, "identifier vector not big enough")
400 : // m_vIdentifier[si] = i;
401 : //}
402 :
403 : } // end of namespace ug
|