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 "refiner_interface.h"
34 : #include "lib_grid/lib_grid_messages.h"
35 : #include "common/catch_std.h"
36 :
37 : // FOR DEBUGGING ONLY:
38 : #include "lib_grid/tools/periodic_boundary_manager.h"
39 :
40 : #ifdef UG_PARALLEL
41 : #include "pcl/pcl_process_communicator.h"
42 : #include "pcl/pcl_util.h"
43 : #endif
44 :
45 : namespace ug{
46 :
47 0 : bool IRefiner::mark(GridObject* o, RefinementMark refMark)
48 : {
49 0 : switch(o->base_object_id()){
50 0 : case VERTEX: return mark(static_cast<Vertex*>(o), refMark);
51 0 : case EDGE: return mark(static_cast<Edge*>(o), refMark);
52 0 : case FACE: return mark(static_cast<Face*>(o), refMark);
53 0 : case VOLUME: return mark(static_cast<Volume*>(o), refMark);
54 : }
55 : return false;
56 : }
57 :
58 0 : RefinementMark IRefiner::get_mark(GridObject* o) const
59 : {
60 0 : switch(o->base_object_id()){
61 0 : case VERTEX: return get_mark(static_cast<Vertex*>(o));
62 0 : case EDGE: return get_mark(static_cast<Edge*>(o));
63 0 : case FACE: return get_mark(static_cast<Face*>(o));
64 0 : case VOLUME: return get_mark(static_cast<Volume*>(o));
65 : }
66 : return RM_NONE;
67 : }
68 :
69 0 : void IRefiner::adaption_begins()
70 : {
71 0 : if(!m_messageHub.valid()){
72 0 : UG_THROW("A message-hub has to be assigned to IRefiner before adaption_begins may be called. "
73 : "Make sure that you assigned a grid to the refiner you're using.");
74 : }
75 :
76 : // we'll schedule an adaption-begins message
77 0 : if(adaptivity_supported())
78 0 : m_messageHub->post_message(GridMessage_Adaption(GMAT_HNODE_ADAPTION_BEGINS));
79 : else
80 0 : m_messageHub->post_message(GridMessage_Adaption(GMAT_GLOBAL_ADAPTION_BEGINS));
81 :
82 0 : m_adaptionIsActive = true;
83 0 : }
84 :
85 0 : void IRefiner::adaption_ends()
86 : {
87 0 : if(!m_messageHub.valid()){
88 0 : UG_THROW("A message-hub has to be assigned to IRefiner before adaption_ends may be called. "
89 : "Make sure that you assigned a grid to the refiner you're using.");
90 : }
91 :
92 0 : if(adaptivity_supported())
93 0 : m_messageHub->post_message(GridMessage_Adaption(GMAT_HNODE_ADAPTION_ENDS));
94 : else
95 0 : m_messageHub->post_message(GridMessage_Adaption(GMAT_GLOBAL_ADAPTION_ENDS));
96 :
97 0 : m_adaptionIsActive = false;
98 0 : }
99 :
100 0 : void IRefiner::refine()
101 : {
102 : #ifdef UG_PARALLEL
103 : PCL_DEBUG_BARRIER_ALL();
104 : #endif
105 : PROFILE_BEGIN_GROUP(IRefiner_refine, "grid");
106 : try
107 : {
108 0 : if(m_projector.invalid() && grid()){
109 0 : Grid& g = *grid();
110 0 : if(g.has_vertex_attachment(aPosition)){
111 0 : m_projector = make_sp(new RefinementProjector(MakeGeometry3d(g, aPosition)));
112 : }
113 0 : else if(g.has_vertex_attachment(aPosition2)){
114 0 : m_projector = make_sp(new RefinementProjector(MakeGeometry3d(g, aPosition2)));
115 : }
116 0 : else if(g.has_vertex_attachment(aPosition1)){
117 0 : m_projector = make_sp(new RefinementProjector(MakeGeometry3d(g, aPosition1)));
118 : }
119 : }
120 :
121 0 : if(!m_messageHub.valid()){
122 0 : UG_THROW("A message-hub has to be assigned to IRefiner before refine may be called. "
123 : "Make sure that you assigned a grid to the refiner you're using.");
124 : }
125 :
126 : // we'll schedule an adaption-begins message, if adaption is not yet enabled.
127 : bool locallyActivatedAdaption = false;
128 0 : if(!m_adaptionIsActive){
129 : locallyActivatedAdaption = true;
130 0 : adaption_begins();
131 : }
132 :
133 : // now post a message, which informs that refinement begins
134 : // if(adaptivity_supported())
135 : // m_messageHub->post_message(GridMessage_Adaption(GMAT_HNODE_REFINEMENT_BEGINS));
136 : // else
137 : // m_messageHub->post_message(GridMessage_Adaption(GMAT_GLOBAL_REFINEMENT_BEGINS));
138 :
139 : // now perform refinement
140 0 : perform_refinement();
141 :
142 : // post a message that refinement has been finished
143 : // if(adaptivity_supported())
144 : // m_messageHub->post_message(GridMessage_Adaption(GMAT_HNODE_REFINEMENT_ENDS));
145 : // else
146 : // m_messageHub->post_message(GridMessage_Adaption(GMAT_GLOBAL_REFINEMENT_ENDS));
147 :
148 : // and finally - if we posted an adaption-begins message, then we'll post
149 : // an adaption ends message, too.
150 0 : if(locallyActivatedAdaption){
151 0 : adaption_ends();
152 : }
153 : }
154 0 : CATCH_STD_EXCEPTIONS();
155 :
156 : #ifdef UG_PARALLEL
157 : PCL_DEBUG_BARRIER_ALL();
158 : #endif
159 0 : }
160 :
161 :
162 0 : bool IRefiner::coarsen()
163 : {
164 : #ifdef UG_PARALLEL
165 : PCL_DEBUG_BARRIER_ALL();
166 : #endif
167 : PROFILE_BEGIN_GROUP(IRefiner_coarsen, "grid");
168 : // if coarsen isn't supported, we'll leave right away
169 0 : if(!coarsening_supported())
170 : return false;
171 :
172 0 : if(!m_messageHub.valid()){
173 0 : UG_THROW("A message-hub has to be assigned to IRefiner before coarsen may be called. "
174 : "Make sure that you assigned a grid to the refiner you're using.");
175 : }
176 :
177 : // we'll schedule an adaption-begins message, if adaption is not yet enabled.
178 : bool locallyActivatedAdaption = false;
179 0 : if(!m_adaptionIsActive){
180 : locallyActivatedAdaption = true;
181 0 : adaption_begins();
182 : }
183 :
184 : // now post a message, which informs that coarsening begins
185 : // if(adaptivity_supported())
186 : // m_messageHub->post_message(GridMessage_Adaption(GMAT_HNODE_COARSENING_BEGINS));
187 : // else
188 : // m_messageHub->post_message(GridMessage_Adaption(GMAT_GLOBAL_COARSENING_BEGINS));
189 :
190 : // now perform coarsening
191 0 : bool retVal = perform_coarsening();
192 :
193 : // post a message that coarsening has been finished
194 : // if(adaptivity_supported())
195 : // m_messageHub->post_message(GridMessage_Adaption(GMAT_HNODE_COARSENING_ENDS));
196 : // else
197 : // m_messageHub->post_message(GridMessage_Adaption(GMAT_GLOBAL_COARSENING_ENDS));
198 :
199 : // and finally - if we posted an adaption-begins message, then we'll post
200 : // an adaption ends message, too.
201 0 : if(locallyActivatedAdaption)
202 0 : adaption_ends();
203 :
204 : // done
205 : #ifdef UG_PARALLEL
206 : PCL_DEBUG_BARRIER_ALL();
207 : #endif
208 : return retVal;
209 : }
210 :
211 :
212 0 : void IRefiner::set_message_hub(SPMessageHub msgHub)
213 : {
214 0 : m_messageHub = msgHub;
215 0 : }
216 :
217 0 : void IRefiner::set_adjusted_marks_debug_filename(const char* filename)
218 : {
219 0 : if(!filename)
220 0 : m_adjustedMarksDebugFilename = "";
221 : else
222 0 : m_adjustedMarksDebugFilename = filename;
223 0 : }
224 :
225 :
226 0 : int IRefiner::
227 : get_local_edge_mark(Face* f, Edge* e) const
228 : {
229 0 : const int edgeInd = GetEdgeIndex(f, e);
230 0 : UG_COND_THROW(edgeInd == -1, "Given edge is not an edge of the given face.");
231 :
232 0 : if(marked_local(f)){
233 0 : const int faceLocalMark = get_local_mark(f);
234 0 : return (faceLocalMark >> edgeInd) & 1;
235 : }
236 0 : else if(marked_full(f)){
237 : return 1;
238 : }
239 0 : else if(marked_closure(f)){
240 :
241 0 : return static_cast<int>(marked_full(e));
242 : }
243 : return 0;
244 : }
245 :
246 0 : int IRefiner::
247 : get_local_edge_mark(Volume* vol, Edge* e) const
248 : {
249 0 : const int edgeInd = GetEdgeIndex(vol, e);
250 0 : UG_COND_THROW(edgeInd == -1, "Given edge is not an edge of the given volume.");
251 :
252 0 : if(marked_local(vol)){
253 0 : const int volLocalMark = get_local_mark(vol);
254 0 : return (volLocalMark >> edgeInd) & 1;
255 : }
256 0 : else if(marked_full(vol)){
257 : return 1;
258 : }
259 0 : else if(marked_closure(vol)){
260 0 : return static_cast<int>(marked_full(e));
261 : }
262 : return 0;
263 : }
264 :
265 0 : int IRefiner::
266 : get_local_face_mark(Volume* vol, Face* f) const
267 : {
268 0 : int sideInd = GetFaceIndex(vol, f);
269 0 : UG_COND_THROW(sideInd == -1, "Given face is not a side of the given volume.");
270 :
271 0 : if(marked_local(vol)){
272 0 : const int volLocalMark = get_local_mark(vol);
273 0 : const size_t numFaceVrts = f->num_vertices();
274 0 : Face::ConstVertexArray vrts = f->vertices();
275 :
276 : int vinds[MAX_FACE_VERTICES];
277 0 : for(size_t i = 0; i < numFaceVrts; ++i){
278 0 : vinds[i] = GetVertexIndex(vol, vrts[i]);
279 : }
280 :
281 : int sideMark = 0;
282 :
283 0 : for(size_t i = 0; i < numFaceVrts; ++i){
284 : const int edgeInd =
285 0 : vol->get_edge_index_from_vertices(
286 0 : vinds[i], vinds[(i+1)%numFaceVrts]);
287 :
288 0 : sideMark |= ((volLocalMark >> edgeInd) & 1) << i;
289 : }
290 :
291 : return sideMark;
292 : }
293 0 : else if(marked_full(vol)){
294 : int sideMark = 0;
295 0 : const size_t numFaceVrts = f->num_vertices();
296 0 : for(size_t i = 0; i < numFaceVrts; ++i)
297 0 : sideMark |= 1 << i;
298 0 : return sideMark;
299 : }
300 0 : else if(marked_closure(vol)){
301 : int sideMark = 0;
302 : const size_t numFaceEdges = f->num_edges();
303 0 : for(size_t iedge = 0; iedge < numFaceEdges; ++iedge){
304 0 : if(marked_full(const_cast<IRefiner*>(this)->grid()->get_edge(f, iedge)))
305 0 : sideMark |= 1 << iedge;
306 : }
307 :
308 0 : return sideMark;
309 : }
310 : return 0;
311 : }
312 :
313 :
314 0 : size_t IRefiner::num_marked_edges(std::vector<int>& numMarkedEdgesOut)
315 : {
316 : #ifdef UG_PARALLEL
317 : std::vector<int> numLocal;
318 : num_marked_edges_local(numLocal);
319 : pcl::ProcessCommunicator com;
320 : com.allreduce(numLocal, numMarkedEdgesOut, PCL_RO_SUM);
321 : #else
322 0 : num_marked_edges_local(numMarkedEdgesOut);
323 : #endif
324 :
325 : size_t total = 0;
326 0 : for(size_t i = 0; i < numMarkedEdgesOut.size(); ++i){
327 0 : total += numMarkedEdgesOut[i];
328 : }
329 0 : return total;
330 : }
331 :
332 0 : size_t IRefiner::num_marked_faces(std::vector<int>& numMarkedFacesOut)
333 : {
334 : #ifdef UG_PARALLEL
335 : std::vector<int> numLocal;
336 : num_marked_faces_local(numLocal);
337 : pcl::ProcessCommunicator com;
338 : com.allreduce(numLocal, numMarkedFacesOut, PCL_RO_SUM);
339 : #else
340 0 : num_marked_faces_local(numMarkedFacesOut);
341 : #endif
342 :
343 : size_t total = 0;
344 0 : for(size_t i = 0; i < numMarkedFacesOut.size(); ++i){
345 0 : total += numMarkedFacesOut[i];
346 : }
347 0 : return total;
348 : }
349 :
350 0 : size_t IRefiner::num_marked_volumes(std::vector<int>& numMarkedVolsOut)
351 : {
352 : #ifdef UG_PARALLEL
353 : std::vector<int> numLocal;
354 : num_marked_volumes_local(numLocal);
355 : pcl::ProcessCommunicator com;
356 : com.allreduce(numLocal, numMarkedVolsOut, PCL_RO_SUM);
357 : #else
358 0 : num_marked_volumes_local(numMarkedVolsOut);
359 : #endif
360 :
361 : size_t total = 0;
362 0 : for(size_t i = 0; i < numMarkedVolsOut.size(); ++i){
363 0 : total += numMarkedVolsOut[i];
364 : }
365 0 : return total;
366 : }
367 :
368 0 : size_t IRefiner::num_marked_elements(std::vector<int>& numMarkedElemsOut)
369 : {
370 0 : if(grid()){
371 0 : Grid& g = *grid();
372 :
373 : size_t numVolumes = g.num<Volume>();
374 : size_t numFaces = g.num<Face>();
375 : size_t numEdges = g.num<Edge>();
376 :
377 : #ifdef UG_PARALLEL
378 : pcl::ProcessCommunicator com;
379 : numVolumes = com.allreduce(numVolumes, PCL_RO_SUM);
380 : numFaces = com.allreduce(numFaces, PCL_RO_SUM);
381 : numEdges = com.allreduce(numEdges, PCL_RO_SUM);
382 : #endif
383 :
384 0 : if(numVolumes > 0)
385 0 : return num_marked_volumes(numMarkedElemsOut);
386 0 : else if(numFaces > 0)
387 0 : return num_marked_faces(numMarkedElemsOut);
388 0 : else if(numEdges > 0)
389 0 : return num_marked_edges(numMarkedElemsOut);
390 : else
391 : return 0;
392 : }
393 : return 0;
394 : }
395 :
396 : }// end of namespace
|