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 : #ifndef __H__UG__HANGING_NODE_REFINER_BASE__
34 : #define __H__UG__HANGING_NODE_REFINER_BASE__
35 :
36 : #include <queue>
37 : #include <vector>
38 : #include "lib_grid/lg_base.h"
39 : #include "refiner_interface.h"
40 : #include "ref_mark_adjuster_interface.h"
41 :
42 : namespace ug
43 : {
44 :
45 : /// \addtogroup lib_grid_algorithms_refinement
46 : /// @{
47 :
48 : /// Base class for a hanging-node refiner.
49 : /** A hanging node refiner allows to adaptively refine grid elements
50 : * by inserting hanging nodes at points where T-junctions would occur
51 : * (ug::HangingVertex).
52 : * If further refinement is performed, the refiner automatically
53 : * takes care to adjust the refined area, so that no more than
54 : * 1 hanging vertex resides on any edge.
55 : *
56 : * Each edge on which a hanging node lies is replaced by a
57 : * ug::ConstrainingEdge. Child-edges of a constraining edge have the
58 : * type ug::ConstrainedEdge.
59 : *
60 : * If volumes exist, the refiner may also create elements of type
61 : * ug::ConstrainingTriangle or ug::ConstrainingQuadrilateral, as well
62 : * as ug::ConstrainedTriangle and ug::ConstrainedQuadrilateral.
63 : *
64 : * Use the mark methods to mark elements which
65 : * shall be refined. A call to refine will then perform the refinement
66 : * and clear all marks.
67 : *
68 : * Please note: If you're using a hanging node refiner, you have to
69 : * be careful to not destroy the connections between hanging-vertices,
70 : * and constrained / constraining objects.
71 : *
72 : * Specializations of this class exist to support hanging node refinement
73 : * on flat and on hierarchical grids.
74 : *
75 : * Note that you may set a refinement callback, which will be
76 : * responsible to calculate new positions of newly created vertices.
77 : * By default a linear refinement callback is created for one of
78 : * the standard position attachments (ug::aPosition, ug::aPosition2,
79 : * ug::aPosition1 - whichever is present).
80 : *
81 : * This class can't be instantiated directly. Use one of its
82 : * specializations instead.
83 : *
84 : * For Developers: Note that HangingNodeRefinerBase stores flags together with
85 : * the refinement marks. Precisely the value 128 is used to flag whether an
86 : * element has to be refined using hanging-node-rules.
87 : *
88 : * \sa ug::HangingNodeRefiner_Grid, ug::HangingNodeRefiner_MultiGrid
89 : */
90 : template <class TSelector>
91 : class HangingNodeRefinerBase : public IRefiner, public GridObserver
92 : {
93 : public:
94 : using IRefiner::mark;
95 :
96 : typedef TSelector selector_t;
97 :
98 : /** additional mark to RefinementMarks. Used to flag whether an element
99 : * will be refined with constraining.*/
100 : enum HNodeRefMarks{
101 : HNRM_TO_NORMAL = 1 << 5,
102 : HNRM_TO_CONSTRAINED = 1 << 6,
103 : HNRM_TO_CONSTRAINING = 1 << 7,
104 : HNRM_MAX
105 : };
106 :
107 : public:
108 : HangingNodeRefinerBase(SPRefinementProjector projector = SPNULL);
109 : virtual ~HangingNodeRefinerBase();
110 :
111 : virtual void grid_to_be_destroyed(Grid* grid);
112 :
113 : /// enables or disables node-dependency-order-1.
114 : /** \{
115 : * If enabled, hanging nodes may only depend on non-hanging nodes.
116 : * An edge containing a hanging node thus will not have a hanging-node
117 : * as a corner vertex.
118 : *
119 : * Enabled by default.*/
120 : void enable_node_dependency_order_1(bool bEnable);
121 0 : bool node_dependency_order_1_enabled() {return m_nodeDependencyOrder1;}
122 : /** \} */
123 :
124 : /// Add a refmark adjuster, which will be called while marks are adjusted during refinement / coarsening
125 0 : void add_ref_mark_adjuster(SPIRefMarkAdjuster adjuster) {m_refMarkAdjusters.push_back(adjuster);}
126 :
127 :
128 : virtual void clear_marks();
129 :
130 : /// Marks a element for refinement.
131 : /** \{ */
132 : virtual bool mark(Vertex* v, RefinementMark refMark = RM_REFINE);
133 : virtual bool mark(Edge* e, RefinementMark refMark = RM_REFINE);
134 : virtual bool mark(Face* f, RefinementMark refMark = RM_REFINE);
135 : virtual bool mark(Volume* v, RefinementMark refMark = RM_REFINE);
136 : /** \} */
137 :
138 : /// Marks the neighborhood of the current selection.
139 : /** \sa ISelector::mark_neighborhood*/
140 : virtual void mark_neighborhood(
141 : size_t numIterations,
142 : RefinementMark refMark,
143 : bool sideNbrsOnly);
144 :
145 : /// Returns the mark of a given element.
146 : /** \{ */
147 : virtual RefinementMark get_mark(Vertex* v) const;
148 : virtual RefinementMark get_mark(Edge* e) const;
149 : virtual RefinementMark get_mark(Face* f) const;
150 : virtual RefinementMark get_mark(Volume* v) const;
151 : /** \} */
152 :
153 :
154 0 : inline bool marked_refine(Edge* elem) const
155 : {
156 : return (m_selMarkedElements.get_selection_status(elem)
157 0 : & RM_REFINE) != 0;
158 : }
159 :
160 : template <class TElem>
161 : inline bool marked_refine(TElem* elem) const
162 : {
163 : return (m_selMarkedElements.get_selection_status(elem)
164 : & (RM_CLOSURE | RM_LOCAL | RM_FULL)) != 0;
165 : }
166 :
167 : template <class TElem>
168 : inline bool marked_adaptive(TElem* elem) const
169 : {
170 : return (m_selMarkedElements.get_selection_status(elem)
171 : & (RM_CLOSURE | RM_LOCAL));
172 : }
173 :
174 : template <class TElem>
175 : inline bool marked_regular(TElem* elem) const
176 : {
177 : return marked_refine(elem) && (!(marked_adaptive(elem)));
178 : }
179 :
180 : template <class TElem>
181 : inline bool marked_coarsen(TElem* elem) const
182 : {
183 : return (m_selMarkedElements.get_selection_status(elem)
184 : & RM_COARSEN) == RM_COARSEN;
185 : }
186 :
187 :
188 :
189 : virtual bool save_marks_to_file(const char* filename);
190 :
191 : protected:
192 : typedef typename TSelector::template traits<Vertex>::iterator sel_vrt_iter;
193 : typedef typename TSelector::template traits<Edge>::iterator sel_edge_iter;
194 : typedef typename TSelector::template traits<Face>::iterator sel_face_iter;
195 : typedef typename TSelector::template traits<Volume>::iterator sel_vol_iter;
196 :
197 : /// performs refinement on the marked elements.
198 : /**
199 : * The grid's message hub is informed using a "GridAdaption" message,
200 : * passing an instance of GridMessage_Adapation, with values
201 : * GMAT_HNODE_REFINEMENT_BEGINS and GMAT_HNODE_REFINEMENT_ENDS.
202 : * See lib_grid/lib_grid_messages.h for more details.
203 : *
204 : * as defined in lib_grid/
205 : *
206 : * automatically extends the refinement to avoid multiple hanging nodes
207 : * on a single edge or face.
208 : *
209 : * refine calls several virtual methods, which allow to influence the
210 : * refinement process. Most notably the methods
211 : *
212 : * - collect_objects_for_refine
213 : * - pre_refine
214 : * - post_refine
215 : *
216 : * are called in the given order. During element refinement further
217 : * virtual methods are called, which perform the actual element refinement.
218 : */
219 : void perform_refinement();
220 :
221 :
222 : /// a callback that allows to deny refinement of special vertices
223 0 : virtual bool refinement_is_allowed(Vertex* elem) {return true;}
224 : /// a callback that allows to deny refinement of special edges
225 0 : virtual bool refinement_is_allowed(Edge* elem) {return true;}
226 : /// a callback that allows to deny refinement of special faces
227 0 : virtual bool refinement_is_allowed(Face* elem) {return true;}
228 : /// a callback that allows to deny refinement of special volumes
229 0 : virtual bool refinement_is_allowed(Volume* elem) {return true;}
230 :
231 : /// performs registration and deregistration at a grid.
232 : /** Sets a grid and performs registration at the given grid.
233 : * The associated selector is also initialised with the given grid.
234 : * It is cruical to call this method or everything will fail.
235 : *
236 : * call set_grid(NULL) to unregister the observer from a grid.
237 : *
238 : * Please note that this method is not declared virtual, since it
239 : * is called during construction and destruction.*/
240 : void set_grid(typename TSelector::grid_type* grid);
241 :
242 : /// marks unmarked elements that have to be refined due to marked neighbors.
243 : /**
244 : * all elements that have to be refined will be written to the passed queues.
245 : * Note that this will most likely be more elements than just the marked ones.
246 : *
247 : * This method is virtual to allow derivates to mark additional elements as required.
248 : * Normally a a derived class will first call the method of its this class and
249 : * the perform its own operations.
250 : */
251 : virtual void collect_objects_for_refine();
252 :
253 : /** after each iteration in collet_objects_for_refine, this method determines
254 : * whether the iteration shall be continued. Important for parallel refiners.
255 : * The default implementation simply returns the specified value. This is fine
256 : * for serial environments.*/
257 0 : virtual bool continue_collect_objects_for_refine(bool continueRequired)
258 0 : {return continueRequired;}
259 :
260 : /** This callback is called during execution of the refine() method after
261 : * collect_objects_for_refine has returned. It is responsible to mark
262 : * elements for hnode refinement. That means all elements on which a hanging
263 : * node or constrained children shall be created have to be marked using
264 : * mark_for_hnode_refinement during this method. The default implementation
265 : * performs this marking for all local elements.
266 : * Make sure to not mark any new elements for refinement during this method.*/
267 : virtual void assign_hnode_marks();
268 :
269 : /** called by refine after collect_objects_for_refine and before
270 : * actual refinement begins.*/
271 0 : virtual void pre_refine() {}
272 :
273 : /** called by refine after refinement is done.*/
274 0 : virtual void post_refine() {}
275 :
276 : ////////////////////////////////////////////////////////////////////////
277 : // refine methods
278 : /// called to refine the specified element.
279 : /** Refines the element. Corner vertices of the newly created element
280 : * can be specified through newCornerVrts. newCornerVrts = NULL (default)
281 : * means, that the corner vertices of the original element shall be taken.
282 : * \{ */
283 : virtual void process_constrained_vertex(ConstrainedVertex* cdv);
284 : virtual void process_constrained_edge(ConstrainedEdge* cde);
285 : virtual void process_constraining_edge(ConstrainingEdge* cge);
286 : virtual void refine_edge_with_normal_vertex(Edge* e,
287 : Vertex** newCornerVrts = NULL);
288 : virtual void refine_edge_with_hanging_vertex(Edge* e,
289 : Vertex** newCornerVrts = NULL);
290 :
291 : virtual void process_constrained_face(ConstrainedFace* cdf);
292 : virtual void process_constraining_face(ConstrainingFace* cgf);
293 : virtual void refine_face_with_normal_vertex(Face* f,
294 : Vertex** newCornerVrts = NULL);
295 : virtual void refine_face_with_hanging_vertex(Face* f,
296 : Vertex** newCornerVrts = NULL);
297 :
298 : virtual void refine_volume_with_normal_vertex(Volume* v,
299 : Vertex** newVolumeVrts = NULL);
300 : /** \} */
301 :
302 : ////////////////////////////////////////////////////////////////////////
303 : // helpers. Make sure that everything is initialized properly
304 : // before calling these methods.
305 : // you should use this methods instead of directly marking elements.
306 0 : inline bool is_marked(Vertex* v) {return m_selMarkedElements.is_selected(v);}
307 : //inline void mark(Vertex* v) {mark(v);}
308 :
309 0 : inline bool is_marked(Edge* e) {return m_selMarkedElements.is_selected(e);}
310 : //inline void mark(Edge* e) {mark(e);}
311 :
312 : /// Returns the vertex associated with the edge
313 : /** pure virtual method.
314 : * Has to return the center vertex which was set to the edge via
315 : * set_center_vertex. If no vertex was set, NULL has to be returned.*/
316 : virtual Vertex* get_center_vertex(Edge* e) = 0;
317 :
318 : /// Associates a vertex with the edge (pure virtual).
319 : virtual void set_center_vertex(Edge* e, Vertex* v) = 0;
320 :
321 0 : inline bool is_marked(Face* f) {return m_selMarkedElements.is_selected(f);}
322 : //inline void mark(Face* f) {mark(f);}
323 :
324 : /// Returns the vertex associated with the face
325 : /** pure virtual method.
326 : * Has to return the center vertex which was set to the face via
327 : * set_center_vertex. If no vertex was set, NULL has to be returned.*/
328 : virtual Vertex* get_center_vertex(Face* f) = 0;
329 :
330 : /// Associates a vertex with the face (pure virtual).
331 : virtual void set_center_vertex(Face* f, Vertex* v) = 0;
332 :
333 0 : inline bool is_marked(Volume* v) {return m_selMarkedElements.is_selected(v);}
334 : //inline void mark(Volume* v) {mark(v);}
335 :
336 :
337 : template <class TElem>
338 : inline bool marked_to_normal(TElem* elem) const {return (m_selMarkedElements.get_selection_status(elem) & HNRM_TO_NORMAL) == HNRM_TO_NORMAL;}
339 :
340 : template <class TElem>
341 : inline bool marked_to_constrained(TElem* elem) const {return (m_selMarkedElements.get_selection_status(elem) & HNRM_TO_CONSTRAINED) == HNRM_TO_CONSTRAINED;}
342 :
343 : template <class TElem>
344 : inline bool marked_to_constraining(TElem* elem) const {return (m_selMarkedElements.get_selection_status(elem) & HNRM_TO_CONSTRAINING) == HNRM_TO_CONSTRAINING;}
345 :
346 : template <class TElem>
347 : void add_hmark(TElem* elem, HNodeRefMarks mark);
348 :
349 : template <class TElem>
350 : void remove_hmark(TElem* elem, uint mark);
351 :
352 : /// removes coarsen marks from the selection
353 : /** Note that derived classes are not informed about those deselections!*/
354 : template <class TElem>
355 : bool remove_coarsen_marks();
356 :
357 : /// returns the selector which is internally used to mark elements.
358 : /** Be sure to use it carefully!*/
359 0 : TSelector& get_refmark_selector() {return m_selMarkedElements;}
360 :
361 0 : inline bool adjusting_ref_marks() const {return m_adjustingRefMarks;}
362 :
363 : private:
364 : /// private copy constructor to avoid copy construction
365 : HangingNodeRefinerBase(const HangingNodeRefinerBase&);
366 :
367 : protected:
368 : TSelector m_selMarkedElements;
369 : std::vector<SPIRefMarkAdjuster> m_refMarkAdjusters;
370 :
371 : private:
372 : Grid* m_pGrid;
373 : std::vector<Vertex*> m_newlyMarkedRefVrts;
374 : std::vector<Edge*> m_newlyMarkedRefEdges;
375 : std::vector<Face*> m_newlyMarkedRefFaces;
376 : std::vector<Volume*> m_newlyMarkedRefVols;
377 : //todo: Use the following vectors during coarsening...
378 : /*
379 : std::vector<Vertex*> m_newlyMarkedCoarseVrts;
380 : std::vector<Edge*> m_newlyMarkedCoarseEdges;
381 : std::vector<Face*> m_newlyMarkedCoarseFaces;
382 : std::vector<Volume*> m_newlyMarkedCoarseVols;
383 : */
384 : bool m_nodeDependencyOrder1;
385 : //bool m_automarkHigherDimensionalObjects; <-- unused
386 : bool m_adjustingRefMarks;///< true during collect_objects_for_refine
387 : };
388 :
389 : /// @} // end of add_to_group command
390 :
391 : }// end of namespace
392 :
393 : #endif
|