Line data Source code
1 : /*
2 : * Copyright (c) 2010-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 <sstream>
34 : #include "surface_view.h"
35 : #include "common/assert.h"
36 : #include "lib_grid/parallelization/util/compol_boolmarker.h"
37 : #include "lib_grid/file_io/file_io.h"
38 : #include "periodic_boundary_manager.h"
39 :
40 : #ifdef UG_PARALLEL
41 : #include "pcl/pcl_interface_communicator.h"
42 : #include "pcl/pcl_process_communicator.h"
43 : #include "lib_grid/parallelization/util/compol_copy_attachment.h"
44 : #endif
45 :
46 : using namespace std;
47 :
48 : namespace ug{
49 :
50 : /// adds marking at extracting side
51 : //todo: change to ComPol_AttachmentBinaryOr
52 : template <class TLayout>
53 : class ComPol_GatherSurfaceStates : public pcl::ICommunicationPolicy<TLayout>
54 : {
55 : public:
56 : typedef TLayout Layout;
57 : typedef typename Layout::Type GeomObj;
58 : typedef typename Layout::Element Element;
59 : typedef typename Layout::Interface Interface;
60 : typedef typename Interface::const_iterator InterfaceIter;
61 :
62 : /// Construct the communication policy with a ug::BoolMarker.
63 : ComPol_GatherSurfaceStates(MultiGrid& mg,
64 : MultiElementAttachmentAccessor<SurfaceView::ASurfaceState>& aaElemSurfState)
65 : : m_mg(mg), m_aaESS(aaElemSurfState)
66 : {}
67 :
68 : virtual ~ComPol_GatherSurfaceStates() {}
69 :
70 : virtual int get_required_buffer_size(const Interface& interface)
71 : {
72 : return interface.size() * sizeof(byte);
73 : }
74 :
75 : /// write surface state for each entry
76 : virtual bool collect(ug::BinaryBuffer& buff, const Interface& intfc)
77 : {
78 : // write the entry indices of marked elements.
79 : for(InterfaceIter iter = intfc.begin(); iter != intfc.end(); ++iter)
80 : {
81 : Element elem = intfc.get_element(iter);
82 : byte val = m_aaESS[elem].get();
83 : buff.write((char*)&val, sizeof(byte));
84 : }
85 : return true;
86 : }
87 :
88 : /// reads marks from the given stream
89 : virtual bool extract(ug::BinaryBuffer& buff, const Interface& intfc)
90 : {
91 : for(InterfaceIter iter = intfc.begin(); iter != intfc.end(); ++iter)
92 : {
93 : Element elem = intfc.get_element(iter);
94 : byte nv;
95 : buff.read((char*)&nv, sizeof(byte));
96 : if(nv > m_aaESS[elem].get())
97 : m_aaESS[elem] = nv;
98 : }
99 : return true;
100 : }
101 :
102 : protected:
103 : MultiGrid& m_mg;
104 : MultiElementAttachmentAccessor<SurfaceView::ASurfaceState> m_aaESS;
105 : };
106 :
107 : ////////////////////////////////////////////////////////////////////////////////
108 : // Create Surface View
109 : ////////////////////////////////////////////////////////////////////////////////
110 : template <class TElem>
111 0 : bool SurfaceView::
112 : is_local_surface_view_element(TElem* elem)
113 : {
114 : #ifdef UG_PARALLEL
115 : return !(m_pMG->has_children(elem)
116 : || m_distGridMgr->is_ghost(elem));
117 : #else
118 0 : return !m_pMG->has_children(elem);
119 : #endif
120 : }
121 :
122 0 : void SurfaceView::
123 : refresh_surface_states()
124 : {
125 : //todo we need a global max-dim!!! (empty processes have to do the right thing, too)
126 : int maxElem = -1;
127 0 : if(m_pMG->num<Volume>() > 0) maxElem = VOLUME;
128 0 : else if(m_pMG->num<Face>() > 0) maxElem = FACE;
129 0 : else if(m_pMG->num<Edge>() > 0) maxElem = EDGE;
130 0 : else if(m_pMG->num<Vertex>() > 0) maxElem = VERTEX;
131 :
132 : #ifdef UG_PARALLEL
133 : pcl::ProcessCommunicator pc;
134 : maxElem = pc.allreduce(maxElem, PCL_RO_MAX);
135 : #endif
136 :
137 : switch(maxElem){
138 0 : case VOLUME: refresh_surface_states<Volume>(); break;
139 0 : case FACE:refresh_surface_states<Face>(); break;
140 0 : case EDGE: refresh_surface_states<Edge>(); break;
141 0 : case VERTEX: refresh_surface_states<Vertex>(); break;
142 : default: break;
143 : }
144 0 : }
145 :
146 : template <class TElem>
147 0 : void SurfaceView::
148 : refresh_surface_states()
149 : {
150 : // some typedefs
151 : typedef typename geometry_traits<TElem>::iterator ElemIter;
152 :
153 0 : MultiGrid& mg = *m_pMG;
154 :
155 : // reset surface states of all elements. Initially, we'll set all states to hidden
156 : SetAttachmentValues(m_aaSurfState, mg.begin<Vertex>(), mg.end<Vertex>(), MG_SHADOW_PURE);
157 : SetAttachmentValues(m_aaSurfState, mg.begin<Edge>(), mg.end<Edge>(), MG_SHADOW_PURE);
158 : SetAttachmentValues(m_aaSurfState, mg.begin<Face>(), mg.end<Face>(), MG_SHADOW_PURE);
159 : SetAttachmentValues(m_aaSurfState, mg.begin<Volume>(), mg.end<Volume>(), MG_SHADOW_PURE);
160 :
161 : // iterate through all levels of the mgsh
162 0 : for(size_t level = 0; level < mg.num_levels(); ++level)
163 : {
164 : // iterate through all elements on that level
165 0 : for(ElemIter iter = mg.begin<TElem>(level);
166 0 : iter != mg.end<TElem>(level); ++iter)
167 : {
168 : TElem* elem = *iter;
169 :
170 0 : if(is_local_surface_view_element(elem)){
171 : surface_state(elem).set(MG_SURFACE_PURE);
172 0 : mark_sides_as_surface_or_shadow<TElem, typename TElem::side>(elem);
173 : }
174 : }
175 : }
176 :
177 : // we now have to mark all shadowing elements.
178 : // Only low dimensional elements can be shadows.
179 : // Perform assignment on higher dimensional elements first, since lower
180 : // dimensional elements may shadow higher dimensional elements...
181 : if(TElem::HAS_SIDES){
182 : // communicate states between all processes
183 : // this is necessary here, since mark_shadowing relies on correct SHADOWED marks.
184 : adjust_parallel_surface_states<Vertex>();
185 : adjust_parallel_surface_states<Edge>();
186 : adjust_parallel_surface_states<Face>();
187 : adjust_parallel_surface_states<Volume>();
188 0 : mark_shadowing<typename TElem::side>(true);
189 : }
190 :
191 : // communicate states between all processes
192 : adjust_parallel_surface_states<Vertex>();
193 : adjust_parallel_surface_states<Edge>();
194 : adjust_parallel_surface_states<Face>();
195 : adjust_parallel_surface_states<Volume>();
196 0 : }
197 :
198 : template <class TElem, class TSide>
199 0 : void SurfaceView::
200 : mark_sides_as_surface_or_shadow(TElem* elem, byte surfaceState)
201 : {
202 : typedef typename PeriodicBoundaryManager::Group<TSide>::SlaveContainer
203 : periodic_slave_container_t;
204 : typedef typename periodic_slave_container_t::iterator periodic_slave_iterator_t;
205 :
206 : if(!TElem::HAS_SIDES)
207 : return;
208 :
209 : typename Grid::traits<TSide>::secure_container sides;
210 0 : PeriodicBoundaryManager* pdm = m_pMG->periodic_boundary_manager();
211 :
212 0 : m_pMG->associated_elements(sides, elem);
213 0 : for(size_t i = 0; i < sides.size(); ++i){
214 : TSide* s = sides[i];
215 0 : if(surface_state(s) == MG_SHADOW_PURE){
216 0 : size_t numChildren = m_pMG->num_children<TSide>(s);
217 0 : if(numChildren == 0)
218 : surface_state(s).set(surfaceState);
219 0 : else if(numChildren == 1)
220 : surface_state(s).set(MG_SHADOW_RIM_COPY);
221 : else
222 : surface_state(s).set(MG_SHADOW_RIM_NONCOPY);
223 :
224 : // if a periodic boundary manager exists, we have to copy this state
225 : // to all linked elements
226 0 : if(pdm && pdm->is_periodic(s)){
227 0 : TSide* master = pdm->master(s);
228 : surface_state(master) = surface_state(s);
229 0 : periodic_slave_container_t* slaves = pdm->slaves(master);
230 0 : for(periodic_slave_iterator_t i = slaves->begin();
231 0 : i != slaves->end(); ++i)
232 : {
233 0 : surface_state(*i) = surface_state(master);
234 : }
235 : }
236 : }
237 : }
238 :
239 : if(TSide::HAS_SIDES)
240 0 : mark_sides_as_surface_or_shadow<TElem, typename TSide::side>(elem, surfaceState);
241 : }
242 :
243 : template <class TElem>
244 0 : void SurfaceView::
245 : mark_shadowing(bool markSides)
246 : {
247 : typedef typename Grid::traits<TElem>::iterator TIter;
248 :
249 0 : MultiGrid& mg = *m_pMG;
250 :
251 0 : for(size_t lvl = 1; lvl < mg.num_levels(); ++lvl){
252 0 : for(TIter iter = mg.begin<TElem>(lvl); iter != mg.end<TElem>(lvl); ++iter)
253 : {
254 : TElem* e = *iter;
255 0 : if(surface_state(e).contains(MG_SHADOW_PURE))
256 0 : continue;
257 :
258 : GridObject* p = mg.get_parent(e);
259 0 : if(p && (surface_state(p).contains(MG_SHADOW_RIM_COPY)
260 0 : || surface_state(p).contains(MG_SHADOW_RIM_NONCOPY)))
261 : {
262 : #ifdef UG_PARALLEL
263 : // The following assertions make sure that during gmg no values have to
264 : // be copied across v-interfaces during add-missing-coarse-grid-correction etc.
265 : // However, when a closure is used, shadowing shadows do currently exist
266 : // and this is why the assertion is only triggered for parallel cases
267 : // (in which closure isn't assumed to work anyways).
268 : // The assertion probably shouldn't be done here but directly in the gmg.
269 : UG_COND_THROW((pcl::NumProcs() > 1) &&
270 : surface_state(e).contains(MG_SHADOW_RIM_COPY),
271 : "SHADOWING-SHADOW_COPY encountered: " << ElementDebugInfo(mg, e));
272 : UG_COND_THROW((pcl::NumProcs() > 1) &&
273 : surface_state(e).contains(MG_SHADOW_RIM_NONCOPY),
274 : "SHADOWING-SHADOW_NONCOPY encountered: " << ElementDebugInfo(mg, e));
275 : #endif
276 : surface_state(e).add(MG_SURFACE_RIM);
277 : surface_state(e).remove(MG_SURFACE_PURE);
278 : }
279 : }
280 : }
281 :
282 0 : if(markSides && TElem::HAS_SIDES){
283 0 : mark_shadowing<typename TElem::side>(markSides);
284 : }
285 0 : }
286 :
287 : template <class TElem>
288 : void SurfaceView::
289 : adjust_parallel_surface_states()
290 : {
291 : #ifdef UG_PARALLEL
292 : typedef typename GridLayoutMap::Types<TElem>::Layout Layout;
293 :
294 : GridLayoutMap& glm = m_distGridMgr->grid_layout_map();
295 : ComPol_GatherSurfaceStates<Layout> cpAdjust(*m_pMG, m_aaSurfState);
296 : pcl::InterfaceCommunicator<Layout> com;
297 : com.exchange_data(glm, INT_H_SLAVE, INT_H_MASTER, cpAdjust);
298 : // the v-communication is only required if constrained ghosts can be surface elements.
299 : com.exchange_data(glm, INT_V_MASTER, INT_V_SLAVE, cpAdjust);
300 : com.communicate();
301 :
302 : ComPol_CopyAttachment<Layout, ASurfaceState> cpCopyStates(*m_pMG, m_aSurfState);
303 : com.exchange_data(glm, INT_H_MASTER, INT_H_SLAVE, cpCopyStates);
304 : com.communicate();
305 :
306 : // communicate final marks to v-masters (if one wants to iterate over ghosts...)
307 : com.exchange_data(glm, INT_V_SLAVE, INT_V_MASTER, cpCopyStates);
308 : com.communicate();
309 : #endif
310 : }
311 :
312 :
313 : ////////////////////////////////////////////////////////////////////////////////
314 : // SurfaceView
315 : ////////////////////////////////////////////////////////////////////////////////
316 :
317 0 : SurfaceView::SurfaceView(SmartPtr<MGSubsetHandler> spMGSH,
318 0 : bool adaptiveMG) :
319 : m_spMGSH(spMGSH),
320 0 : m_adaptiveMG(adaptiveMG),
321 0 : m_pMG(m_spMGSH->multi_grid()),
322 0 : m_distGridMgr(m_spMGSH->multi_grid()->distributed_grid_manager())
323 : {
324 : UG_ASSERT(m_pMG, "A MultiGrid has to be assigned to the given subset handler");
325 :
326 0 : m_pMG->attach_to_all_dv(m_aSurfState, 0);
327 0 : m_aaSurfState.access(*m_pMG, m_aSurfState);
328 :
329 0 : refresh_surface_states();
330 0 : }
331 :
332 0 : SurfaceView::~SurfaceView()
333 : {
334 0 : m_pMG->detach_from_all(m_aSurfState);
335 0 : }
336 :
337 : }// end of namespace
|