Line data Source code
1 : /*
2 : * Copyright (c) 2012-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 "./std_hnode_adjuster.h"
34 : #include "lib_grid/tools/periodic_boundary_manager.h"
35 : #include "lib_grid/algorithms/debug_util.h"
36 :
37 : namespace ug{
38 :
39 : // marks geometric object e for refinement if it is periodic
40 : template <class TElem>
41 0 : static void mark_if_periodic(IRefiner& ref, TElem* e) {
42 0 : if(!ref.grid())
43 : return;
44 0 : if(!ref.grid()->has_periodic_boundaries())
45 : return;
46 :
47 0 : PeriodicBoundaryManager& pbm = *ref.grid()->periodic_boundary_manager();
48 :
49 : // ensure element is periodic
50 0 : if(!pbm.is_periodic(e))
51 : return;
52 :
53 0 : RefinementMark refMark = ref.get_mark(e);
54 0 : if(pbm.is_master(e))
55 : {
56 : typedef typename PeriodicBoundaryManager::Group<TElem>::SlaveContainer SlaveContainer;
57 : typedef typename PeriodicBoundaryManager::Group<TElem>::SlaveIterator SlaveIterator;
58 0 : SlaveContainer& slaves = *pbm.slaves(e);
59 0 : for (SlaveIterator iter = slaves.begin(); iter != slaves.end(); ++iter)
60 0 : ref.mark(*iter, refMark);
61 : }
62 : else { // is slave
63 0 : ref.mark(pbm.master(e), refMark);
64 : }
65 : }
66 :
67 0 : void StdHNodeAdjuster::
68 : ref_marks_changed(IRefiner& ref,
69 : const std::vector<Vertex*>& vrts,
70 : const std::vector<Edge*>& edges,
71 : const std::vector<Face*>& faces,
72 : const std::vector<Volume*>& vols)
73 : {
74 0 : if(!ref.grid())
75 0 : return;
76 0 : Grid& grid = *ref.grid();
77 :
78 : Grid::edge_traits::secure_container assEdges;
79 : Grid::face_traits::secure_container assFaces;
80 : Grid::volume_traits::secure_container assVols;
81 :
82 : ////////////////////////////////
83 : // VERTICES
84 0 : if(node_dependency_order_1_enabled()){
85 : // make sure that a hanging node is never constrained by an element which
86 : // is has constrained vertices as corners
87 0 : for(size_t i_vrt = 0; i_vrt < vrts.size(); ++i_vrt){
88 0 : Vertex* vrt = vrts[i_vrt];
89 0 : if(!vrt->is_constrained())
90 0 : continue;
91 0 : ConstrainedVertex* hv = dynamic_cast<ConstrainedVertex*>(vrt);
92 0 : if(!hv)
93 0 : continue;
94 :
95 : // make sure that all parents are marked
96 : GridObject* co = hv->get_constraining_object();
97 0 : if(co){
98 0 : if(Edge* e = dynamic_cast<Edge*>(co)){
99 0 : ref.mark(e);
100 : }
101 0 : else if(Face* f = dynamic_cast<Face*>(co)){
102 0 : ref.mark(f);
103 : }
104 : }
105 : }
106 : }
107 :
108 : ////////////////////////////////
109 : // EDGES
110 0 : for(size_t i_edge = 0; i_edge < edges.size(); ++i_edge){
111 0 : Edge* e = edges[i_edge];
112 :
113 0 : if(ref.get_mark(e) != RM_REFINE)
114 0 : continue;
115 :
116 : // check whether hangingNodeOrder1 is enabled. If so, we have to check
117 : // for associated hanging vertices and push them to qHVrts.
118 0 : if(node_dependency_order_1_enabled()){
119 0 : for(size_t i = 0; i < 2; ++i){
120 0 : if(e->vertex(i)->is_constrained()){
121 0 : Vertex* v = e->vertex(i);
122 0 : ref.mark(v);
123 : }
124 : }
125 : }
126 :
127 : // depending on the type of the edge, we have to perform different operations
128 0 : if(ConstrainedEdge* cde = dynamic_cast<ConstrainedEdge*>(e))
129 : {
130 : // the edge is a constrained edge. Make sure that its constraining edge
131 : // or face will be refined.
132 0 : if(ConstrainingEdge* cge = dynamic_cast<ConstrainingEdge*>(
133 : cde->get_constraining_object()))
134 : {
135 0 : ref.mark(cge);
136 : }
137 0 : else if(ConstrainingFace* cgf = dynamic_cast<ConstrainingFace*>(
138 : cde->get_constraining_object()))
139 : {
140 0 : ref.mark(cgf);
141 : }
142 : else{
143 : UG_ASSERT(grid.is_parallel(),
144 : "Constrained edge doesn't have a constraining edge. In "
145 : "a serial environment this should always be the case!"
146 : << " At: " << GetGridObjectCenter(grid, e));
147 : }
148 : }
149 0 : else if(ConstrainingEdge* cge = dynamic_cast<ConstrainingEdge*>(e))
150 : {
151 : // associated faces and volumes have to be marked
152 0 : if(grid.num_faces() > 0){
153 : grid.associated_elements(assFaces, cge);
154 0 : for(size_t i = 0; i < assFaces.size(); ++i){
155 0 : if (!(ref.get_mark(assFaces[i]) & RM_ANISOTROPIC)) // do not mark RM_REFINE if already marked anisotropic
156 0 : ref.mark(assFaces[i]);
157 : }
158 : }
159 :
160 0 : if(grid.num_volumes() > 0){
161 : grid.associated_elements(assVols, cge);
162 0 : for(size_t i = 0; i < assVols.size(); ++i){
163 0 : if (!(ref.get_mark(assVols[i]) & RM_ANISOTROPIC)) // do not mark RM_REFINE if already marked anisotropic
164 0 : ref.mark(assVols[i]);
165 : }
166 : }
167 : }
168 : //NOTE: The check below was intended to replace the one above to reduce element refinement.
169 : // However, since constrained edges may be marked after this check has
170 : // been performed for a constraining edge, at least in parallel environments,
171 : // this implementation leads to problems (segfaults!)
172 : // else if(ConstrainingEdge* cge = dynamic_cast<ConstrainingEdge*>(e))
173 : // {
174 : // // if one of the constrained objects is marked, then all associated faces
175 : // // and volumes have to be marked, too
176 : // const size_t nce = cge->num_constrained_edges();
177 : // bool oneIsMarked = false;
178 : // for(size_t i = 0; i < nce; ++i){
179 : // const RefinementMark rm = ref.get_mark(cge->constrained_edge(i));
180 : // if(rm & RM_REFINE){
181 : // oneIsMarked = true;
182 : // break;
183 : // }
184 : // }
185 :
186 : // if(oneIsMarked){
187 : // if(grid.num_faces() > 0){
188 : // grid.associated_elements(assFaces, cge);
189 : // for(size_t i = 0; i < assFaces.size(); ++i){
190 : // if (!(ref.get_mark(assFaces[i]) & RM_ANISOTROPIC)) // do not mark RM_REFINE if already marked anisotropic
191 : // ref.mark(assFaces[i]);
192 : // }
193 : // }
194 :
195 : // if(grid.num_volumes() > 0){
196 : // grid.associated_elements(assVols, cge);
197 : // for(size_t i = 0; i < assVols.size(); ++i){
198 : // if (!(ref.get_mark(assVols[i]) & RM_ANISOTROPIC)) // do not mark RM_REFINE if already marked anisotropic
199 : // ref.mark(assVols[i]);
200 : // }
201 : // }
202 : // }
203 : // }
204 : }
205 :
206 : ////////////////////////////////
207 : // FACES
208 0 : for(size_t i_face = 0; i_face < faces.size(); ++i_face){
209 0 : Face* f = faces[i_face];
210 0 : RefinementMark refMark = ref.get_mark(f);
211 : // check whether hangingNodeOrder1 is enabled. If so, we have to check
212 : // for associated hanging vertices and push them to qHVrts.
213 0 : if(node_dependency_order_1_enabled()){
214 0 : for(size_t i = 0; i < f->num_vertices(); ++i){
215 0 : if(f->vertex(i)->is_constrained())
216 0 : ref.mark(f->vertex(i));
217 : }
218 : }
219 :
220 : // we have to make sure that associated edges are marked.
221 0 : if(refMark != RM_LOCAL){
222 : grid.associated_elements(assEdges, f);
223 0 : for(size_t i = 0; i < assEdges.size(); ++i){
224 0 : if(refMark > ref.get_mark(assEdges[i]))
225 0 : ref.mark(assEdges[i], refMark);
226 : }
227 : }
228 :
229 : // constrained and constraining faces require special treatment
230 0 : if(ConstrainedFace* cdf = dynamic_cast<ConstrainedFace*>(f)){
231 : // make sure that its constraining face will be refined
232 0 : if(ConstrainingFace* cgf = dynamic_cast<ConstrainingFace*>(
233 : cdf->get_constraining_object()))
234 : {
235 0 : ref.mark(cgf);
236 : }
237 : else{
238 : UG_ASSERT(grid.is_parallel(),
239 : "Constrained face doesn't have a constraining face. In "
240 : "a serial environment this should always be the case!"
241 : << " At: " << GetGridObjectCenter(grid, f));
242 : }
243 : }
244 0 : else if(ConstrainingFace* cgf = dynamic_cast<ConstrainingFace*>(f)){
245 : // associated volumes have to be marked
246 0 : if(grid.num_volumes() > 0){
247 : grid.associated_elements(assVols, cgf);
248 0 : for(size_t i = 0; i < assVols.size(); ++i){
249 : //todo: also check whether the local mark matches
250 0 : if (!(ref.get_mark(assVols[i]) & RM_ANISOTROPIC)) // do not mark RM_REFINE if already marked anisotropic
251 0 : ref.mark(assVols[i]);
252 : }
253 : }
254 : }
255 : }
256 :
257 : ////////////////////////////////
258 : // VOLUMES
259 0 : for(size_t i_vol = 0; i_vol < vols.size(); ++i_vol){
260 0 : Volume* v = vols[i_vol];
261 0 : RefinementMark refMark = ref.get_mark(v);
262 : // we have to make sure that all associated edges and faces are marked.
263 0 : if(refMark != RM_LOCAL){
264 : grid.associated_elements(assEdges, v);
265 0 : for(size_t i = 0; i < assEdges.size(); ++i){
266 0 : if(refMark > ref.get_mark(assEdges[i]))
267 0 : ref.mark(assEdges[i], refMark);
268 : }
269 :
270 : grid.associated_elements(assFaces, v);
271 0 : for(size_t i = 0; i < assFaces.size(); ++i){
272 0 : if(refMark > ref.get_mark(assFaces[i]))
273 0 : ref.mark(assFaces[i], refMark);
274 : }
275 : }
276 : }
277 :
278 : ////////////////////////////////
279 : // Periodic boundaries
280 0 : if(grid.has_periodic_boundaries()){
281 0 : for(size_t i_vrt = 0; i_vrt < vrts.size(); ++i_vrt)
282 0 : mark_if_periodic(ref, vrts[i_vrt]);
283 :
284 0 : for(size_t i_edge = 0; i_edge < edges.size(); ++i_edge)
285 0 : mark_if_periodic(ref, edges[i_edge]);
286 :
287 0 : for(size_t i_face = 0; i_face < faces.size(); ++i_face)
288 0 : mark_if_periodic(ref, faces[i_face]);
289 :
290 : // omit volumes, as these are not meant to be periodic
291 : }
292 : }
293 : }// end of namespace
|