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__HANGIN_NODE_REFINER_MULTI_GRID__
34 : #define __H__UG__HANGIN_NODE_REFINER_MULTI_GRID__
35 :
36 : #include "hanging_node_refiner_base.h"
37 : #include "lib_grid/tools/selector_multi_grid.h"
38 :
39 : namespace ug
40 : {
41 :
42 : /// \addtogroup lib_grid_algorithms_refinement
43 : /// @{
44 :
45 : /// Specialization of ug::HangingNodeRefiner for ug::MultiGrid
46 : /** This class should be used, if hanging node refinement shall be
47 : * applied on a hierarchical grid (ug::MultiGrid).
48 : *
49 : * New elements will be constructed one level above their parent elements.
50 : *
51 : * HangingNodeRefiner_MultiGrid supports coarsening. Please note that coarsening
52 : * presumably has not yet reached its final implementation and behavior may
53 : * thus change in future revisions.
54 : * In the current implementation, refinement marks are removed during coarsening
55 : * and coarsening marks are removed during refinement. In order to use
56 : * coarsening and refinement on thus should first mark all elements which shall
57 : * be coarsened, perform coarsening, then mark all elements will shall be
58 : * refined and perform refinement (or vice versa).
59 : *
60 : * Take a look at ug::HangingNodeRefinerBase for a more in-depth documentation.
61 : *
62 : * \todo: Avoid the removal of refinement marks during coarsening and of
63 : * coarsening marks during refinement.
64 : *
65 : * \sa ug::HangingNodeRefinerBase, ug::HangingNodeRefiner_Grid
66 : */
67 : class HangingNodeRefiner_MultiGrid : public HangingNodeRefinerBase<MGSelector>
68 : {
69 : public:
70 : typedef HangingNodeRefinerBase<MGSelector> BaseClass;
71 : using BaseClass::mark;
72 :
73 : enum HNodeCoarsenMarks{
74 : HNCM_FIRST = HNRM_MAX + 1,
75 : HNCM_NO_NBRS,
76 : HNCM_NONE,
77 : HNCM_PARTIAL,
78 : HNCM_REPLACE,
79 : HNCM_ALL,
80 : HNCM_INVALID,
81 : HNCM_UNKNOWN
82 : };
83 :
84 : public:
85 : HangingNodeRefiner_MultiGrid(SPRefinementProjector projector = SPNULL);
86 : HangingNodeRefiner_MultiGrid(MultiGrid& mg,
87 : SPRefinementProjector projector = SPNULL);
88 :
89 : virtual ~HangingNodeRefiner_MultiGrid();
90 :
91 : virtual void grid_to_be_destroyed(Grid* grid);
92 :
93 : virtual void assign_grid(MultiGrid& mg);
94 0 : virtual Grid* get_associated_grid() {return m_pMG;}//depreciated
95 0 : virtual Grid* grid() {return m_pMG;}
96 0 : virtual MultiGrid* multi_grid() {return m_pMG;}
97 :
98 0 : virtual bool adaptivity_supported() const {return true;}
99 0 : virtual bool coarsening_supported() const {return true;}
100 :
101 : protected:
102 : /// returns the number of (globally) marked edges on this level of the hierarchy
103 : virtual void num_marked_edges_local(std::vector<int>& numMarkedEdgesOut);
104 : /// returns the number of (globally) marked faces on this level of the hierarchy
105 : virtual void num_marked_faces_local(std::vector<int>& numMarkedFacesOut);
106 : /// returns the number of (globally) marked volumes on this level of the hierarchy
107 : virtual void num_marked_volumes_local(std::vector<int>& numMarkedVolsOut);
108 :
109 : template <class TElem>
110 : void num_marked_elems(std::vector<int>& numMarkedElemsOut);
111 :
112 : /// performs coarsening on the elements marked with RM_COARSEN.
113 : /**
114 : * The grid's message hub is informed using a "GridAdaption" message,
115 : * passing an instance of GridMessage_Adapation, with values
116 : * GMAT_HNODE_COARSENING_BEGINS and GMAT_HNODE_COARSENING_ENDS.
117 : * See lib_grid/lib_grid_messages.h for more details.
118 : *
119 : * automatically adjusts the selection so that only valid coarsening operations
120 : * are executed. Not that refinement marks are removed in this process.
121 : *
122 : * During a coarsening step only elements from the surface layer are removed.
123 : * If not all children of a sub-surface element are marked, then the marks are ignored.
124 : *
125 : * Note that coarsen in contrary to refine is conservative. While refine
126 : * extends the selection to construct a valid grid, coarsen shrinks the
127 : * selection. On could think of implementing an alternative non conservative
128 : * coarsen approach. However, the conservative one is the one mostly used
129 : * in adaptive multigrid methods and was thus chosen here.
130 : *
131 : * coarsen returns false, if no elements have been coarsened, true if at
132 : * least one has been coarsened.
133 : */
134 : virtual bool perform_coarsening();
135 :
136 : void save_coarsen_marks_to_file(ISelector& sel, const char* filename);
137 : void debug_save(ISelector& sel, const char* filename);
138 :
139 : /// a callback that allows to deny refinement of special vertices
140 : virtual bool refinement_is_allowed(Vertex* elem);
141 : /// a callback that allows to deny refinement of special edges
142 : virtual bool refinement_is_allowed(Edge* elem);
143 : /// a callback that allows to deny refinement of special faces
144 : virtual bool refinement_is_allowed(Face* elem);
145 : /// a callback that allows to deny refinement of special volumes
146 : virtual bool refinement_is_allowed(Volume* elem);
147 :
148 : /// performs registration and deregistration at a grid.
149 : /** Initializes all grid related variables.
150 : * call set_grid(NULL) to unregister the observer from a grid.
151 : *
152 : * Please note that though the base grid features a set_grid method,
153 : * it is not declared virtual. This is because we want to call it
154 : * during construction and destruction.*/
155 : void set_grid(MultiGrid* mg);
156 :
157 : virtual void assign_hnode_marks();
158 :
159 : /// creates required vertices in higher levels.
160 : virtual void pre_refine();
161 :
162 : /// called before elements are removed in coarsening
163 : /** Default implementation is emtpy */
164 0 : virtual void pre_coarsen() {};
165 :
166 : /// called after elements have been removed in coarsening
167 : /** Default implementation is emtpy */
168 0 : virtual void post_coarsen() {};
169 :
170 :
171 : /** Calls the base implementation and passes the mg-child vertices as
172 : * newCornerVrts. If newCornerVrts were passed to this method, they
173 : * are ignored.
174 : * \{*/
175 : /// calls base implementation and replaces cge with a normal edge.
176 : virtual void process_constraining_edge(ConstrainingEdge* cge);
177 :
178 : virtual void refine_edge_with_normal_vertex(Edge* e,
179 : Vertex** newCornerVrts = NULL);
180 : virtual void refine_edge_with_hanging_vertex(Edge* e,
181 : Vertex** newCornerVrts = NULL);
182 :
183 : virtual void refine_face_with_normal_vertex(Face* f,
184 : Vertex** newCornerVrts = NULL);
185 : virtual void refine_face_with_hanging_vertex(Face* f,
186 : Vertex** newCornerVrts = NULL);
187 :
188 : virtual void refine_volume_with_normal_vertex(Volume* v,
189 : Vertex** newVolumeVrts = NULL);
190 : /* \} */
191 :
192 : /// Returns the vertex associated with the edge
193 : virtual Vertex* get_center_vertex(Edge* e);
194 :
195 : /// Associates a vertex with the edge.
196 : virtual void set_center_vertex(Edge* e, Vertex* v);
197 :
198 : /// Returns the vertex associated with the face
199 : virtual Vertex* get_center_vertex(Face* f);
200 :
201 : /// Associates a vertex with the face.
202 : virtual void set_center_vertex(Face* f, Vertex* v);
203 :
204 :
205 : /// collects corner vertices and fills them into the associated vector
206 : /** The size of cornersOut is automatically adjusted.
207 : * The i-th element of corners out will contain the child vertex of the
208 : * i-th vertex of elem.*/
209 : template <class TElem>
210 0 : void collect_child_corners(std::vector<Vertex*>& cornersOut, TElem* elem)
211 : {
212 0 : cornersOut.resize(elem->num_vertices());
213 0 : for(size_t i = 0; i < elem->num_vertices(); ++i){
214 : //UG_ASSERT(m_pMG->get_child_vertex(elem->vertex(i)), "A child vertex has to exists!");
215 0 : cornersOut[i] = m_pMG->get_child_vertex(elem->vertex(i));
216 : }
217 0 : }
218 :
219 : /// Makes sure that only surface elements are marked and that only coarsen marks are used.
220 : /** calls the overloaded template implementation for the four base element types.
221 : * this method is called prior to restrict_selection_to_coarsen_families.*/
222 : virtual void restrict_selection_to_surface_coarsen_elements();
223 :
224 : /// Deselects all elements which have an unselected sibling.
225 : /** Siblings are elements who share the same parent.
226 : * Calls the overloaded template implementation for the four base element types.
227 : * this method is called after to restrict_selection_to_surface_coarsen_elements.*/
228 : virtual void restrict_selection_to_coarsen_families();
229 :
230 : /// Deselects all non-surface elements and all elements not marked with RM_COARSEN
231 : template <class TElem>
232 : void restrict_selection_to_surface_coarsen_elements();
233 :
234 : /// Only complete families (all siblings are selected) may be coarsened.
235 : /** When calling this method, make sure that only surface elements are
236 : * marked/selected and that only the mark RM_COARSEN is used.*/
237 : template <class TElem>
238 : void restrict_selection_to_coarsen_families();
239 :
240 : /// adjusts the selection marks to those specified in HNodeCoarsenMarks.
241 : /** This method does not alter the selection itself, it only alters the
242 : * selection-mark, associated with each selected element. It neither
243 : * selects nor deselects any elements.
244 : * It iterates over all selected elements of the given type and assigns one
245 : * of the marks, depending on how many associated elements of the next higher
246 : * dimension are selected.
247 : * Note that this method should only be called for vertices, edges and faces.
248 : * It does not make sense to call it for volumes.*/
249 : // template <class TElem>
250 : // void classify_selection();
251 :
252 : /// Applies marks like RM_COARSEN_CONSTRAINING or RM_COARSEN_UNCONSTRAIN
253 : /** This method should first be called for Face, then for Edge, then for
254 : * Vertex.*/
255 : //template <class TElem>
256 : //void adjust_coarsen_marks_on_side_elements();
257 :
258 : ///deselect coarsen families, which are adjacent to unselected constraining elements
259 : /** If at least one family was deselected, this method returns true.*/
260 : // template <class TElem>
261 : // bool deselect_invalid_coarsen_families();
262 : //
263 : // template <class TElem>
264 : // void deselect_isolated_sides();
265 : //
266 : // template <class TElem>
267 : // void deselect_uncoarsenable_parents();
268 :
269 : /// called by the coarsen method in order to adjust the selection to valid elements.
270 : /** This method is responsible to mark all elements that shall be coarsened.
271 : * Only sub-surface elements may be coarsened. If a sub-surface element has
272 : * a side, which is not a sub-surface element, then the element may not be
273 : * coarsened.
274 : * If scheduleCoarseningBeginsMessage is set to true, the method will schedule
275 : * a GridMessage_Adaption message which indicates that coarsening begins.*/
276 : virtual void collect_objects_for_coarsen(bool scheduleCoarseningBeginsMessage = false);
277 :
278 :
279 : ////////////////////////////////////////
280 : // Callbacks for PARALLELIZATION
281 :
282 : /// called to check, whether another iteration of collect_objects_for_coarsen has to be performed.
283 : /** This method is especially useful if coarsening shall be applied in a
284 : * parallel environment. Each process calls this method and basses a boolean,
285 : * which indicates if it requires the continuation of collect_objects_for_coarsen.
286 : * If one process does require continuation, then all processes have to continue.
287 : * The default implementation simply returns the local status.*/
288 : // virtual bool continue_collect_objects_for_coarsen(bool continueRequired)
289 : // {return continueRequired;}
290 :
291 : /// called during collect_objects_for_coarsen when coarsen-marks shall be distributed
292 : /** This method is especially useful if coarsening shall be applied in a
293 : * parallel environment. A derived class can implement this method to schedule
294 : * communication. The default implementation does nothing.
295 : * \{ */
296 : // virtual void broadcast_vertex_coarsen_marks() {}
297 : // virtual void broadcast_edge_coarsen_marks() {}
298 : // virtual void broadcast_face_coarsen_marks() {}
299 : /** \} */
300 :
301 : /// allows to check whether a distributed grid contains edges
302 : /** The default implementation returns whether the local grid contains edges.*/
303 0 : virtual bool contains_edges() {return m_pMG->num<Edge>() > 0;}
304 :
305 : /// allows to check whether a distributed grid contains faces
306 : /** The default implementation returns whether the local grid contains faces.*/
307 0 : virtual bool contains_faces() {return m_pMG->num<Face>() > 0;}
308 :
309 : /// allows to check whether a distributed grid contains volumes
310 : /** The default implementation returns whether the local grid contains volumes.*/
311 0 : virtual bool contains_volumes() {return m_pMG->num<Volume>() > 0;}
312 :
313 : /** This callback is called during execution of the coarsen() method after
314 : * collect_objects_for_coarsen is done. It is responsible to mark
315 : * elements for hnode coarsening. That means all elements on which a hanging
316 : * node or constrained children shall be created have to be marked using
317 : * mark_for_hnode_refinement during this method. The default implementation
318 : * performs this marking for all local elements.*/
319 : //virtual void assign_hnode_coarsen_marks();
320 :
321 0 : virtual void broadcast_marks_horizontally(bool vertices, bool edges, bool faces,
322 0 : bool allowDeselection = false) {}
323 0 : virtual void broadcast_marks_vertically(bool vertices, bool edges,
324 : bool faces, bool volumes,
325 0 : bool allowDeselection = false) {}
326 :
327 0 : virtual void copy_marks_to_vmasters(bool vertices, bool edges,
328 0 : bool faces, bool volumes) {}
329 :
330 0 : virtual void copy_marks_to_vslaves(bool vertices, bool edges,
331 0 : bool faces, bool volumes) {}
332 :
333 0 : virtual bool one_proc_true(bool localProcTrue) {return localProcTrue;}
334 :
335 : private:
336 : MultiGrid* m_pMG;
337 : };
338 :
339 : /// @} // end of add_to_group command
340 :
341 : }// end of namespace
342 :
343 : #endif
|