Line data Source code
1 : /*
2 : * Copyright (c) 2011-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 <sstream>
34 : #include "common/assert.h"
35 : #include "lib_grid/algorithms/multi_grid_util.h"
36 : #include "lib_grid/algorithms/selection_util.h"
37 : #include "lib_grid/algorithms/debug_util.h"
38 : #include "hanging_node_refiner_multi_grid.h"
39 : #include "ref_mark_adjusters/mg_hnode_adjuster.h"
40 :
41 : // Only required for debug saves
42 : #include "lib_grid/file_io/file_io.h"
43 :
44 : #ifdef UG_PARALLEL
45 : #include "pcl/pcl.h"
46 : #include "lib_grid/parallelization/distributed_grid.h"
47 : #include "lib_grid/parallelization/parallelization_util.h"
48 : #endif
49 :
50 : //define PROFILE_HANGING_NODE_REFINER_MG if you want to profile
51 : //the refinement code.
52 : //#define PROFILE_HANGING_NODE_REFINER_MG
53 : #ifdef PROFILE_HANGING_NODE_REFINER_MG
54 : #define MGHNODE_PROFILE_FUNC() PROFILE_FUNC()
55 : #define MGHNODE_PROFILE_BEGIN(name) PROFILE_BEGIN(name)
56 : #define MGHNODE_PROFILE_END() PROFILE_END()
57 : #else
58 : #define MGHNODE_PROFILE_FUNC()
59 : #define MGHNODE_PROFILE_BEGIN(name)
60 : #define MGHNODE_PROFILE_END()
61 : #endif
62 :
63 : using namespace std;
64 :
65 : namespace ug{
66 :
67 0 : HangingNodeRefiner_MultiGrid::
68 0 : HangingNodeRefiner_MultiGrid(SPRefinementProjector projector) :
69 : BaseClass(projector),
70 0 : m_pMG(NULL)
71 : {
72 0 : add_ref_mark_adjuster(MGHNodeAdjuster::create());
73 0 : }
74 :
75 0 : HangingNodeRefiner_MultiGrid::
76 : HangingNodeRefiner_MultiGrid(MultiGrid& mg,
77 0 : SPRefinementProjector projector) :
78 : BaseClass(projector),
79 0 : m_pMG(NULL)
80 : {
81 0 : add_ref_mark_adjuster(MGHNodeAdjuster::create());
82 0 : set_grid(&mg);
83 0 : }
84 :
85 0 : HangingNodeRefiner_MultiGrid::
86 0 : ~HangingNodeRefiner_MultiGrid()
87 : {
88 0 : set_grid(NULL);
89 0 : }
90 :
91 0 : void HangingNodeRefiner_MultiGrid::
92 : grid_to_be_destroyed(Grid* grid)
93 : {
94 0 : set_grid(NULL);
95 0 : }
96 :
97 0 : void HangingNodeRefiner_MultiGrid::
98 : assign_grid(MultiGrid& mg)
99 : {
100 0 : set_grid(&mg);
101 0 : }
102 :
103 0 : void HangingNodeRefiner_MultiGrid::
104 : num_marked_edges_local(std::vector<int>& numMarkedEdgesOut)
105 : {
106 0 : num_marked_elems<Edge>(numMarkedEdgesOut);
107 0 : }
108 :
109 0 : void HangingNodeRefiner_MultiGrid::
110 : num_marked_faces_local(std::vector<int>& numMarkedFacesOut)
111 : {
112 0 : num_marked_elems<Face>(numMarkedFacesOut);
113 0 : }
114 :
115 0 : void HangingNodeRefiner_MultiGrid::
116 : num_marked_volumes_local(std::vector<int>& numMarkedVolsOut)
117 : {
118 0 : num_marked_elems<Volume>(numMarkedVolsOut);
119 0 : }
120 :
121 :
122 : template <class TElem>
123 0 : void HangingNodeRefiner_MultiGrid::
124 : num_marked_elems(std::vector<int>& numMarkedElemsOut)
125 : {
126 : MGSelector& sel = get_refmark_selector();
127 : numMarkedElemsOut.clear();
128 0 : numMarkedElemsOut.resize(sel.num_levels(), 0);
129 0 : for(size_t i = 0; i < sel.num_levels(); ++i){
130 0 : numMarkedElemsOut[i] = sel.num<TElem>(i);
131 : }
132 0 : }
133 :
134 0 : void HangingNodeRefiner_MultiGrid::
135 : set_grid(MultiGrid* mg)
136 : {
137 : // call base class implementation
138 0 : BaseClass::set_grid(mg);
139 :
140 0 : m_pMG = mg;
141 0 : }
142 :
143 : bool
144 0 : HangingNodeRefiner_MultiGrid::
145 : refinement_is_allowed(Vertex* elem)
146 : {
147 0 : return !m_pMG->has_children(elem);
148 : }
149 :
150 : bool
151 0 : HangingNodeRefiner_MultiGrid::
152 : refinement_is_allowed(Edge* elem)
153 : {
154 0 : return (!m_pMG->has_children(elem))
155 0 : || elem->is_constraining();
156 : }
157 :
158 : bool
159 0 : HangingNodeRefiner_MultiGrid::
160 : refinement_is_allowed(Face* elem)
161 : {
162 0 : return (!m_pMG->has_children(elem))
163 0 : || elem->is_constraining();
164 : }
165 :
166 : bool
167 0 : HangingNodeRefiner_MultiGrid::
168 : refinement_is_allowed(Volume* elem)
169 : {
170 0 : return !m_pMG->has_children(elem);
171 : }
172 :
173 0 : void HangingNodeRefiner_MultiGrid::assign_hnode_marks()
174 : {
175 : // first call the base implementation
176 0 : BaseClass::assign_hnode_marks();
177 :
178 : // now use multigrid info to do another important set of hnode assignments
179 0 : if (!m_pMG)
180 0 : throw(UGError("HangingNodeRefiner_MultiGrid::refine: No grid assigned."));
181 :
182 : MultiGrid& mg = *m_pMG;
183 :
184 : // TODO: This had better be done in the base implementation. But how?
185 : // Also take care of (unmarkable) SHADOW_COPY edges
186 : // whose children are marked for refinement:
187 : // These children need to be marked HNRM_TO_CONSTRAINING!
188 : Grid::face_traits::secure_container fl;
189 : EdgeIterator it = mg.begin<Edge>();
190 : EdgeIterator itEnd = mg.end<Edge>();
191 0 : for (; it != itEnd; ++it)
192 : {
193 : Edge* e = *it;
194 :
195 : // find out whether this is a SHADOW-COPY edge;
196 : // which is the case iff it has exactly one child
197 : // and there exists an associated face that does not have any
198 0 : if (mg.num_child_edges(e) != 1)
199 0 : continue;
200 :
201 : bool faceWithoutChildExists = false;
202 0 : mg.associated_elements(fl, e);
203 : const size_t flSz = fl.size();
204 0 : for (size_t f = 0; f < flSz; ++f)
205 : {
206 0 : if (refinement_is_allowed(fl[f]) && !mg.num_child_faces(fl[f]))
207 : {
208 : faceWithoutChildExists = true;
209 : break;
210 : }
211 : }
212 :
213 0 : if (!faceWithoutChildExists)
214 0 : continue;
215 :
216 : Edge* child = mg.get_child_edge(e, 0);
217 :
218 0 : if (marked_refine(child))
219 0 : add_hmark(child, HNRM_TO_CONSTRAINING);
220 : }
221 0 : }
222 :
223 0 : void HangingNodeRefiner_MultiGrid::
224 : pre_refine()
225 : {
226 0 : if(!m_pMG)
227 0 : throw(UGError("HangingNodeRefiner_MultiGrid::refine: No grid assigned."));
228 :
229 : MultiGrid& mg = *m_pMG;
230 :
231 : // Resize the attachment containers
232 :
233 : {
234 : selector_t& sel = get_refmark_selector();
235 :
236 : MGHNODE_PROFILE_BEGIN(MGHNode_ReserveAttachmentMemory);
237 :
238 : MGHNODE_PROFILE_BEGIN(MGHNODE_ReserveVrtData);
239 0 : mg.reserve<Vertex>(mg.num<Vertex>() +
240 : + sel.num<Vertex>()
241 0 : + sel.num<Edge>() - sel.num<ConstrainingEdge>()
242 0 : + sel.num<Quadrilateral>()
243 0 : + sel.num<ConstrainedQuadrilateral>()
244 0 : + sel.num<Hexahedron>());
245 : MGHNODE_PROFILE_END();
246 :
247 : MGHNODE_PROFILE_BEGIN(MGHNODE_ReserveEdgeData);
248 0 : mg.reserve<Edge>(mg.num<Edge>()
249 0 : + 2 * (sel.num<Edge>() - sel.num<ConstrainingEdge>())
250 0 : + 3 * (sel.num<Triangle>() + sel.num<ConstrainedTriangle>())
251 0 : + 4 * (sel.num<Quadrilateral>() + sel.num<ConstrainedQuadrilateral>())
252 0 : + 3 * sel.num<Prism>() + sel.num<Tetrahedron>()
253 0 : + 4 * sel.num<Pyramid>() + 6 * sel.num<Hexahedron>());
254 : MGHNODE_PROFILE_END();
255 :
256 : MGHNODE_PROFILE_BEGIN(MGHNODE_ReserveFaceData);
257 0 : mg.reserve<Face>(mg.num<Face>()
258 0 : + 4 * (sel.num<Face>() - sel.num<ConstrainingTriangle>()
259 0 : - sel.num<ConstrainingQuadrilateral>())
260 0 : + 10 * sel.num<Prism>()
261 0 : + 8 * sel.num<Tetrahedron>()
262 0 : + 9 * sel.num<Pyramid>() + 12 * sel.num<Hexahedron>());
263 : MGHNODE_PROFILE_END();
264 :
265 : MGHNODE_PROFILE_BEGIN(MGHNODE_ReserveVolData);
266 0 : mg.reserve<Volume>(mg.num<Volume>()
267 0 : + 8 * sel.num<Tetrahedron>() + 8 * sel.num<Prism>()
268 0 : + 6 * sel.num<Pyramid>() + 8 * sel.num<Hexahedron>());
269 : MGHNODE_PROFILE_END();
270 :
271 : MGHNODE_PROFILE_END();
272 : }
273 :
274 :
275 : // create a child vertex for each marked vertex
276 0 : for(sel_vrt_iter iter = m_selMarkedElements.begin<Vertex>();
277 0 : iter != m_selMarkedElements.end<Vertex>(); ++iter)
278 : {
279 0 : if(marked_refine(*iter) && refinement_is_allowed(*iter)){
280 0 : Vertex* vrt = *mg.create<RegularVertex>(*iter);
281 0 : if(m_projector.valid())
282 0 : m_projector->new_vertex(vrt, *iter);
283 : }
284 : }
285 0 : }
286 :
287 0 : void HangingNodeRefiner_MultiGrid::
288 : process_constraining_edge(ConstrainingEdge* cge)
289 : {
290 : // call base implementation to perform refinement
291 0 : BaseClass::process_constraining_edge(cge);
292 :
293 : // the constrained edge is now a normal edge
294 : UG_ASSERT(marked_to_normal(cge), "A constraining has to be converted to a"
295 : " normal edge when it is refined.");
296 0 : Vertex* centerVrt = get_center_vertex(cge);
297 0 : RegularEdge* e = *m_pMG->create_and_replace<RegularEdge>(cge);
298 0 : if(centerVrt)
299 0 : set_center_vertex(e, centerVrt);
300 0 : }
301 :
302 0 : void HangingNodeRefiner_MultiGrid::
303 : refine_edge_with_normal_vertex(Edge* e, Vertex** newCornerVrts)
304 : {
305 : // collect child corners
306 : std::vector<Vertex*> childCorners;
307 0 : collect_child_corners(childCorners, e);
308 :
309 : // call original implementation
310 0 : BaseClass::refine_edge_with_normal_vertex(e, &childCorners.front());
311 0 : }
312 :
313 0 : void HangingNodeRefiner_MultiGrid::
314 : refine_edge_with_hanging_vertex(Edge* e, Vertex** newCornerVrts)
315 : {
316 : // collect child corners
317 : std::vector<Vertex*> childCorners;
318 0 : collect_child_corners(childCorners, e);
319 :
320 : // call original implementation
321 0 : BaseClass::refine_edge_with_hanging_vertex(e, &childCorners.front());
322 0 : }
323 :
324 0 : void HangingNodeRefiner_MultiGrid::
325 : refine_face_with_normal_vertex(Face* f, Vertex** newCornerVrts)
326 : {
327 : // collect child corners
328 : std::vector<Vertex*> childCorners;
329 0 : collect_child_corners(childCorners, f);
330 :
331 : // call original implementation
332 0 : BaseClass::refine_face_with_normal_vertex(f, &childCorners.front());
333 0 : }
334 :
335 0 : void HangingNodeRefiner_MultiGrid::
336 : refine_face_with_hanging_vertex(Face* f, Vertex** newCornerVrts)
337 : {
338 : // collect child corners
339 : std::vector<Vertex*> childCorners;
340 0 : collect_child_corners(childCorners, f);
341 :
342 : // call original implementation
343 0 : BaseClass::refine_face_with_hanging_vertex(f, &childCorners.front());
344 0 : }
345 :
346 0 : void HangingNodeRefiner_MultiGrid::
347 : refine_volume_with_normal_vertex(Volume* v, Vertex** newCornerVrts)
348 : {
349 : // collect child corners
350 : std::vector<Vertex*> childCorners;
351 0 : collect_child_corners(childCorners, v);
352 :
353 : // call original implementation
354 0 : BaseClass::refine_volume_with_normal_vertex(v, &childCorners.front());
355 0 : }
356 :
357 0 : Vertex* HangingNodeRefiner_MultiGrid::
358 : get_center_vertex(Edge* e)
359 : {
360 0 : return m_pMG->get_child_vertex(e);
361 : }
362 :
363 :
364 0 : void HangingNodeRefiner_MultiGrid::
365 : set_center_vertex(Edge* e, Vertex* v)
366 : {
367 : // the child vertex should already have been associated since the
368 : // multigrid is an observer itself.
369 : UG_ASSERT(m_pMG->get_child_vertex(e) == v, "child/vertex mismatch.");
370 0 : }
371 :
372 :
373 0 : Vertex* HangingNodeRefiner_MultiGrid::
374 : get_center_vertex(Face* f)
375 : {
376 0 : return m_pMG->get_child_vertex(f);
377 : }
378 :
379 :
380 0 : void HangingNodeRefiner_MultiGrid::
381 : set_center_vertex(Face* f, Vertex* v)
382 : {
383 : // the child vertex should already have been associated since the
384 : // multigrid is an observer itself.
385 : UG_ASSERT(m_pMG->get_child_vertex(f) == v, "child/vertex mismatch.");
386 0 : }
387 :
388 :
389 :
390 0 : void HangingNodeRefiner_MultiGrid::
391 : restrict_selection_to_surface_coarsen_elements()
392 : {
393 0 : restrict_selection_to_surface_coarsen_elements<Vertex>();
394 0 : restrict_selection_to_surface_coarsen_elements<Edge>();
395 0 : restrict_selection_to_surface_coarsen_elements<Face>();
396 0 : restrict_selection_to_surface_coarsen_elements<Volume>();
397 0 : }
398 :
399 : template <class TElem>
400 0 : void HangingNodeRefiner_MultiGrid::
401 : restrict_selection_to_surface_coarsen_elements()
402 : {
403 0 : MultiGrid& mg = *m_pMG;
404 : selector_t& sel = get_refmark_selector();
405 :
406 0 : for(typename selector_t::template traits<TElem>::iterator iter = sel.template begin<TElem>();
407 0 : iter != sel.template end<TElem>();)
408 : {
409 : TElem* e = *iter;
410 : ++iter;
411 :
412 : // make sure that only coarsen-marks are applied
413 0 : if(get_mark(e) != RM_COARSEN){
414 0 : sel.deselect(e);
415 0 : continue;
416 : }
417 :
418 : // make sure that the element is a surface element
419 0 : if(mg.has_children(e))
420 0 : sel.deselect(e);
421 : }
422 0 : }
423 :
424 :
425 0 : void HangingNodeRefiner_MultiGrid::
426 : restrict_selection_to_coarsen_families()
427 : {
428 0 : restrict_selection_to_coarsen_families<Vertex>();
429 0 : restrict_selection_to_coarsen_families<Edge>();
430 0 : restrict_selection_to_coarsen_families<Face>();
431 0 : restrict_selection_to_coarsen_families<Volume>();
432 0 : }
433 :
434 :
435 : template <class TElem>
436 0 : void HangingNodeRefiner_MultiGrid::
437 : restrict_selection_to_coarsen_families()
438 : {
439 : typedef typename TElem::grid_base_object TBaseElem;
440 0 : MultiGrid& mg = *m_pMG;
441 : selector_t& sel = get_refmark_selector();
442 :
443 : // coarsening is only performed for complete families. If some siblings aren't
444 : // selected for coarsening, the whole family may not be coarsened. All siblings
445 : // have to be deselected in this case.
446 :
447 : // mark parents, which have been processed and mark siblings, which are valid
448 : // candidates. If thus a surface element is encountered, which has a marked
449 : // parent, but is not marked itself, then it is clear that it is not a valid
450 : // candidate.
451 0 : mg.begin_marking();
452 0 : for(typename selector_t::traits<TElem>::iterator iter = sel.begin<TElem>();
453 0 : iter != sel.end<TElem>();)
454 : {
455 : TElem* e = *iter;
456 : ++iter;
457 :
458 : // make sure that only surface elements are selected
459 : UG_ASSERT(mg.num_children<TBaseElem>(e) == 0,
460 : "Only surface elements may be passed to this method.");
461 :
462 : // make sure that only RM_COARSEN marks are used
463 : UG_ASSERT(get_mark(e) == RM_COARSEN,
464 : "Only RM_COARSEN marks may be used in this method.");
465 :
466 : // if the element is marked, we'll continue (the family is complete)
467 0 : if(mg.is_marked(e))
468 0 : continue;
469 :
470 : // get the parent
471 0 : TBaseElem* parent = dynamic_cast<TBaseElem*>(mg.get_parent(e));
472 0 : if(parent){
473 0 : if(mg.is_marked(parent)){
474 : // the parent is marked and e is not. We thus have to deselect e
475 0 : sel.deselect(e);
476 0 : continue;
477 : }
478 :
479 : mg.mark(parent);
480 :
481 : // check whether all children of e of type TBaseElem are marked
482 : bool allMarked = true;
483 : size_t numChildren = mg.num_children<TBaseElem>(parent);
484 0 : for(size_t i = 0; i < numChildren; ++i){
485 0 : if(get_mark(mg.get_child<TBaseElem>(parent, i)) != RM_COARSEN){
486 : allMarked = false;
487 : break;
488 : }
489 : }
490 :
491 0 : if(allMarked){
492 : // mark all children of parent, so that all it is clear that they
493 : // belong to a complete family
494 0 : for(size_t i = 0; i < numChildren; ++i){
495 : mg.mark(mg.get_child<TBaseElem>(parent, i));
496 : }
497 : }
498 : else
499 0 : sel.deselect(e);
500 : }
501 : else{
502 : // the parent of this element has a different type or it doesn't exist
503 : // at all. The element is thus not regarded as a valid candidate.
504 0 : sel.deselect(e);
505 : }
506 : }
507 0 : mg.end_marking();
508 0 : }
509 :
510 0 : static void DeselectFamily(ISelector& sel, MultiGrid& mg, Vertex* elem)
511 : {
512 0 : sel.deselect(elem);
513 : size_t numVertexChildren = mg.num_children<Vertex>(elem);
514 :
515 0 : for(size_t i = 0; i < numVertexChildren; ++i)
516 0 : DeselectFamily(sel, mg, mg.get_child<Vertex>(elem, i));
517 0 : }
518 :
519 0 : static void DeselectFamily(ISelector& sel, MultiGrid& mg, Edge* elem)
520 : {
521 0 : sel.deselect(elem);
522 : size_t numVertexChildren = mg.num_children<Vertex>(elem);
523 : size_t numEdgeChildren = mg.num_children<Edge>(elem);
524 :
525 0 : for(size_t i = 0; i < numVertexChildren; ++i)
526 0 : DeselectFamily(sel, mg, mg.get_child<Vertex>(elem, i));
527 :
528 0 : for(size_t i = 0; i < numEdgeChildren; ++i)
529 0 : DeselectFamily(sel, mg, mg.get_child<Edge>(elem, i));
530 0 : }
531 :
532 0 : static void DeselectFamily(ISelector& sel, MultiGrid& mg, Face* elem)
533 : {
534 0 : sel.deselect(elem);
535 : size_t numVertexChildren = mg.num_children<Vertex>(elem);
536 : size_t numEdgeChildren = mg.num_children<Edge>(elem);
537 : size_t numFaceChildren = mg.num_children<Face>(elem);
538 :
539 0 : for(size_t i = 0; i < numVertexChildren; ++i)
540 0 : DeselectFamily(sel, mg, mg.get_child<Vertex>(elem, i));
541 :
542 0 : for(size_t i = 0; i < numEdgeChildren; ++i)
543 0 : DeselectFamily(sel, mg, mg.get_child<Edge>(elem, i));
544 :
545 0 : for(size_t i = 0; i < numFaceChildren; ++i)
546 0 : DeselectFamily(sel, mg, mg.get_child<Face>(elem, i));
547 0 : }
548 :
549 0 : static void DeselectFamily(ISelector& sel, MultiGrid& mg, Volume* elem)
550 : {
551 0 : sel.deselect(elem);
552 : size_t numVertexChildren = mg.num_children<Vertex>(elem);
553 : size_t numEdgeChildren = mg.num_children<Edge>(elem);
554 : size_t numFaceChildren = mg.num_children<Face>(elem);
555 : size_t numVolumeChildren = mg.num_children<Volume>(elem);
556 :
557 0 : for(size_t i = 0; i < numVertexChildren; ++i)
558 0 : DeselectFamily(sel, mg, mg.get_child<Vertex>(elem, i));
559 :
560 0 : for(size_t i = 0; i < numEdgeChildren; ++i)
561 0 : DeselectFamily(sel, mg, mg.get_child<Edge>(elem, i));
562 :
563 0 : for(size_t i = 0; i < numFaceChildren; ++i)
564 0 : DeselectFamily(sel, mg, mg.get_child<Face>(elem, i));
565 :
566 0 : for(size_t i = 0; i < numVolumeChildren; ++i)
567 0 : DeselectFamily(sel, mg, mg.get_child<Volume>(elem, i));
568 0 : }
569 :
570 0 : static void DeselectFamily(ISelector& sel, MultiGrid& mg, GridObject* elem)
571 : {
572 0 : switch(elem->base_object_id()){
573 0 : case VERTEX: return DeselectFamily(sel, mg, static_cast<Vertex*>(elem));
574 0 : case EDGE: return DeselectFamily(sel, mg, static_cast<Edge*>(elem));
575 0 : case FACE: return DeselectFamily(sel, mg, static_cast<Face*>(elem));
576 0 : case VOLUME: return DeselectFamily(sel, mg, static_cast<Volume*>(elem));
577 : }
578 : }
579 :
580 :
581 0 : static void SaveCoarsenMarksToFile(ISelector& sel, const char* filename)
582 : {
583 : assert(sel.grid());
584 : Grid& g = *sel.grid();
585 :
586 0 : SubsetHandler sh(g);
587 :
588 0 : AssignGridToSubset(g, sh, 8);
589 0 : for(VertexIterator iter = g.vertices_begin(); iter != g.vertices_end(); ++iter){
590 : ISelector::status_t status = sel.get_selection_status(*iter);
591 0 : switch(status){
592 0 : case RM_COARSEN: sh.assign_subset(*iter, 0); break;
593 0 : case HangingNodeRefiner_MultiGrid::HNCM_ALL: sh.assign_subset(*iter, 1); break;
594 0 : case HangingNodeRefiner_MultiGrid::HNCM_PARTIAL: sh.assign_subset(*iter, 2); break;
595 0 : case HangingNodeRefiner_MultiGrid::HNCM_NONE: sh.assign_subset(*iter, 3); break;
596 0 : case HangingNodeRefiner_MultiGrid::HNCM_UNKNOWN: sh.assign_subset(*iter, 4); break;
597 0 : case HangingNodeRefiner_MultiGrid::HNCM_INVALID: sh.assign_subset(*iter, 5); break;
598 0 : case HangingNodeRefiner_MultiGrid::HNCM_REPLACE: sh.assign_subset(*iter, 6); break;
599 0 : case HangingNodeRefiner_MultiGrid::HNCM_NO_NBRS: sh.assign_subset(*iter, 7); break;
600 : }
601 : }
602 :
603 0 : for(EdgeIterator iter = g.edges_begin(); iter != g.edges_end(); ++iter){
604 : ISelector::status_t status = sel.get_selection_status(*iter);
605 0 : switch(status){
606 0 : case RM_COARSEN: sh.assign_subset(*iter, 0); break;
607 0 : case HangingNodeRefiner_MultiGrid::HNCM_ALL: sh.assign_subset(*iter, 1); break;
608 0 : case HangingNodeRefiner_MultiGrid::HNCM_PARTIAL: sh.assign_subset(*iter, 2); break;
609 0 : case HangingNodeRefiner_MultiGrid::HNCM_NONE: sh.assign_subset(*iter, 3); break;
610 0 : case HangingNodeRefiner_MultiGrid::HNCM_UNKNOWN: sh.assign_subset(*iter, 4); break;
611 0 : case HangingNodeRefiner_MultiGrid::HNCM_INVALID: sh.assign_subset(*iter, 5); break;
612 0 : case HangingNodeRefiner_MultiGrid::HNCM_REPLACE: sh.assign_subset(*iter, 6); break;
613 0 : case HangingNodeRefiner_MultiGrid::HNCM_NO_NBRS: sh.assign_subset(*iter, 7); break;
614 : }
615 : }
616 :
617 0 : for(FaceIterator iter = g.faces_begin(); iter != g.faces_end(); ++iter){
618 : ISelector::status_t status = sel.get_selection_status(*iter);
619 0 : switch(status){
620 0 : case RM_COARSEN: sh.assign_subset(*iter, 0); break;
621 0 : case HangingNodeRefiner_MultiGrid::HNCM_ALL: sh.assign_subset(*iter, 1); break;
622 0 : case HangingNodeRefiner_MultiGrid::HNCM_PARTIAL: sh.assign_subset(*iter, 2); break;
623 0 : case HangingNodeRefiner_MultiGrid::HNCM_NONE: sh.assign_subset(*iter, 3); break;
624 0 : case HangingNodeRefiner_MultiGrid::HNCM_UNKNOWN: sh.assign_subset(*iter, 4); break;
625 0 : case HangingNodeRefiner_MultiGrid::HNCM_INVALID: sh.assign_subset(*iter, 5); break;
626 0 : case HangingNodeRefiner_MultiGrid::HNCM_REPLACE: sh.assign_subset(*iter, 6); break;
627 0 : case HangingNodeRefiner_MultiGrid::HNCM_NO_NBRS: sh.assign_subset(*iter, 7); break;
628 : }
629 : }
630 :
631 0 : for(VolumeIterator iter = g.volumes_begin(); iter != g.volumes_end(); ++iter){
632 : ISelector::status_t status = sel.get_selection_status(*iter);
633 0 : switch(status){
634 0 : case RM_COARSEN: sh.assign_subset(*iter, 0); break;
635 0 : case HangingNodeRefiner_MultiGrid::HNCM_ALL: sh.assign_subset(*iter, 1); break;
636 0 : case HangingNodeRefiner_MultiGrid::HNCM_PARTIAL: sh.assign_subset(*iter, 2); break;
637 0 : case HangingNodeRefiner_MultiGrid::HNCM_NONE: sh.assign_subset(*iter, 3); break;
638 0 : case HangingNodeRefiner_MultiGrid::HNCM_UNKNOWN: sh.assign_subset(*iter, 4); break;
639 0 : case HangingNodeRefiner_MultiGrid::HNCM_INVALID: sh.assign_subset(*iter, 5); break;
640 0 : case HangingNodeRefiner_MultiGrid::HNCM_REPLACE: sh.assign_subset(*iter, 6); break;
641 0 : case HangingNodeRefiner_MultiGrid::HNCM_NO_NBRS: sh.assign_subset(*iter, 7); break;
642 : }
643 : }
644 :
645 0 : sh.subset_info(0).name = "coarsen";
646 0 : sh.subset_info(1).name = "all";
647 0 : sh.subset_info(2).name = "partial";
648 0 : sh.subset_info(3).name = "none";
649 0 : sh.subset_info(4).name = "unknown";
650 0 : sh.subset_info(5).name = "invalid";
651 0 : sh.subset_info(6).name = "replace";
652 0 : sh.subset_info(7).name = "no_nbrs";
653 0 : sh.subset_info(8).name = "unassigned";
654 0 : AssignSubsetColors(sh);
655 :
656 :
657 0 : if(MultiGrid* mg = dynamic_cast<MultiGrid*>(&g)){
658 0 : if(mg->num<Volume>() > 0)
659 0 : SaveGridHierarchyTransformed(*mg, sh, filename, 3);
660 : else
661 0 : SaveGridHierarchyTransformed(*mg, sh, filename, 0.1);
662 : }
663 : else
664 0 : SaveGridToFile(g, sh, filename);
665 0 : }
666 :
667 0 : void HangingNodeRefiner_MultiGrid::
668 : save_coarsen_marks_to_file(ISelector& sel, const char* filename)
669 : {
670 0 : SaveCoarsenMarksToFile(sel, filename);
671 0 : }
672 :
673 :
674 : /// temporary method, which will be removed when debugging is done.
675 0 : void HangingNodeRefiner_MultiGrid::
676 : debug_save(ISelector& sel, const char* filePrefix)
677 : {
678 0 : if(debugging_enabled()){
679 0 : stringstream ss;
680 0 : ss << filePrefix << "_p";
681 : #ifdef UG_PARALLEL
682 : ss << pcl::ProcRank();
683 : #else
684 0 : ss << "0";
685 : #endif
686 0 : ss << ".ugx";
687 : //UG_LOG("Saving coarsen debug marks: " << ss.str() << endl);
688 0 : save_coarsen_marks_to_file(sel, ss.str().c_str());
689 0 : }
690 0 : }
691 :
692 : /// temporary method, which will be removed when debugging is done.
693 0 : static void ContinuousDebugSave(ISelector& sel)
694 : {
695 : static int counter = 0;
696 0 : stringstream ss;
697 0 : ss << "coarsen_debug_" << counter << "_p";
698 : #ifdef UG_PARALLEL
699 : ss << pcl::ProcRank();
700 : #else
701 0 : ss << "0";
702 : #endif
703 0 : ss << ".ugx";
704 0 : UG_LOG("Saving coarsen debug marks: " << ss.str() << endl);
705 0 : SaveCoarsenMarksToFile(sel, ss.str().c_str());
706 0 : ++counter;
707 0 : }
708 :
709 : /// temporary method, which will be removed when debugging is done.
710 0 : static void ParallelLayoutDebugSave(MultiGrid& mg)
711 : {
712 : static int counter = 0;
713 0 : stringstream ss;
714 0 : ss << "coarsen_parallel_layout_" << counter << "_p";
715 : #ifdef UG_PARALLEL
716 : ss << pcl::ProcRank();
717 : #else
718 0 : ss << "0";
719 : #endif
720 0 : ss << ".ugx";
721 0 : UG_LOG("Saving coarsen parallel layout: " << ss.str() << endl);
722 0 : if(mg.num<Volume>() > 0)
723 0 : SaveParallelGridLayout(mg, ss.str().c_str(), 3);
724 : else
725 0 : SaveParallelGridLayout(mg, ss.str().c_str(), 0.1);
726 0 : ++counter;
727 0 : }
728 :
729 :
730 : //void HangingNodeRefiner_MultiGrid::
731 : //collect_objects_for_coarsen(bool scheduleCoarseningBeginsMessage)
732 : //{
733 : // MultiGrid& mg = *m_pMG;
734 : // selector_t& sel = get_refmark_selector();
735 : //
736 : // bool gotVols = contains_volumes();
737 : // bool gotFaces = contains_faces();
738 : // bool gotEdges = contains_edges();
739 : //
740 : //debug_save(sel, "coarsen_marks_01_start");
741 : //// deselect all elements of lower dimension, since we currently can't handle them correctly...
742 : ////todo: A more sophisticated approach could be used. E.g. only deselect elements if they
743 : //// are connected to an element of higher dimension.
744 : // if(gotVols)
745 : // sel.clear<Face>();
746 : //
747 : // if(gotFaces)
748 : // sel.clear<Edge>();
749 : //
750 : // if(gotEdges)
751 : // sel.clear<Vertex>();
752 : //
753 : //debug_save(sel, "coarsen_marks_01.5_only_full_dim_selected");
754 : // restrict_selection_to_surface_coarsen_elements();
755 : // copy_marks_to_vmasters(true, true, true, true);
756 : // restrict_selection_to_coarsen_families();
757 : // copy_marks_to_vslaves(true, true, true, true);
758 : //
759 : // SelectAssociatedEdges(sel, sel.begin<Face>(), sel.end<Face>(), HNCM_UNKNOWN);
760 : // SelectAssociatedEdges(sel, sel.begin<Volume>(), sel.end<Volume>(), HNCM_UNKNOWN);
761 : // broadcast_marks_horizontally(false, true, false);
762 : // copy_marks_to_vmasters(false, true, false, false);
763 : //
764 : //debug_save(sel, "coarsen_marks_02_restricted_to_surface_families");
765 : //
766 : // typedef vector<Edge*> EdgeVec;
767 : // EdgeVec vedges;
768 : // vedges.assign(sel.begin<Edge>(), sel.end<Edge>());
769 : //
770 : // Grid::edge_traits::secure_container edges;
771 : // Grid::face_traits::secure_container faces;
772 : // Grid::volume_traits::secure_container vols;
773 : //
774 : //// make sure that coarsening won't generate constraining edges with more than
775 : //// one constrained vertex.
776 : // bool running = gotVols || gotFaces;
777 : // while(running){
778 : // // classify unknown edges
779 : // for(EdgeVec::iterator iter = vedges.begin(); iter != vedges.end(); ++iter)
780 : // {
781 : // Edge* e = *iter;
782 : //
783 : // if(sel.get_selection_status(e) == HNCM_UNKNOWN){
784 : // size_t numSel = 0;
785 : // size_t numNbrs = 0;
786 : // if(gotVols){
787 : // mg.associated_elements(vols, e);
788 : // numNbrs = vols.size();
789 : // for(size_t i = 0; i < numNbrs; ++i){
790 : // if(sel.is_selected(vols[i]))
791 : // ++numSel;
792 : // }
793 : // }
794 : // else if(gotFaces){
795 : // mg.associated_elements(faces, e);
796 : // numNbrs = faces.size();
797 : // for(size_t i = 0; i < numNbrs; ++i){
798 : // if(sel.is_selected(faces[i]))
799 : // ++numSel;
800 : // }
801 : // }
802 : //
803 : // if(numNbrs > 0){
804 : // if(numSel == 0)
805 : // sel.select(e, HNCM_NONE);
806 : // else if(numSel < numNbrs)
807 : // sel.select(e, HNCM_PARTIAL);
808 : // else
809 : // sel.select(e, HNCM_ALL);
810 : // }
811 : // else
812 : // sel.select(e, HNCM_NO_NBRS);
813 : // }
814 : // }
815 : //
816 : // broadcast_marks_horizontally(false, true, false);
817 : // copy_marks_to_vmasters(false, true, false, false);
818 : //
819 : // // clear all edges which are marked with HNCM_NONE from the selection
820 : // for(selector_t::traits<Edge>::iterator iter = sel.begin<Edge>();
821 : // iter != sel.end<Edge>();)
822 : // {
823 : // Edge* e = *iter;
824 : // ++iter;
825 : // if(sel.get_selection_status(e) == HNCM_NONE)
826 : // sel.deselect(e);
827 : // }
828 : //
829 : // // if a constrained edge of a constraining edge won't be fully coarsened,
830 : // // then the constraining edge may not be coarsened at all.
831 : // bool foundInvalid = false;
832 : // for(selector_t::traits<ConstrainingEdge>::iterator iter = sel.begin<ConstrainingEdge>();
833 : // iter != sel.end<ConstrainingEdge>(); ++iter)
834 : // {
835 : // ConstrainingEdge* cge = *iter;
836 : // for(size_t i = 0; i < cge->num_constrained_edges(); ++i){
837 : // if(sel.get_selection_status(cge->constrained_edge(i)) != HNCM_ALL){
838 : // foundInvalid = true;
839 : // sel.select(cge, HNCM_INVALID);
840 : // break;
841 : // }
842 : // }
843 : // }
844 : //
845 : // // has anybody found an invalid parent? If not, exit adjustment.
846 : // if(!one_proc_true(foundInvalid)){
847 : // running = false;
848 : // break;
849 : // }
850 : //
851 : // // clear the current candidate vector
852 : // vedges.clear();
853 : //
854 : //
855 : // // exchange invalid marks
856 : // // we have to copy them to vmasters, since constraining ghost edges don't
857 : // // have an associated constrained edge from which they could obtain their
858 : // // invalid mark.
859 : // copy_marks_to_vmasters(false, true, false, false);
860 : //
861 : // for(selector_t::traits<Edge>::iterator iter = sel.begin<Edge>();
862 : // iter != sel.end<Edge>();)
863 : // {
864 : // Edge* e = *iter;
865 : // ++iter;
866 : // if(sel.get_selection_status(e) == HNCM_INVALID){
867 : // if(gotVols){
868 : // mg.associated_elements(vols, e);
869 : // for(size_t i_vol = 0; i_vol < vols.size(); ++i_vol){
870 : // if(!sel.is_selected(vols[i_vol]))
871 : // continue;
872 : // GridObject* parent = mg.get_parent(vols[i_vol]);
873 : // if(parent){
874 : // DeselectFamily(sel, mg, parent);
875 : // mg.associated_elements(edges, parent);
876 : // for(size_t i_edge = 0; i_edge < edges.size(); ++i_edge){
877 : // Edge* e = edges[i_edge];
878 : // if(sel.is_selected(e))
879 : // sel.select(e, HNCM_UNKNOWN);
880 : // for(size_t i = 0; i < mg.num_children<Edge>(e); ++i){
881 : // Edge* child = mg.get_child<Edge>(e, i);
882 : // if(sel.is_selected(child)){
883 : // sel.select(child, HNCM_UNKNOWN);
884 : // }
885 : // }
886 : // }
887 : //
888 : // // we also have to mark edge-children of side-faces as unknown
889 : // mg.associated_elements(faces, parent);
890 : // for(size_t i_face = 0; i_face < faces.size(); ++i_face){
891 : // Face* f = faces[i_face];
892 : // if(sel.is_selected(f))
893 : // sel.select(f, HNCM_UNKNOWN);
894 : // for(size_t i = 0; i < mg.num_children<Edge>(f); ++i){
895 : // Edge* child = mg.get_child<Edge>(f, i);
896 : // if(sel.is_selected(child)){
897 : // sel.select(child, HNCM_UNKNOWN);
898 : // }
899 : // }
900 : // }
901 : //
902 : // }
903 : // }
904 : // }
905 : // else if(gotFaces){
906 : // mg.associated_elements(faces, e);
907 : // for(size_t i_face = 0; i_face < faces.size(); ++i_face){
908 : // if(!sel.is_selected(faces[i_face]))
909 : // continue;
910 : // GridObject* parent = mg.get_parent(faces[i_face]);
911 : // if(parent){
912 : // DeselectFamily(sel, mg, parent);
913 : // mg.associated_elements(edges, parent);
914 : // for(size_t i_edge = 0; i_edge < edges.size(); ++i_edge){
915 : // if(sel.is_selected(edges[i_edge]))
916 : // sel.select(edges[i_edge], HNCM_UNKNOWN);
917 : // for(size_t i = 0; i < mg.num_children<Edge>(edges[i_edge]); ++i){
918 : // Edge* child = mg.get_child<Edge>(edges[i_edge], i);
919 : // if(sel.is_selected(child)){
920 : // sel.select(child, HNCM_UNKNOWN);
921 : // }
922 : // }
923 : // }
924 : // }
925 : // }
926 : // }
927 : //
928 : // // mark the formerly invalid edge as unknown
929 : // sel.select(e, HNCM_UNKNOWN);
930 : // }
931 : // }
932 : //
933 : // if(debugging_enabled()){
934 : // ContinuousDebugSave(sel);
935 : // }
936 : //
937 : // // since h-interfaces do not always exist between v-master copies,
938 : // // we have to perform an additional broadcast, to make sure, that all copies
939 : // // have the correct marks.
940 : // broadcast_marks_vertically(false, true, true, true, true);
941 : // if(debugging_enabled()){
942 : // ContinuousDebugSave(sel);
943 : // }
944 : //
945 : //
946 : //
947 : // // find edges which were marked as unknown and prepare qedges for the next run
948 : // for(selector_t::traits<Edge>::iterator iter = sel.begin<Edge>();
949 : // iter != sel.end<Edge>(); ++iter)
950 : // {
951 : // if(sel.get_selection_status(*iter) == HNCM_UNKNOWN)
952 : // vedges.push_back(*iter);
953 : // }
954 : // }
955 : //
956 : //debug_save(sel, "coarsen_marks_03_irregularities_resolved");
957 : //
958 : //// finally classify faces and vertices
959 : // SelectAssociatedFaces(sel, sel.begin<Volume>(), sel.end<Volume>(), HNCM_ALL);
960 : // SelectAssociatedVertices(sel, sel.begin<Edge>(), sel.end<Edge>(), HNCM_ALL);
961 : //
962 : // broadcast_marks_horizontally(true, false, true);
963 : // copy_marks_to_vmasters(true, false, true, false);
964 : //
965 : // if(gotVols){
966 : // for(selector_t::traits<Face>::iterator iter = sel.begin<Face>();
967 : // iter != sel.end<Face>();)
968 : // {
969 : // Face* f = *iter;
970 : // ++iter;
971 : //
972 : // mg.associated_elements(vols, f);
973 : // for(size_t i = 0; i < vols.size(); ++i){
974 : // if(!sel.is_selected(vols[i])){
975 : // sel.select(f, HNCM_PARTIAL);
976 : // break;
977 : // }
978 : // }
979 : // }
980 : // }
981 : //
982 : // for(selector_t::traits<Vertex>::iterator iter = sel.begin<Vertex>();
983 : // iter != sel.end<Vertex>();)
984 : // {
985 : // Vertex* v = *iter;
986 : // ++iter;
987 : //
988 : // mg.associated_elements(edges, v);
989 : // for(size_t i = 0; i < edges.size(); ++i){
990 : // if(sel.get_selection_status(edges[i]) != HNCM_ALL){
991 : // sel.select(v, HNCM_PARTIAL);
992 : // break;
993 : // }
994 : // }
995 : // }
996 : //
997 : // broadcast_marks_horizontally(true, false, true);
998 : // copy_marks_to_vmasters(true, false, true, false);
999 : //
1000 : //debug_save(sel, "coarsen_marks_04_faces_and_vertices_classified");
1001 : //
1002 : //
1003 : //// ATTENTION: We post the message that coarsening begins at this point, since
1004 : //// we don't want REPLACE elements to be selected and thus contained
1005 : //// in the specified geometric-object-collection.
1006 : // if(scheduleCoarseningBeginsMessage){
1007 : // m_messageHub->post_message(GridMessage_Adaption(GMAT_HNODE_COARSENING_BEGINS,
1008 : // m_selMarkedElements.get_grid_objects()));
1009 : // }
1010 : //
1011 : //
1012 : //// select unselected constraining edges and faces of selected constrained
1013 : //// edges and faces with HNCM_REPLACE to indicate, that they have to be
1014 : //// transformed to a normal edge
1015 : //// mark parents of normal and constraining edges and faces which were marked for
1016 : //// partial refinement with a replace mark
1017 : // for(selector_t::traits<Edge>::iterator
1018 : // iter = sel.begin<Edge>(); iter != sel.end<Edge>(); ++iter)
1019 : // {
1020 : // Edge* e = *iter;
1021 : // if(GridObject* parent = mg.get_parent(e)){
1022 : // bool isConstrained = e->is_constrained();
1023 : // if((isConstrained && (sel.get_selection_status(e) == HNCM_ALL)) ||
1024 : // ((!isConstrained) && (sel.get_selection_status(*iter) == HNCM_PARTIAL)))
1025 : // {
1026 : // if(!sel.is_selected(parent))
1027 : // sel.select(parent, HNCM_REPLACE);
1028 : // }
1029 : // }
1030 : // }
1031 : //
1032 : // for(selector_t::traits<Face>::iterator
1033 : // iter = sel.begin<Face>(); iter != sel.end<Face>(); ++iter)
1034 : // {
1035 : // Face* e = *iter;
1036 : // if(GridObject* parent = mg.get_parent(e)){
1037 : // bool isConstrained = e->is_constrained();
1038 : // if((isConstrained && (sel.get_selection_status(e) == HNCM_ALL)) ||
1039 : // ((!isConstrained) && (sel.get_selection_status(*iter) == HNCM_PARTIAL)))
1040 : // {
1041 : // if(!sel.is_selected(parent))
1042 : // sel.select(parent, HNCM_REPLACE);
1043 : // }
1044 : // }
1045 : // }
1046 : //
1047 : // broadcast_marks_horizontally(false, true, true);
1048 : // copy_marks_to_vmasters(false, true, true, false);
1049 : //
1050 : //debug_save(sel, "coarsen_marks_05_adjustment_done");
1051 : //}
1052 :
1053 0 : void HangingNodeRefiner_MultiGrid::
1054 : collect_objects_for_coarsen(bool scheduleCoarseningBeginsMessage)
1055 : {
1056 : PROFILE_FUNC();
1057 :
1058 0 : MultiGrid& mg = *m_pMG;
1059 : selector_t& sel = get_refmark_selector();
1060 :
1061 0 : bool gotVols = contains_volumes();
1062 0 : bool gotFaces = contains_faces();
1063 0 : bool gotEdges = contains_edges();
1064 :
1065 0 : debug_save(sel, "coarsen_marks_01_start");
1066 : // deselect all elements of lower dimension, since we currently can't handle them correctly...
1067 : //todo: A more sophisticated approach could be used. E.g. only deselect elements if they
1068 : // are connected to an element of higher dimension.
1069 0 : if(gotVols)
1070 0 : sel.clear<Face>();
1071 :
1072 0 : if(gotFaces)
1073 0 : sel.clear<Edge>();
1074 :
1075 0 : if(gotEdges)
1076 0 : sel.clear<Vertex>();
1077 :
1078 0 : restrict_selection_to_surface_coarsen_elements();
1079 0 : copy_marks_to_vmasters(true, true, true, true);
1080 0 : restrict_selection_to_coarsen_families();
1081 0 : copy_marks_to_vslaves(true, true, true, true);
1082 :
1083 0 : SelectAssociatedVertices(sel, sel.begin<Edge>(), sel.end<Edge>(), HNCM_UNKNOWN);
1084 0 : SelectAssociatedVertices(sel, sel.begin<Face>(), sel.end<Face>(), HNCM_UNKNOWN);
1085 0 : SelectAssociatedVertices(sel, sel.begin<Volume>(), sel.end<Volume>(), HNCM_UNKNOWN);
1086 0 : broadcast_marks_horizontally(true, false, false);
1087 0 : copy_marks_to_vmasters(true, false, false, false);
1088 :
1089 0 : debug_save(sel, "coarsen_marks_02_restricted_to_surface_families");
1090 :
1091 : typedef vector<Vertex*> VrtVec;
1092 : VrtVec vvrts;
1093 0 : vvrts.assign(sel.begin<Vertex>(), sel.end<Vertex>());
1094 :
1095 : Grid::vertex_traits::secure_container vrts;
1096 : Grid::edge_traits::secure_container edges;
1097 : Grid::face_traits::secure_container faces;
1098 : Grid::volume_traits::secure_container vols;
1099 :
1100 : // make sure that coarsening won't generate situations in which surface elements
1101 : // which meet at a common vertex have a level difference of more than 1.
1102 0 : bool running = gotVols || gotFaces;
1103 0 : while(running){
1104 : // classify unknown vertices
1105 0 : for(VrtVec::iterator iter = vvrts.begin(); iter != vvrts.end(); ++iter)
1106 : {
1107 0 : Vertex* e = *iter;
1108 :
1109 0 : if(sel.get_selection_status(e) == HNCM_UNKNOWN){
1110 : size_t numSel = 0;
1111 : size_t numNbrs = 0;
1112 0 : if(gotVols){
1113 0 : mg.associated_elements(vols, e);
1114 : numNbrs = vols.size();
1115 0 : for(size_t i = 0; i < numNbrs; ++i){
1116 0 : if(sel.is_selected(vols[i]))
1117 0 : ++numSel;
1118 : }
1119 : }
1120 0 : else if(gotFaces){
1121 0 : mg.associated_elements(faces, e);
1122 : numNbrs = faces.size();
1123 0 : for(size_t i = 0; i < numNbrs; ++i){
1124 0 : if(sel.is_selected(faces[i]))
1125 0 : ++numSel;
1126 : }
1127 : }
1128 :
1129 0 : if(numNbrs > 0){
1130 0 : if(numSel == 0)
1131 0 : sel.select(e, HNCM_NONE);
1132 0 : else if(numSel < numNbrs)
1133 0 : sel.select(e, HNCM_PARTIAL);
1134 : else
1135 0 : sel.select(e, HNCM_ALL);
1136 : }
1137 : else
1138 0 : sel.select(e, HNCM_NO_NBRS);
1139 : }
1140 : }
1141 :
1142 0 : broadcast_marks_horizontally(true, false, false);
1143 0 : copy_marks_to_vmasters(true, false, false, false);
1144 :
1145 : // clear all vertices which are marked with HNCM_NONE from the selection
1146 0 : for(selector_t::traits<Vertex>::iterator iter = sel.begin<Vertex>();
1147 0 : iter != sel.end<Vertex>();)
1148 : {
1149 : Vertex* e = *iter;
1150 : ++iter;
1151 0 : if(sel.get_selection_status(e) == HNCM_NONE)
1152 0 : sel.deselect(e);
1153 : }
1154 :
1155 : // if a vertex has a child which will not be fully coarsed then the
1156 : // vertex itself may not be coarsened at all (nor neighboring elements)
1157 : bool foundInvalid = false;
1158 0 : for(selector_t::traits<Vertex>::iterator iter = sel.begin<Vertex>();
1159 0 : iter != sel.end<Vertex>(); ++iter)
1160 : {
1161 : Vertex* e = *iter;
1162 : Vertex* c = mg.get_child_vertex(e);
1163 0 : if(c && sel.get_selection_status(c) != HNCM_ALL){
1164 : foundInvalid = true;
1165 0 : sel.select(e, HNCM_INVALID);
1166 : }
1167 : }
1168 :
1169 : // has anybody marked an element as invalid? If not, exit adjustment.
1170 0 : if(!one_proc_true(foundInvalid)){
1171 : break;
1172 : }
1173 :
1174 : // clear the current candidate vector
1175 : vvrts.clear();
1176 :
1177 : // exchange invalid marks
1178 : // we have to copy them to vmasters, since in some situations there may be
1179 : // ghost-vertices which are shadows of vertices which lie on the rim of a level...
1180 0 : copy_marks_to_vmasters(true, false, false, false);
1181 :
1182 : // we have to deselect all families which are connected to invalid vertices
1183 0 : for(selector_t::traits<Vertex>::iterator iter = sel.begin<Vertex>();
1184 0 : iter != sel.end<Vertex>();)
1185 : {
1186 : Vertex* e = *iter;
1187 : ++iter;
1188 0 : if(sel.get_selection_status(e) == HNCM_INVALID){
1189 0 : if(gotVols){
1190 0 : mg.associated_elements(vols, e);
1191 0 : for(size_t i_vol = 0; i_vol < vols.size(); ++i_vol){
1192 0 : if(!sel.is_selected(vols[i_vol]))
1193 0 : continue;
1194 : GridObject* parent = mg.get_parent(vols[i_vol]);
1195 0 : if(parent){
1196 0 : DeselectFamily(sel, mg, parent);
1197 : mg.associated_elements(vrts, parent);
1198 0 : for(size_t i_vrt = 0; i_vrt < vrts.size(); ++i_vrt){
1199 : Vertex* vrt = vrts[i_vrt];
1200 0 : if(sel.is_selected(vrt))
1201 0 : sel.select(vrt, HNCM_UNKNOWN);
1202 :
1203 : Vertex* c = mg.get_child_vertex(vrt);
1204 0 : if(c && sel.is_selected(c)){
1205 0 : sel.select(c, HNCM_UNKNOWN);
1206 : }
1207 : }
1208 :
1209 : // we also have to mark vertex-children of side-faces
1210 : // and side-edges as unknown
1211 : mg.associated_elements(edges, parent);
1212 0 : for(size_t i_edge = 0; i_edge < edges.size(); ++i_edge){
1213 : Edge* edge = edges[i_edge];
1214 0 : if(sel.is_selected(edge))
1215 0 : sel.select(edge, HNCM_UNKNOWN);
1216 :
1217 : Vertex* c = mg.get_child_vertex(edge);
1218 0 : if(c && sel.is_selected(c)){
1219 0 : sel.select(c, HNCM_UNKNOWN);
1220 : }
1221 : }
1222 :
1223 : mg.associated_elements(faces, parent);
1224 0 : for(size_t i_face = 0; i_face < faces.size(); ++i_face){
1225 : Face* f = faces[i_face];
1226 0 : if(sel.is_selected(f))
1227 0 : sel.select(f, HNCM_UNKNOWN);
1228 :
1229 : Vertex* c = mg.get_child_vertex(f);
1230 0 : if(c && sel.is_selected(c)){
1231 0 : sel.select(c, HNCM_UNKNOWN);
1232 : }
1233 : }
1234 :
1235 : }
1236 : }
1237 : }
1238 0 : else if(gotFaces){
1239 0 : mg.associated_elements(faces, e);
1240 0 : for(size_t i_face = 0; i_face < faces.size(); ++i_face){
1241 0 : if(!sel.is_selected(faces[i_face]))
1242 0 : continue;
1243 : GridObject* parent = mg.get_parent(faces[i_face]);
1244 0 : if(parent){
1245 0 : DeselectFamily(sel, mg, parent);
1246 : mg.associated_elements(vrts, parent);
1247 0 : for(size_t i_vrt = 0; i_vrt < vrts.size(); ++i_vrt){
1248 : Vertex* vrt = vrts[i_vrt];
1249 0 : if(sel.is_selected(vrt))
1250 0 : sel.select(vrt, HNCM_UNKNOWN);
1251 :
1252 : Vertex* c = mg.get_child_vertex(vrt);
1253 0 : if(c && sel.is_selected(c)){
1254 0 : sel.select(c, HNCM_UNKNOWN);
1255 : }
1256 : }
1257 :
1258 : // we also have to mark vertex-children of side-edges
1259 : mg.associated_elements(edges, parent);
1260 0 : for(size_t i_edge = 0; i_edge < edges.size(); ++i_edge){
1261 : Edge* edge = edges[i_edge];
1262 0 : if(sel.is_selected(edge))
1263 0 : sel.select(edge, HNCM_UNKNOWN);
1264 :
1265 : Vertex* c = mg.get_child_vertex(edge);
1266 0 : if(c && sel.is_selected(c)){
1267 0 : sel.select(c, HNCM_UNKNOWN);
1268 : }
1269 : }
1270 : }
1271 : }
1272 : }
1273 :
1274 : // mark the formerly invalid vertex as unknown
1275 0 : sel.select(e, HNCM_UNKNOWN);
1276 : }
1277 : }
1278 :
1279 0 : if(debugging_enabled()){
1280 0 : ContinuousDebugSave(sel);
1281 : }
1282 :
1283 : // since h-interfaces do not always exist between v-master copies,
1284 : // we have to perform an additional broadcast, to make sure, that all copies
1285 : // have the correct marks.
1286 0 : broadcast_marks_vertically(true, true, true, true, true);
1287 0 : if(debugging_enabled()){
1288 0 : ContinuousDebugSave(sel);
1289 : }
1290 :
1291 :
1292 :
1293 : // find vertices which were marked as unknown and prepare the candidates array for the next run
1294 0 : for(selector_t::traits<Vertex>::iterator iter = sel.begin<Vertex>();
1295 0 : iter != sel.end<Vertex>(); ++iter)
1296 : {
1297 0 : if(sel.get_selection_status(*iter) == HNCM_UNKNOWN)
1298 0 : vvrts.push_back(*iter);
1299 : }
1300 : }
1301 :
1302 0 : debug_save(sel, "coarsen_marks_03_irregularities_resolved");
1303 :
1304 : // finally classify faces and edges
1305 0 : SelectAssociatedFaces(sel, sel.begin<Volume>(), sel.end<Volume>(), HNCM_ALL);
1306 0 : SelectAssociatedEdges(sel, sel.begin<Face>(), sel.end<Face>(), HNCM_ALL);
1307 :
1308 : // we only have to communicate face marks if volumes exist
1309 0 : if(gotVols){
1310 0 : broadcast_marks_horizontally(false, true, true);
1311 0 : copy_marks_to_vmasters(false, true, true, false);
1312 : }
1313 : else{
1314 0 : broadcast_marks_horizontally(false, true, false);
1315 0 : copy_marks_to_vmasters(false, true, false, false);
1316 : }
1317 :
1318 0 : if(gotVols){
1319 0 : for(selector_t::traits<Face>::iterator iter = sel.begin<Face>();
1320 0 : iter != sel.end<Face>();)
1321 : {
1322 : Face* f = *iter;
1323 : ++iter;
1324 :
1325 0 : mg.associated_elements(vols, f);
1326 0 : for(size_t i = 0; i < vols.size(); ++i){
1327 0 : if(!sel.is_selected(vols[i])){
1328 0 : sel.select(f, HNCM_PARTIAL);
1329 : break;
1330 : }
1331 : }
1332 : }
1333 :
1334 0 : for(selector_t::traits<Edge>::iterator iter = sel.begin<Edge>();
1335 0 : iter != sel.end<Edge>();)
1336 : {
1337 : Edge* e = *iter;
1338 : ++iter;
1339 :
1340 0 : mg.associated_elements(vols, e);
1341 0 : for(size_t i = 0; i < vols.size(); ++i){
1342 0 : if(!sel.is_selected(vols[i])){
1343 0 : sel.select(e, HNCM_PARTIAL);
1344 : break;
1345 : }
1346 : }
1347 : }
1348 : }
1349 0 : else if(gotFaces){
1350 0 : for(selector_t::traits<Edge>::iterator iter = sel.begin<Edge>();
1351 0 : iter != sel.end<Edge>();)
1352 : {
1353 : Edge* e = *iter;
1354 : ++iter;
1355 :
1356 0 : mg.associated_elements(faces, e);
1357 0 : for(size_t i = 0; i < faces.size(); ++i){
1358 0 : if(!sel.is_selected(faces[i])){
1359 0 : sel.select(e, HNCM_PARTIAL);
1360 : break;
1361 : }
1362 : }
1363 : }
1364 : }
1365 :
1366 0 : if(gotVols){
1367 0 : broadcast_marks_horizontally(false, true, true);
1368 0 : copy_marks_to_vmasters(false, true, true, false);
1369 : }
1370 : else{
1371 0 : broadcast_marks_horizontally(false, true, false);
1372 0 : copy_marks_to_vmasters(false, true, false, false);
1373 : }
1374 :
1375 0 : debug_save(sel, "coarsen_marks_04_faces_and_vertices_classified");
1376 :
1377 :
1378 : // ATTENTION: We post the message that coarsening begins at this point, since
1379 : // we don't want REPLACE elements to be selected and thus contained
1380 : // in the specified geometric-object-collection.
1381 0 : if(scheduleCoarseningBeginsMessage){
1382 0 : m_messageHub->post_message(GridMessage_Adaption(GMAT_HNODE_COARSENING_BEGINS,
1383 0 : m_selMarkedElements.get_grid_objects()));
1384 : }
1385 :
1386 :
1387 : // select unselected constraining edges and faces of selected constrained
1388 : // edges and faces with HNCM_REPLACE to indicate, that they have to be
1389 : // transformed to a normal edge
1390 : // mark parents of normal and constraining edges and faces which were marked for
1391 : // partial refinement with a replace mark
1392 : for(selector_t::traits<Edge>::iterator
1393 0 : iter = sel.begin<Edge>(); iter != sel.end<Edge>(); ++iter)
1394 : {
1395 : Edge* e = *iter;
1396 0 : if(GridObject* parent = mg.get_parent(e)){
1397 0 : bool isConstrained = e->is_constrained();
1398 0 : if((isConstrained && (sel.get_selection_status(e) == HNCM_ALL)) ||
1399 0 : ((!isConstrained) && (sel.get_selection_status(*iter) == HNCM_PARTIAL)))
1400 : {
1401 0 : if(!sel.is_selected(parent))
1402 0 : sel.select(parent, HNCM_REPLACE);
1403 : }
1404 : }
1405 : }
1406 :
1407 0 : if(gotVols){
1408 : for(selector_t::traits<Face>::iterator
1409 0 : iter = sel.begin<Face>(); iter != sel.end<Face>(); ++iter)
1410 : {
1411 : Face* e = *iter;
1412 0 : if(GridObject* parent = mg.get_parent(e)){
1413 0 : bool isConstrained = e->is_constrained();
1414 0 : if((isConstrained && (sel.get_selection_status(e) == HNCM_ALL)) ||
1415 0 : ((!isConstrained) && (sel.get_selection_status(*iter) == HNCM_PARTIAL)))
1416 : {
1417 0 : if(!sel.is_selected(parent))
1418 0 : sel.select(parent, HNCM_REPLACE);
1419 : }
1420 : }
1421 : }
1422 : }
1423 :
1424 : if(gotVols){
1425 0 : broadcast_marks_horizontally(false, true, true);
1426 0 : copy_marks_to_vmasters(false, true, true, false);
1427 : }
1428 : else{
1429 0 : broadcast_marks_horizontally(false, true, false);
1430 0 : copy_marks_to_vmasters(false, true, false, false);
1431 : }
1432 :
1433 0 : debug_save(sel, "coarsen_marks_05_adjustment_done");
1434 0 : }
1435 :
1436 0 : bool HangingNodeRefiner_MultiGrid::
1437 : perform_coarsening()
1438 : {
1439 : PROFILE_FUNC();
1440 : /*
1441 : We have to handle elements as follows:
1442 :
1443 : normal edge:
1444 : All nbrs marked: remove
1445 : Some nbrs marked (hnode):
1446 : If has (unconstrained) parent:
1447 : convert to constrained. If parent is normal, then make parent constraining.
1448 : add edge to constrained elements of parent.
1449 : else
1450 : keep edge
1451 :
1452 : constrained edge:
1453 : All nbrs marked: remove
1454 : Some nbrs marked (hnode): keep (important for 3d)
1455 :
1456 : constraining edge (hnode) (only marked, if associated constrained edges are marked, too):
1457 : (All nbrs can't be marked)
1458 : Some nbrs marked:
1459 : If has (unconstrained) parent:
1460 : convert to constrained. If parent is normal, then make parent constraining.
1461 : add edge to constrained elements of parent.
1462 : else
1463 : convert to normal edge
1464 :
1465 : constraining edge (no hnode - no nbrs marked, but children are marked):
1466 : Convert to normal edge
1467 : */
1468 0 : if(!m_pMG)
1469 : return false;
1470 :
1471 : MultiGrid& mg = *m_pMG;
1472 : selector_t& sel = get_refmark_selector();
1473 :
1474 : // We let collect-objects-for-coarsen schedule the message that coarsening begins
1475 0 : collect_objects_for_coarsen(true);
1476 :
1477 : // if a debug file was specified, we'll now save the marks to that file
1478 0 : if(!m_adjustedMarksDebugFilename.empty())
1479 0 : save_coarsen_marks_to_file(sel, m_adjustedMarksDebugFilename.c_str());
1480 :
1481 : // inform derived classes that coarsening begins
1482 0 : pre_coarsen();
1483 :
1484 : ////////////////////
1485 : // VOLUMES
1486 : // erase elements and introduce constraining/constrained elements as required.
1487 0 : mg.erase(sel.begin<Volume>(), sel.end<Volume>());
1488 :
1489 : ////////////////////
1490 : // FACES
1491 0 : for(selector_t::traits<Face>::iterator iter = sel.begin<Face>();
1492 0 : iter != sel.end<Face>();)
1493 : {
1494 : Face* elem = *iter;
1495 : ++iter;
1496 : ISelector::status_t selState = sel.get_selection_status(elem);
1497 0 : sel.deselect(elem);
1498 :
1499 0 : switch(selState){
1500 0 : case RM_COARSEN:
1501 : case HNCM_ALL:{
1502 : // this should only be set on normal or constrained faces
1503 : assert(!elem->is_constraining());
1504 0 : mg.erase(elem);
1505 : }break;
1506 :
1507 0 : case HNCM_PARTIAL:{
1508 0 : if(elem->is_constrained()){
1509 : // a constrained element where not all nbrs are selected
1510 : // will be kept as it is.
1511 0 : continue;
1512 : }
1513 :
1514 : UG_ASSERT(mg.parent_type(elem) == FACE,
1515 : "Only a face with a parent-face may be marked for "
1516 : "partial coarsening!");
1517 :
1518 : // replace elem by a constrained face
1519 : ConstrainedFace* cdf = NULL;
1520 0 : switch(elem->reference_object_id()){
1521 0 : case ROID_TRIANGLE:
1522 0 : cdf = *mg.create_and_replace<ConstrainedTriangle>(elem);
1523 0 : break;
1524 0 : case ROID_QUADRILATERAL:
1525 0 : cdf = *mg.create_and_replace<ConstrainedQuadrilateral>(elem);
1526 0 : break;
1527 0 : default:
1528 0 : UG_THROW("Unknown face reference object type in "
1529 : "HangingNodeRefiner_MultiGrid::coarsen");
1530 : break;
1531 : }
1532 :
1533 : elem = cdf;
1534 :
1535 :
1536 : // the face has to be replaced by a constrained face.
1537 : // Volume-children don't have to be considered here, since
1538 : // they should all be marked with HNCM_ALL_NBRS_SELECTED
1539 0 : Face* parent = dynamic_cast<Face*>(mg.get_parent(elem));
1540 :
1541 0 : if(parent){
1542 : // the parent may not be a constrained object
1543 : UG_ASSERT(!parent->is_constrained(),
1544 : "An element with a constrained parent may not be marked"
1545 : " for partial coarsening!");
1546 :
1547 : // check whether the parent is already constraining.
1548 : // if not, it will be transformed to a constraining element later on
1549 : // and the connection is established then.
1550 0 : ConstrainingFace* cf = dynamic_cast<ConstrainingFace*>(parent);
1551 0 : if(cf){
1552 0 : cf->add_constrained_object(cdf);
1553 : cdf->set_constraining_object(cf);
1554 : }
1555 : }
1556 : else{
1557 : // There is no parent on the local process. We thus only set the
1558 : // type of the constraining element
1559 0 : cdf->set_parent_base_object_id(mg.parent_type(cdf));
1560 : }
1561 :
1562 : }break;
1563 :
1564 0 : case HNCM_REPLACE:{
1565 : assert(!elem->is_constrained());
1566 0 : if(elem->is_constraining()){
1567 : #ifdef UG_DEBUG
1568 : // make sure that the associated constrained vertex will be removed
1569 : ConstrainingFace* cf = dynamic_cast<ConstrainingFace*>(elem);
1570 : if(cf->num_constrained_vertices() > 0){
1571 : Vertex* hv = cf->constrained_vertex(0);
1572 : UG_ASSERT(sel.get_selection_status(hv) == HNCM_ALL,
1573 : "A constraining face may only be replaced by a normal face"
1574 : " during coarsening, if its constrained vertex will be removed."
1575 : " At: " << ElementDebugInfo(mg, elem));
1576 : }
1577 : #endif
1578 :
1579 : // the constraining face has to be transformed to a normal face
1580 0 : switch(elem->reference_object_id()){
1581 0 : case ROID_TRIANGLE:
1582 0 : mg.create_and_replace<Triangle>(elem);
1583 0 : break;
1584 0 : case ROID_QUADRILATERAL:
1585 0 : mg.create_and_replace<Quadrilateral>(elem);
1586 0 : break;
1587 0 : default:
1588 0 : UG_THROW("Unknown face reference object type in "
1589 : "HangingNodeRefiner_MultiGrid::coarsen");
1590 : break;
1591 : }
1592 : }
1593 : else{
1594 : // transform the face to a constraining face
1595 : ConstrainingFace* cf = NULL;
1596 0 : switch(elem->reference_object_id()){
1597 0 : case ROID_TRIANGLE:
1598 0 : cf = *mg.create_and_replace<ConstrainingTriangle>(elem);
1599 0 : break;
1600 0 : case ROID_QUADRILATERAL:
1601 0 : cf = *mg.create_and_replace<ConstrainingQuadrilateral>(elem);
1602 0 : break;
1603 0 : default:
1604 0 : UG_THROW("Unknown face reference object type in "
1605 : "HangingNodeRefiner_MultiGrid::coarsen");
1606 : break;
1607 : }
1608 :
1609 : // make sure that a connection with constrained children is established
1610 : // note - associated constrained vertices and constrained edges can
1611 : // not exist at this point.
1612 0 : for(size_t i = 0; i < mg.num_children<Face>(cf); ++i){
1613 0 : if(ConstrainedFace* cdf =
1614 0 : dynamic_cast<ConstrainedFace*>(mg.get_child<Face>(cf, i)))
1615 : {
1616 0 : cf->add_constrained_object(cdf);
1617 : cdf->set_constraining_object(cf);
1618 : }
1619 : }
1620 : }
1621 :
1622 : }break;
1623 :
1624 0 : default:
1625 0 : UG_THROW("Bad selection mark on face during "
1626 : "HangingNodeRefiner_MultiGrid::coarsen. Internal error.");
1627 : break;
1628 : }
1629 : }
1630 :
1631 : ////////////////////
1632 : // EDGES
1633 0 : for(selector_t::traits<Edge>::iterator iter = sel.begin<Edge>();
1634 0 : iter != sel.end<Edge>();)
1635 : {
1636 : Edge* elem = *iter;
1637 : ++iter;
1638 : ISelector::status_t selState = sel.get_selection_status(elem);
1639 0 : sel.deselect(elem);
1640 :
1641 0 : switch(selState){
1642 0 : case RM_COARSEN:
1643 : case HNCM_ALL:{
1644 : // this should only be set on normal or constrained edges
1645 : assert(!elem->is_constraining());
1646 0 : mg.erase(elem);
1647 : }break;
1648 :
1649 0 : case HNCM_PARTIAL:{
1650 0 : if(elem->is_constrained()){
1651 : // a constrained element where not all nbrs are selected
1652 : // will be kept as it is.
1653 0 : continue;
1654 : }
1655 :
1656 : UG_ASSERT(mg.parent_type(elem) != VOLUME,
1657 : "Children of volume elements may not be marked for"
1658 : " partial coarsening!");
1659 :
1660 : // replace the edge by a constrained edge
1661 0 : ConstrainedEdge* cde = *mg.create_and_replace<ConstrainedEdge>(elem);
1662 : elem = cde;
1663 :
1664 : // establish connection to constraining element
1665 : GridObject* parent = mg.get_parent(cde);
1666 0 : if(parent){
1667 0 : switch(parent->base_object_id()){
1668 : case EDGE:{
1669 0 : Edge* edgeParent = dynamic_cast<Edge*>(parent);
1670 : UG_ASSERT(edgeParent, "Severe type error during coarsing - bad parent type: "
1671 : << ElementDebugInfo(mg, elem));
1672 :
1673 : // check whether the parent is already constraining
1674 0 : ConstrainingEdge* ce = dynamic_cast<ConstrainingEdge*>(edgeParent);
1675 0 : if(ce){
1676 0 : ce->add_constrained_object(cde);
1677 : cde->set_constraining_object(ce);
1678 : }
1679 : }break;
1680 : case FACE:{
1681 : // if the parent is a face, then it the face should have been converted
1682 : // to a constraining face during the face-coarsening step. If it hasn't
1683 : // been converted, then the somethings wrong with the selection states.
1684 0 : ConstrainingFace* cf = dynamic_cast<ConstrainingFace*>(parent);
1685 : UG_ASSERT(cf, "The parent face should have been transformed"
1686 : " to a constraining face already: "
1687 : << ElementDebugInfo(mg, cf));
1688 0 : cf->add_constrained_object(cde);
1689 : cde->set_constraining_object(cf);
1690 0 : continue;
1691 0 : }break;
1692 0 : default:
1693 0 : UG_THROW("Unsupported parent type during partial coarsening: "
1694 : << ElementDebugInfo(mg, parent));
1695 : break;
1696 : }
1697 : }
1698 : else{
1699 : // since no parent is present on the local process, we have to
1700 : // manually set the type of the constraining element.
1701 0 : cde->set_parent_base_object_id(mg.parent_type(cde));
1702 : }
1703 : }break;
1704 :
1705 0 : case HNCM_REPLACE:{
1706 : // this should only not be set on constrained edges
1707 : UG_ASSERT(!elem->is_constrained(), "RegularEdge should not be constrained: "
1708 : << ElementDebugInfo(mg, elem));
1709 0 : if(elem->is_constraining()){
1710 : // the constraining edge has to be transformed to a normal edge
1711 : #ifdef UG_DEBUG
1712 : // make sure that the associated constrained vertex will be removed
1713 : ConstrainingEdge* ce = dynamic_cast<ConstrainingEdge*>(elem);
1714 : if(ce->num_constrained_vertices() > 0){
1715 : Vertex* hv = ce->constrained_vertex(0);
1716 : UG_ASSERT(sel.get_selection_status(hv) == HNCM_ALL,
1717 : "A constraining edge may only be replaced by a normal edge"
1718 : " during coarsening, if its constrained vertex will be removed."
1719 : " At: " << ElementDebugInfo(mg, elem));
1720 : }
1721 : #endif
1722 :
1723 0 : mg.create_and_replace<RegularEdge>(elem);
1724 : }
1725 : else{
1726 : // transform the edge to a constraining edge
1727 0 : ConstrainingEdge* cge = *mg.create_and_replace<ConstrainingEdge>(elem);
1728 : // make sure that a connection with constrained children is established
1729 : // note - associated constrained vertices and constrained edges can
1730 : // not exist at this point.
1731 0 : for(size_t i = 0; i < mg.num_children<Edge>(cge); ++i){
1732 0 : if(ConstrainedEdge* cde =
1733 0 : dynamic_cast<ConstrainedEdge*>(mg.get_child<Edge>(cge, i)))
1734 : {
1735 0 : cge->add_constrained_object(cde);
1736 : cde->set_constraining_object(cge);
1737 : }
1738 : }
1739 : }
1740 : }break;
1741 :
1742 0 : default:
1743 0 : UG_THROW("Bad selection mark on edge during "
1744 : "HangingNodeRefiner_MultiGrid::coarsen. Internal error: "
1745 : << ElementDebugInfo(mg, elem));
1746 : break;
1747 : }
1748 : }
1749 :
1750 : ////////////////////
1751 : // VERTICES
1752 0 : for(selector_t::traits<Vertex>::iterator iter = sel.begin<Vertex>();
1753 0 : iter != sel.end<Vertex>();)
1754 : {
1755 : Vertex* elem = *iter;
1756 : ++iter;
1757 : ISelector::status_t selState = sel.get_selection_status(elem);
1758 0 : sel.deselect(elem);
1759 :
1760 0 : switch(selState){
1761 0 : case RM_COARSEN:
1762 : case HNCM_ALL:{
1763 0 : mg.erase(elem);
1764 : }break;
1765 :
1766 0 : case HNCM_PARTIAL:{
1767 0 : if(elem->is_constrained()){
1768 : // a constrained element where not all nbrs are selected
1769 : // will be kept as it is.
1770 0 : continue;
1771 : }
1772 :
1773 : // a constrained vertex is only created if the parent is an edge or a face
1774 : ConstrainedVertex* hv = NULL;
1775 : char parentType = mg.parent_type(elem);
1776 0 : if((parentType == EDGE) || (parentType == FACE)){
1777 0 : hv = *mg.create_and_replace<ConstrainedVertex>(elem);
1778 : // elem = hv; // never used
1779 : }
1780 : else
1781 : break;
1782 :
1783 : // associated constrained and constraining elements
1784 : GridObject* parent = mg.get_parent(hv);
1785 :
1786 0 : if(parent){
1787 : // the parent may not be a constrained object
1788 : UG_ASSERT(!parent->is_constrained(),
1789 : "An element with a constrained parent may not be marked"
1790 : " for partial coarsening: " << ElementDebugInfo(mg, parent));
1791 :
1792 : // if the parent is an edge or a face, the vertex will be converted
1793 : // to a hanging-vertex
1794 0 : switch(parent->base_object_id()){
1795 : case EDGE:{
1796 : // the parent already has to be a constraining edge, due to
1797 : // the operations performed during edge-coarsening
1798 0 : ConstrainingEdge* ce = dynamic_cast<ConstrainingEdge*>(parent);
1799 : UG_ASSERT(ce, "The parent edge already has to be constraining: "
1800 : << ElementDebugInfo(mg, parent));
1801 : UG_ASSERT(ce->num_constrained_vertices() == 0,
1802 : "The parent edge may not yet have any constrained vertices: "
1803 : << ElementDebugInfo(mg, parent));
1804 :
1805 0 : ce->add_constrained_object(hv);
1806 : hv->set_constraining_object(ce);
1807 : hv->set_local_coordinate_1(0.5);
1808 : }break;
1809 :
1810 : case FACE:{
1811 : // the parent already has to be a constraining face, due to
1812 : // the operations performed during face-coarsening
1813 0 : ConstrainingFace* cf = dynamic_cast<ConstrainingFace*>(parent);
1814 : UG_ASSERT(cf, "The parent face already has to be constraining: "
1815 : << ElementDebugInfo(mg, parent));
1816 : UG_ASSERT(cf->num_constrained_vertices() == 0,
1817 : "The parent face may not yet have any constrained vertices: "
1818 : << ElementDebugInfo(mg, parent));
1819 :
1820 0 : cf->add_constrained_object(hv);
1821 : hv->set_constraining_object(cf);
1822 : hv->set_local_coordinates(0.5, 0.5);
1823 : }break;
1824 :
1825 0 : default:
1826 0 : UG_THROW("Unsupported parent type during partial"
1827 : " vertex coarsening: " << ElementDebugInfo(mg, parent));
1828 : break;
1829 : }
1830 : }
1831 : else{
1832 : // There is no parent on the local process. We thus only set the
1833 : // type of the constraining element
1834 0 : hv->set_parent_base_object_id(mg.parent_type(hv));
1835 : }
1836 :
1837 : }break;
1838 :
1839 0 : default:
1840 0 : UG_THROW("Bad selection mark on vertex during "
1841 : "HangingNodeRefiner_MultiGrid::coarsen. Internal error: "
1842 : << ElementDebugInfo(mg, elem));
1843 : break;
1844 : }
1845 : }
1846 :
1847 0 : debug_save(sel, "coarsen_marks_06_coarsening_done");
1848 0 : if(debugging_enabled()){
1849 0 : ParallelLayoutDebugSave(mg);
1850 : }
1851 :
1852 : //ContinuousDebugSave(sel);
1853 : // inform derived classes that coarsening is done
1854 0 : post_coarsen();
1855 0 : clear_marks();
1856 0 : m_messageHub->post_message(GridMessage_Adaption(GMAT_HNODE_COARSENING_ENDS));
1857 :
1858 0 : return true;
1859 : }
1860 :
1861 : }// end of namespace
1862 :
|