Line data Source code
1 : /*
2 : * Copyright (c) 2010-2015: G-CSC, Goethe University Frankfurt
3 : * Author: Sebastian Reiter
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 "lib_grid/algorithms/attachment_util.h"
34 : #include "selector_interface.h"
35 : #ifdef UG_PARALLEL
36 : #include "lib_grid/parallelization/distributed_grid.h"
37 : #include "lib_grid/parallelization/util/compol_selection.h"
38 : #endif
39 :
40 :
41 : namespace ug
42 : {
43 :
44 0 : ISelector::ISelector(uint supportedElements) :
45 0 : m_aSelected("ISelector_IsSelected")
46 : {
47 0 : m_pGrid = NULL;
48 0 : m_supportedElements = supportedElements;// Since no grid is available, we can't yet activate them.
49 0 : m_bAutoselectionEnabled = false;
50 0 : m_bSelectionInheritanceEnabled = true;
51 0 : m_bStrictInheritanceEnabled = false;
52 0 : }
53 :
54 0 : ISelector::ISelector(Grid& grid, uint supportedElements) :
55 0 : m_aSelected("ISelector_IsSelected")
56 : {
57 0 : m_pGrid = &grid;
58 0 : m_supportedElements = SE_NONE;
59 0 : m_bAutoselectionEnabled = false;
60 0 : m_bSelectionInheritanceEnabled = true;
61 0 : m_bStrictInheritanceEnabled = false;
62 :
63 : // register at grid. Don't use set_grid here since it invokes virtual methods.
64 : if(m_pGrid){
65 0 : m_pGrid->register_observer(this, OT_GRID_OBSERVER | OT_VERTEX_OBSERVER | OT_EDGE_OBSERVER |
66 : OT_FACE_OBSERVER | OT_VOLUME_OBSERVER);
67 :
68 : // initialise attachments and accessors.
69 0 : enable_element_support(supportedElements);
70 : }
71 0 : }
72 :
73 0 : ISelector::~ISelector()
74 : {
75 : // unregister from grid
76 : // don't use set_grid here, since it invokes virtual methods.
77 0 : if(m_pGrid){
78 : // disable all currently supported elements (this will remove any attachments)
79 0 : disable_element_support(m_supportedElements);
80 0 : m_pGrid->unregister_observer(this);
81 : m_pGrid = NULL;
82 : }
83 0 : }
84 :
85 0 : void ISelector::
86 : set_supported_elements(uint shElements)
87 : {
88 : // do this in two steps:
89 : // 1: disable the element-support that is no longer required.
90 : // 2: enable the element-support that was not already enabled.
91 : // disable the elements that shall be disabled.
92 :
93 : // (the ones which shall not be set, but are currently active.)
94 0 : disable_element_support((~shElements) & m_supportedElements);
95 :
96 : // enable the elements that are not already enabled
97 0 : enable_element_support(shElements & (~m_supportedElements));
98 0 : }
99 :
100 0 : void ISelector::enable_element_support(uint shElements)
101 : {
102 : // if no grid is assigned, we can't do anything.
103 0 : if(m_pGrid){
104 : // check for each option whether it should be enabled.
105 : // to reduce unnecessary operations, we have to make sure that
106 : // that option hasn't already been enabled.
107 :
108 0 : if((shElements & SE_VERTEX) &&
109 : (!elements_are_supported(SE_VERTEX))){
110 : //LOG("enabling vertex support\n");
111 : // enable vertex-support.
112 0 : m_pGrid->attach_to_vertices(m_aSelected);
113 0 : m_aaSelVRT.access(*m_pGrid, m_aSelected);
114 : SetAttachmentValues(m_aaSelVRT, m_pGrid->begin<Vertex>(),
115 : m_pGrid->end<Vertex>(), 0);
116 0 : m_supportedElements |= SE_VERTEX;
117 : }
118 :
119 0 : if((shElements & SE_EDGE) &&
120 : (!elements_are_supported(SE_EDGE))){
121 : //LOG("enabling edge support\n");
122 : // enable edge support
123 0 : m_pGrid->attach_to_edges(m_aSelected);
124 0 : m_aaSelEDGE.access(*m_pGrid, m_aSelected);
125 : SetAttachmentValues(m_aaSelEDGE, m_pGrid->begin<Edge>(),
126 : m_pGrid->end<Edge>(), 0);
127 0 : m_supportedElements |= SE_EDGE;
128 : }
129 :
130 0 : if((shElements & SE_FACE) &&
131 : (!elements_are_supported(SE_FACE))){
132 : //LOG("enabling face support\n");
133 : // enable face support
134 0 : m_pGrid->attach_to_faces(m_aSelected);
135 0 : m_aaSelFACE.access(*m_pGrid, m_aSelected);
136 : SetAttachmentValues(m_aaSelFACE, m_pGrid->begin<Face>(),
137 : m_pGrid->end<Face>(), 0);
138 0 : m_supportedElements |= SE_FACE;
139 : }
140 :
141 0 : if((shElements & SE_VOLUME) &&
142 : (!elements_are_supported(SE_VOLUME))){
143 : //LOG("enabling volume support\n");
144 : // enable volume support
145 0 : m_pGrid->attach_to_volumes(m_aSelected);
146 0 : m_aaSelVOL.access(*m_pGrid, m_aSelected);
147 : SetAttachmentValues(m_aaSelVOL, m_pGrid->begin<Volume>(),
148 : m_pGrid->end<Volume>(), 0);
149 0 : m_supportedElements |= SE_VOLUME;
150 : }
151 : }
152 : else{
153 0 : m_supportedElements |= shElements;
154 : }
155 0 : }
156 :
157 0 : void ISelector::disable_element_support(uint shElements)
158 : {
159 : // if no grid is assigned, we can't do anything.
160 0 : if(m_pGrid){
161 : // check for each option whether it should be disabled.
162 : // to reduce unnecessary operations, we have to make sure that
163 : // that option hasn't already been disabled.
164 :
165 0 : if((shElements & SE_VERTEX) && elements_are_supported(SE_VERTEX)){
166 : //LOG("disabling vertex support\n");
167 0 : m_pGrid->detach_from_vertices(m_aSelected);
168 : }
169 :
170 0 : if((shElements & SE_EDGE) && elements_are_supported(SE_EDGE)){
171 : //LOG("disabling edge support\n");
172 0 : m_pGrid->detach_from_edges(m_aSelected);
173 : }
174 :
175 0 : if((shElements & SE_FACE) && elements_are_supported(SE_FACE)){
176 : //LOG("disabling face support\n");
177 0 : m_pGrid->detach_from_faces(m_aSelected);
178 : }
179 :
180 0 : if((shElements & SE_VOLUME) && elements_are_supported(SE_VOLUME)){
181 : //LOG("disabling volume support\n");
182 0 : m_pGrid->detach_from_volumes(m_aSelected);
183 : }
184 : }
185 :
186 : // remove the disabled elements from the set of currently supported elements.
187 0 : m_supportedElements &= (~shElements);
188 0 : }
189 :
190 0 : void ISelector::enable_autoselection(bool bEnable)
191 : {
192 0 : m_bAutoselectionEnabled = bEnable;
193 0 : }
194 :
195 0 : void ISelector::enable_selection_inheritance(bool bEnable)
196 : {
197 0 : m_bSelectionInheritanceEnabled = bEnable;
198 0 : }
199 :
200 0 : void ISelector::enable_strict_inheritance(bool bEnable)
201 : {
202 0 : m_bStrictInheritanceEnabled = bEnable;
203 0 : }
204 :
205 :
206 0 : void ISelector::set_grid(Grid* grid)
207 : {
208 : // if we're already registered at this grid then return
209 0 : if(m_pGrid == grid)
210 : return;
211 :
212 : // if we're already registered at a grid unregister first.
213 0 : if(m_pGrid){
214 : // disable all currently supported elements (this will remove any attachments)
215 0 : clear();
216 0 : disable_element_support(m_supportedElements);
217 0 : m_pGrid->unregister_observer(this);
218 0 : m_pGrid = NULL;
219 : }
220 :
221 : // if the new grid is not empty, we'll initialise and register
222 0 : if(grid){
223 0 : grid->register_observer(this, OT_GRID_OBSERVER | OT_VERTEX_OBSERVER | OT_EDGE_OBSERVER |
224 : OT_FACE_OBSERVER | OT_VOLUME_OBSERVER);
225 0 : m_pGrid = grid;
226 :
227 : // initialise attachments and accessors.
228 : // do this whith a little trick:
229 : // set the supported-element-options to SE_NONE,
230 : // then call enable for all element-types that should be supported.
231 0 : uint tmpOpts = m_supportedElements;
232 0 : m_supportedElements = SE_NONE;
233 0 : enable_element_support(tmpOpts);
234 : }
235 : }
236 :
237 :
238 : #ifdef UG_PARALLEL
239 : template <class TIntfcCom>
240 : void ISelector::broadcast_selection_states(bool deselect,
241 : bool includeGhosts,
242 : TIntfcCom& icom)
243 : {
244 : DistributedGridManager& dgm = *m_pGrid->distributed_grid_manager();
245 : GridLayoutMap& glm = dgm.grid_layout_map();
246 :
247 : if(deselect){
248 : ComPol_Selection<typename TIntfcCom::Layout> compol(*this, false, true);
249 : if(includeGhosts){
250 : // if ghosts shall be included, we will first have to make sure that
251 : // copies in h-interfaces know about the selection state of associated
252 : // ghosts
253 : icom.exchange_data(glm, INT_V_MASTER, INT_V_SLAVE, compol);
254 : icom.communicate();
255 : }
256 :
257 : // gather selection state at h-master
258 : icom.exchange_data(glm, INT_H_SLAVE, INT_H_MASTER, compol);
259 : icom.communicate();
260 :
261 : // copy it to all h-slaves
262 : icom.exchange_data(glm, INT_H_MASTER, INT_H_SLAVE, compol);
263 : icom.communicate();
264 :
265 : if(includeGhosts){
266 : // if ghosts shall be included, we will now have to copy the values back
267 : // to those ghosts
268 : icom.exchange_data(glm, INT_V_SLAVE, INT_V_MASTER, compol);
269 : icom.communicate();
270 : }
271 : }
272 : else{
273 : ComPol_EnableSelectionStateBits<typename TIntfcCom::Layout> compol(*this, 0xFF);
274 : if(includeGhosts){
275 : // if ghosts shall be included, we will first have to make sure that
276 : // copies in h-interfaces know about the selection state of associated
277 : // ghosts
278 : icom.exchange_data(glm, INT_V_MASTER, INT_V_SLAVE, compol);
279 : icom.communicate();
280 : }
281 :
282 : // gather selection state at h-master
283 : icom.exchange_data(glm, INT_H_SLAVE, INT_H_MASTER, compol);
284 : icom.communicate();
285 :
286 : // copy it to all h-slaves
287 : icom.exchange_data(glm, INT_H_MASTER, INT_H_SLAVE, compol);
288 : icom.communicate();
289 :
290 : if(includeGhosts){
291 : // if ghosts shall be included, we will now have to copy the values back
292 : // to those ghosts
293 : icom.exchange_data(glm, INT_V_SLAVE, INT_V_MASTER, compol);
294 : icom.communicate();
295 : }
296 : }
297 : }
298 : #endif
299 :
300 0 : void ISelector::broadcast_selection_states(bool deselect,
301 : bool includeGhosts)
302 : {
303 : #ifdef UG_PARALLEL
304 : if(!m_pGrid)
305 : return;
306 :
307 : broadcast_selection_states(deselect, includeGhosts, m_icomVRT);
308 : broadcast_selection_states(deselect, includeGhosts, m_icomEDGE);
309 : broadcast_selection_states(deselect, includeGhosts, m_icomFACE);
310 : broadcast_selection_states(deselect, includeGhosts, m_icomVOL);
311 : #endif
312 0 : }
313 :
314 : ////////////////////////////////////////////////////////////////////////
315 : // grid callbacks
316 : /*
317 : void ISelector::registered_at_grid(Grid* grid)
318 : {
319 : // if we're already registered at this grid then return
320 : if(m_pGrid == grid)
321 : return;
322 :
323 : // if we're already registered at a grid, then unregister first
324 : if(m_pGrid)
325 : m_pGrid->unregister_observer(this);
326 :
327 : // assign grid
328 : m_pGrid = grid;
329 :
330 : // initialise attachments and accessors.
331 : // do this whith a little trick:
332 : // set the supported-element-options to SE_NONE,
333 : // then call enable for all element-types that should be supported.
334 : uint tmpOpts = m_supportedElements;
335 : m_supportedElements = SE_NONE;
336 : enable_element_support(tmpOpts);
337 : }
338 :
339 : void ISelector::unregistered_from_grid(Grid* grid)
340 : {
341 : assert(m_pGrid == grid && "grids do not match!");
342 :
343 : if(m_pGrid == grid){
344 : // disable all currently supported elements (this will remove any attachments)
345 : disable_element_support(m_supportedElements);
346 : m_pGrid = NULL;
347 : }
348 : }
349 : */
350 0 : void ISelector::grid_to_be_destroyed(Grid* grid)
351 : {
352 : assert(m_pGrid == grid && "grids do not match!");
353 :
354 0 : if(m_pGrid == grid){
355 0 : set_grid(NULL);
356 : }
357 0 : }
358 :
359 0 : void ISelector::elements_to_be_cleared(Grid* grid)
360 : {
361 0 : clear();
362 0 : }
363 :
364 : // vertex callbacks
365 0 : void ISelector::vertex_created(Grid* grid, Vertex* vrt,
366 : GridObject* pParent,
367 : bool replacesParent)
368 : {
369 : assert((m_pGrid == grid) && "grids do not match.");
370 :
371 : //TODO: this if could be removed if the subset-handler was only registered for
372 : // the elements that it supports. Note that a dynamic register/unregister
373 : // would be required...
374 0 : if(elements_are_supported(SE_VERTEX)){
375 : // init the element
376 : mark_deselected(vrt);
377 0 : if(autoselection_enabled())
378 : select(vrt);
379 0 : else if((pParent != NULL) && selection_inheritance_enabled()){
380 0 : if(m_bStrictInheritanceEnabled){
381 0 : if(pParent->base_object_id() == VERTEX){
382 0 : select(vrt, get_selection_status(static_cast<Vertex*>(pParent)));
383 : }
384 : }
385 : else
386 0 : select(vrt, get_selection_status(pParent));
387 : }
388 0 : else if(replacesParent){
389 : UG_ASSERT(pParent, "A parent has to exist if it shall be replaced");
390 : UG_ASSERT(dynamic_cast<Vertex*>(pParent), "Only parents of the same type may be replaced.");
391 0 : select(vrt, get_selection_status(static_cast<Vertex*>(pParent)));
392 : }
393 : }
394 0 : }
395 :
396 0 : void ISelector::vertex_to_be_erased(Grid* grid, Vertex* vrt,
397 : Vertex* replacedBy)
398 : {
399 : assert((m_pGrid == grid) && "grids do not match.");
400 :
401 : //TODO: this if could be removed if the subset-handler was only registered for
402 : // the elements that it supports. Note that a dynamic register/unregister
403 : // would be required...
404 0 : if(elements_are_supported(SE_VERTEX)){
405 0 : deselect(vrt);
406 : }
407 0 : }
408 :
409 : // edge callbacks
410 0 : void ISelector::edge_created(Grid* grid, Edge* edge,
411 : GridObject* pParent,
412 : bool replacesParent)
413 : {
414 : assert((m_pGrid == grid) && "grids do not match.");
415 :
416 : //TODO: this if could be removed if the subset-handler was only registered for
417 : // the elements that it supports. Note that a dynamic register/unregister
418 : // would be required...
419 0 : if(elements_are_supported(SE_EDGE)){
420 : // init the element
421 : mark_deselected(edge);
422 0 : if(autoselection_enabled())
423 : select(edge);
424 0 : else if((pParent != NULL) && selection_inheritance_enabled()){
425 0 : if(m_bStrictInheritanceEnabled){
426 0 : if(pParent->base_object_id() == EDGE){
427 0 : select(edge, get_selection_status(static_cast<Edge*>(pParent)));
428 : }
429 : }
430 : else
431 0 : select(edge, get_selection_status(pParent));
432 : }
433 0 : else if(replacesParent){
434 : UG_ASSERT(pParent, "A parent has to exist if it shall be replaced");
435 : UG_ASSERT(dynamic_cast<Edge*>(pParent), "Only parents of the same type may be replaced.");
436 0 : select(edge, get_selection_status(static_cast<Edge*>(pParent)));
437 : }
438 : }
439 0 : }
440 :
441 0 : void ISelector::edge_to_be_erased(Grid* grid, Edge* edge,
442 : Edge* replacedBy)
443 : {
444 : assert((m_pGrid == grid) && "grids do not match.");
445 :
446 : //TODO: this if could be removed if the subset-handler was only registered for
447 : // the elements that it supports. Note that a dynamic register/unregister
448 : // would be required...
449 0 : if(elements_are_supported(SE_EDGE)){
450 0 : deselect(edge);
451 : }
452 0 : }
453 :
454 : // face callbacks
455 0 : void ISelector::face_created(Grid* grid, Face* face,
456 : GridObject* pParent,
457 : bool replacesParent)
458 : {
459 : assert((m_pGrid == grid) && "grids do not match.");
460 :
461 : //TODO: this if could be removed if the subset-handler was only registered for
462 : // the elements that it supports. Note that a dynamic register/unregister
463 : // would be required...
464 0 : if(elements_are_supported(SE_FACE)){
465 : // init the element
466 : mark_deselected(face);
467 0 : if(autoselection_enabled())
468 : select(face);
469 0 : else if((pParent != NULL) && selection_inheritance_enabled()){
470 0 : if(m_bStrictInheritanceEnabled){
471 0 : if(pParent->base_object_id() == FACE){
472 0 : select(face, get_selection_status(static_cast<Face*>(pParent)));
473 : }
474 : }
475 : else
476 0 : select(face, get_selection_status(pParent));
477 : }
478 0 : else if(replacesParent){
479 : UG_ASSERT(pParent, "A parent has to exist if it shall be replaced");
480 : UG_ASSERT(dynamic_cast<Face*>(pParent), "Only parents of the same type may be replaced.");
481 0 : select(face, get_selection_status(static_cast<Face*>(pParent)));
482 : }
483 : }
484 0 : }
485 :
486 0 : void ISelector::face_to_be_erased(Grid* grid, Face* face,
487 : Face* replacedBy)
488 : {
489 : assert((m_pGrid == grid) && "grids do not match.");
490 :
491 : //TODO: this if could be removed if the subset-handler was only registered for
492 : // the elements that it supports. Note that a dynamic register/unregister
493 : // would be required...
494 0 : if(elements_are_supported(SE_FACE)){
495 0 : deselect(face);
496 : }
497 0 : }
498 :
499 : // volume callbacks
500 0 : void ISelector::volume_created(Grid* grid, Volume* vol,
501 : GridObject* pParent,
502 : bool replacesParent)
503 : {
504 : assert((m_pGrid == grid) && "grids do not match.");
505 :
506 : //TODO: this if could be removed if the subset-handler was only registered for
507 : // the elements that it supports. Note that a dynamic register/unregister
508 : // would be required...
509 0 : if(elements_are_supported(SE_VOLUME)){
510 : // init the element
511 : mark_deselected(vol);
512 0 : if(autoselection_enabled())
513 : select(vol);
514 0 : else if((pParent != NULL) && selection_inheritance_enabled()){
515 0 : if(m_bStrictInheritanceEnabled){
516 0 : if(pParent->base_object_id() == VOLUME){
517 0 : select(vol, get_selection_status(static_cast<Volume*>(pParent)));
518 : }
519 : }
520 : else
521 0 : select(vol, get_selection_status(pParent));
522 : }
523 0 : else if(replacesParent){
524 : UG_ASSERT(pParent, "A parent has to exist if it shall be replaced");
525 : UG_ASSERT(dynamic_cast<Volume*>(pParent), "Only parents of the same type may be replaced.");
526 0 : select(vol, get_selection_status(static_cast<Volume*>(pParent)));
527 : }
528 : }
529 0 : }
530 :
531 0 : void ISelector::volume_to_be_erased(Grid* grid, Volume* vol,
532 : Volume* replacedBy)
533 : {
534 : assert((m_pGrid == grid) && "grids do not match.");
535 :
536 : //TODO: this if could be removed if the subset-handler was only registered for
537 : // the elements that it supports. Note that a dynamic register/unregister
538 : // would be required...
539 0 : if(elements_are_supported(SE_VOLUME)){
540 0 : deselect(vol);
541 : }
542 0 : }
543 :
544 :
545 : template <class TElem>
546 0 : void ISelector::
547 : elems_to_be_merged(Grid* grid, TElem* target,
548 : TElem* elem1, TElem* elem2)
549 : {
550 : // if at least one was selected, we'll select the new one too.
551 0 : if(is_selected(elem1) || is_selected(elem2))
552 : select(target);
553 0 : }
554 :
555 0 : void ISelector::
556 : vertices_to_be_merged(Grid* grid, Vertex* target,
557 : Vertex* elem1, Vertex* elem2)
558 : {
559 0 : elems_to_be_merged(grid, target, elem1, elem2);
560 0 : }
561 :
562 0 : void ISelector::
563 : edges_to_be_merged(Grid* grid, Edge* target,
564 : Edge* elem1, Edge* elem2)
565 : {
566 0 : elems_to_be_merged(grid, target, elem1, elem2);
567 0 : }
568 :
569 0 : void ISelector::
570 : faces_to_be_merged(Grid* grid, Face* target,
571 : Face* elem1, Face* elem2)
572 : {
573 0 : elems_to_be_merged(grid, target, elem1, elem2);
574 0 : }
575 :
576 0 : void ISelector::
577 : volumes_to_be_merged(Grid* grid, Volume* target,
578 : Volume* elem1, Volume* elem2)
579 : {
580 0 : elems_to_be_merged(grid, target, elem1, elem2);
581 0 : }
582 :
583 : }// end of namespace
|