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 <vector>
34 : #include "hanging_node_refiner_grid.h"
35 : #include "lib_grid/algorithms/geom_obj_util/geom_obj_util.h"
36 : #include "ref_mark_adjusters/local_mark_adjuster.h"
37 :
38 : using namespace std;
39 :
40 : namespace ug{
41 :
42 0 : HangingNodeRefiner_Grid::
43 0 : HangingNodeRefiner_Grid(SPRefinementProjector projector) :
44 : BaseClass(projector),
45 0 : m_pGrid(NULL),
46 0 : m_aVertex(false)
47 : {
48 :
49 0 : }
50 :
51 0 : HangingNodeRefiner_Grid::
52 : HangingNodeRefiner_Grid(Grid& grid,
53 0 : SPRefinementProjector projector) :
54 : BaseClass(projector),
55 0 : m_pGrid(NULL),
56 0 : m_aVertex(false)
57 : {
58 0 : set_grid(&grid);
59 0 : }
60 :
61 0 : HangingNodeRefiner_Grid::
62 0 : ~HangingNodeRefiner_Grid()
63 : {
64 0 : set_grid(NULL);
65 0 : }
66 :
67 0 : void HangingNodeRefiner_Grid::
68 : grid_to_be_destroyed(Grid* grid)
69 : {
70 0 : set_grid(NULL);
71 0 : }
72 :
73 0 : void HangingNodeRefiner_Grid::
74 : assign_grid(Grid& grid)
75 : {
76 0 : set_grid(&grid);
77 0 : }
78 :
79 0 : void HangingNodeRefiner_Grid::
80 : set_grid(Grid* grid)
81 : {
82 : // call base class implementation
83 0 : BaseClass::set_grid(grid);
84 :
85 : // clear own attachments
86 0 : if(m_pGrid)
87 : {
88 0 : m_pGrid->detach_from_edges(m_aVertex);
89 0 : m_pGrid->detach_from_faces(m_aVertex);
90 0 : m_pGrid->detach_from_faces(m_aLocalMark);
91 0 : m_pGrid->detach_from_volumes(m_aLocalMark);
92 : m_aaLocalMark.invalidate();
93 0 : m_pGrid = NULL;
94 : }
95 :
96 : // attach new attachments
97 0 : if(grid){
98 0 : grid->attach_to_edges_dv(m_aVertex, NULL, false);
99 0 : grid->attach_to_faces_dv(m_aVertex, NULL, false);
100 :
101 : m_aaVertexEDGE.access(*grid, m_aVertex);
102 : m_aaVertexFACE.access(*grid, m_aVertex);
103 :
104 0 : m_pGrid = grid;
105 : }
106 0 : }
107 :
108 0 : bool HangingNodeRefiner_Grid::mark(Vertex* v, RefinementMark refMark)
109 : {
110 0 : if(refMark != RM_COARSEN)
111 0 : return BaseClass::mark(v, refMark);
112 : return false;
113 : }
114 :
115 0 : bool HangingNodeRefiner_Grid::mark(Edge* e, RefinementMark refMark)
116 : {
117 0 : if(refMark != RM_COARSEN)
118 0 : return BaseClass::mark(e, refMark);
119 : return false;
120 : }
121 :
122 0 : bool HangingNodeRefiner_Grid::mark(Face* f, RefinementMark refMark)
123 : {
124 0 : if(refMark != RM_COARSEN)
125 0 : return BaseClass::mark(f, refMark);
126 : return false;
127 : }
128 :
129 0 : bool HangingNodeRefiner_Grid::mark(Volume* v, RefinementMark refMark)
130 : {
131 0 : if(refMark != RM_COARSEN)
132 0 : return BaseClass::mark(v, refMark);
133 : return false;
134 : }
135 :
136 :
137 0 : void HangingNodeRefiner_Grid::
138 : mark_local(Face* e, int localMark)
139 : {
140 0 : if(!m_aaLocalMark.is_valid_face_accessor())
141 0 : attach_local_marks();
142 :
143 : // make sure that the local mark is considered a new mark
144 0 : if(adjusting_ref_marks() && marked_local(e) && (localMark != m_aaLocalMark[e]))
145 0 : mark(e, RM_NONE);
146 :
147 0 : m_aaLocalMark[e] = localMark;
148 0 : mark(e, RM_LOCAL);
149 0 : }
150 :
151 0 : void HangingNodeRefiner_Grid::
152 : mark_local(Volume* e, int localMark)
153 : {
154 0 : if(!m_aaLocalMark.is_valid_volume_accessor())
155 0 : attach_local_marks();
156 :
157 : // make sure that the local mark is considered a new mark
158 0 : if(adjusting_ref_marks() && marked_local(e) && (localMark != m_aaLocalMark[e]))
159 0 : mark(e, RM_NONE);
160 :
161 0 : m_aaLocalMark[e] = localMark;
162 0 : mark(e, RM_LOCAL);
163 0 : }
164 :
165 :
166 0 : int HangingNodeRefiner_Grid::
167 : get_local_mark(Face* e) const
168 : {
169 0 : if(m_aaLocalMark.is_valid_face_accessor())
170 0 : return m_aaLocalMark[e];
171 : return 0;
172 : }
173 :
174 0 : int HangingNodeRefiner_Grid::
175 : get_local_mark(Volume* e) const
176 : {
177 0 : if(m_aaLocalMark.is_valid_volume_accessor())
178 0 : return m_aaLocalMark[e];
179 : return 0;
180 : }
181 :
182 :
183 0 : void HangingNodeRefiner_Grid::
184 : attach_local_marks()
185 : {
186 : //todo: more elaborate check that the method is not executed multiple times per object
187 0 : if(!m_aaLocalMark.is_valid_face_accessor()){
188 0 : add_ref_mark_adjuster(LocalMarkAdjuster::create());
189 0 : m_pGrid->attach_to_faces_dv(m_aLocalMark, 0);
190 0 : m_pGrid->attach_to_volumes_dv(m_aLocalMark, 0);
191 0 : m_aaLocalMark.access(*m_pGrid, m_aLocalMark, false, false, true, true);
192 : }
193 0 : }
194 :
195 :
196 0 : void HangingNodeRefiner_Grid::
197 : num_marked_edges_local(std::vector<int>& numMarkedEdgesOut)
198 : {
199 0 : num_marked_elems<Edge>(numMarkedEdgesOut);
200 0 : }
201 :
202 0 : void HangingNodeRefiner_Grid::
203 : num_marked_faces_local(std::vector<int>& numMarkedFacesOut)
204 : {
205 0 : num_marked_elems<Face>(numMarkedFacesOut);
206 0 : }
207 :
208 0 : void HangingNodeRefiner_Grid::
209 : num_marked_volumes_local(std::vector<int>& numMarkedVolsOut)
210 : {
211 0 : num_marked_elems<Volume>(numMarkedVolsOut);
212 0 : }
213 :
214 :
215 : template <class TElem>
216 0 : void HangingNodeRefiner_Grid::
217 : num_marked_elems(std::vector<int>& numMarkedElemsOut)
218 : {
219 : numMarkedElemsOut.clear();
220 0 : numMarkedElemsOut.resize(1, 0);
221 0 : if(m_pGrid)
222 0 : numMarkedElemsOut[0] = get_refmark_selector().num<TElem>();
223 0 : }
224 :
225 0 : void HangingNodeRefiner_Grid::
226 : collect_objects_for_refine()
227 : {
228 0 : BaseClass::collect_objects_for_refine();
229 :
230 : Selector& sel = get_refmark_selector();
231 :
232 : for(ConstrainingEdgeIterator iter = sel.begin<ConstrainingEdge>();
233 0 : iter != sel.end<ConstrainingEdge>(); ++iter)
234 : {
235 : ConstrainingEdge* cge = *iter;
236 0 : if(cge->num_constrained_vertices() > 0)
237 0 : set_center_vertex(cge, cge->constrained_vertex(0));
238 : }
239 :
240 : for(ConstrainingTriangleIterator iter = sel.begin<ConstrainingTriangle>();
241 0 : iter != sel.end<ConstrainingTriangle>(); ++iter)
242 : {
243 : ConstrainingTriangle* cgt = *iter;
244 0 : if(cgt->num_constrained_vertices() > 0)
245 0 : set_center_vertex(cgt, cgt->constrained_vertex(0));
246 : }
247 :
248 : for(ConstrainingQuadrilateralIterator iter = sel.begin<ConstrainingQuadrilateral>();
249 0 : iter != sel.end<ConstrainingQuadrilateral>(); ++iter)
250 : {
251 : ConstrainingQuadrilateral* cgq = *iter;
252 0 : if(cgq->num_constrained_vertices() > 0)
253 0 : set_center_vertex(cgq, cgq->constrained_vertex(0));
254 : }
255 0 : }
256 :
257 : /* pre-refine
258 : // Resize the attachment containers
259 : {
260 : Selector& sel = get_refmark_selector();
261 :
262 : HNODE_PROFILE_BEGIN("HNode_ReserveAttachmentMemory");
263 :
264 : HNODE_PROFILE_BEGIN(HNODE_ReserveVrtData);
265 : mg.reserve<Vertex>(grid.num<Vertex>() +
266 : + sel.num<Vertex>() + sel.num<Edge>()
267 : + sel.num<Quadrilateral>() + sel.num<Hexahedron>());
268 : HNODE_PROFILE_END();
269 :
270 : HNODE_PROFILE_BEGIN(HNODE_ReserveEdgeData);
271 : mg.reserve<Edge>(mg.num<Edge>()
272 : + 2 * mg.num<Edge>() + 3 * mg.num<Triangle>()
273 : + 4 * mg.num<Quadrilateral>() + 3 * mg.num<Prism>()
274 : + mg.num<Tetrahedron>()
275 : + 4 * mg.num<Pyramid>() + 6 * mg.num<Hexahedron>());
276 : HNODE_PROFILE_END();
277 :
278 : HNODE_PROFILE_BEGIN(HNODE_ReserveFaceData);
279 : mg.reserve<Face>(mg.num<Face>()
280 : + 4 * mg.num<Face>(l) + 10 * mg.num<Prism>(l)
281 : + 8 * mg.num<Tetrahedron>(l)
282 : + 9 * mg.num<Pyramid>(l) + 12 * mg.num<Hexahedron>(l));
283 : HNODE_PROFILE_END();
284 :
285 : HNODE_PROFILE_BEGIN(HNODE_ReserveVolData);
286 : mg.reserve<Volume>(mg.num<Volume>()
287 : + 8 * mg.num<Tetrahedron>(l) + 8 * mg.num<Prism>(l)
288 : + 6 * mg.num<Pyramid>(l) + 8 * mg.num<Hexahedron>(l));
289 : HNODE_PROFILE_END();
290 :
291 : HNODE_PROFILE_END();
292 : }
293 : */
294 0 : void HangingNodeRefiner_Grid::
295 : post_refine()
296 : {
297 0 : if(!m_pGrid)
298 0 : throw(UGError("HangingNodeRefiner_Grid::post_refine: No grid assigned."));
299 :
300 : // erase unused elements
301 : UG_DLOG(LIB_GRID, 1, " erasing elements.\n");
302 :
303 : Grid& grid = *m_pGrid;
304 : vector<Face*> vFaces;
305 : vector<Volume*> vVols;
306 :
307 : // erase faces that are no longer needed.
308 0 : if(grid.num_volumes() > 0)
309 : {
310 : FaceIterator iter = m_selMarkedElements.begin<Face>();
311 0 : while(iter != m_selMarkedElements.end<Face>())
312 : {
313 : Face* f = *iter;
314 : ++iter;
315 0 : CollectVolumes(vVols, grid, f);
316 0 : if(vVols.empty())
317 : {
318 : // erase
319 0 : grid.erase(f);
320 : }
321 : }
322 : }
323 :
324 : // erase edges that are no longer needed.
325 0 : if(grid.num_faces() > 0)
326 : {
327 : EdgeIterator iter = m_selMarkedElements.begin<Edge>();
328 0 : while(iter != m_selMarkedElements.end<Edge>())
329 : {
330 : Edge* e = *iter;
331 : ++iter;
332 0 : CollectFaces(vFaces, grid, e);
333 0 : if(vFaces.empty())
334 : {
335 : // erase
336 0 : grid.erase(e);
337 : }
338 : }
339 : }
340 0 : }
341 :
342 0 : void HangingNodeRefiner_Grid::
343 : process_constraining_edge(ConstrainingEdge* e)
344 : {
345 : // call original implementation
346 0 : BaseClass::process_constraining_edge(e);
347 :
348 : // if there are no faces, the edge can be erased
349 0 : if(m_pGrid->num_faces() == 0)
350 0 : m_pGrid->erase(e);
351 0 : }
352 :
353 0 : void HangingNodeRefiner_Grid::
354 : refine_edge_with_normal_vertex(Edge* e, Vertex** newCornerVrts)
355 : {
356 : // call original implementation
357 0 : BaseClass::refine_edge_with_normal_vertex(e, newCornerVrts);
358 :
359 : // if there are no faces, the edge can be erased
360 0 : if(m_pGrid->num_faces() == 0)
361 0 : m_pGrid->erase(e);
362 0 : }
363 :
364 0 : void HangingNodeRefiner_Grid::
365 : refine_face_with_normal_vertex(Face* f, Vertex** newCornerVrts)
366 : {
367 : // call original implementation
368 0 : BaseClass::refine_face_with_normal_vertex(f, newCornerVrts);
369 :
370 : // if there are no volumes, the face can be erased
371 0 : if(m_pGrid->num_volumes() == 0)
372 0 : m_pGrid->erase(f);
373 0 : }
374 :
375 0 : void HangingNodeRefiner_Grid::
376 : process_constraining_face(ConstrainingFace* f)
377 : {
378 : // call original implementation
379 0 : BaseClass::process_constraining_face(f);
380 :
381 : // if there are no volumes, the face can be erased
382 0 : if(m_pGrid->num_volumes() == 0)
383 0 : m_pGrid->erase(f);
384 0 : }
385 :
386 0 : void HangingNodeRefiner_Grid::
387 : refine_volume_with_normal_vertex(Volume* v, Vertex** newCornerVrts)
388 : {
389 : // call original implementation
390 0 : BaseClass::refine_volume_with_normal_vertex(v, newCornerVrts);
391 :
392 : // erase the volume
393 0 : m_pGrid->erase(v);
394 0 : }
395 :
396 0 : Vertex* HangingNodeRefiner_Grid::
397 : get_center_vertex(Edge* e)
398 : {
399 0 : return m_aaVertexEDGE[e];
400 : }
401 :
402 :
403 0 : void HangingNodeRefiner_Grid::
404 : set_center_vertex(Edge* e, Vertex* v)
405 : {
406 0 : m_aaVertexEDGE[e] = v;
407 0 : }
408 :
409 :
410 0 : Vertex* HangingNodeRefiner_Grid::
411 : get_center_vertex(Face* f)
412 : {
413 0 : return m_aaVertexFACE[f];
414 : }
415 :
416 :
417 0 : void HangingNodeRefiner_Grid::
418 : set_center_vertex(Face* f, Vertex* v)
419 : {
420 0 : m_aaVertexFACE[f] = v;
421 0 : }
422 :
423 : }// end of namespace
|