Line data Source code
1 : /*
2 : * Copyright (c) 2016: 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 "projection_handler.h"
34 :
35 : namespace ug{
36 :
37 0 : ProjectionHandler::
38 0 : ProjectionHandler () :
39 0 : m_sh (NULL)
40 : {
41 0 : m_defaultProjector = make_sp(new RefinementProjector);
42 0 : }
43 :
44 0 : ProjectionHandler::
45 0 : ProjectionHandler (ISubsetHandler* psh) :
46 0 : m_sh (psh)
47 : {
48 0 : m_defaultProjector = make_sp(new RefinementProjector);
49 0 : }
50 :
51 0 : ProjectionHandler::
52 0 : ProjectionHandler (SmartPtr<ISubsetHandler> psh) :
53 0 : m_sh (psh.get()),
54 0 : m_spSH (psh)
55 : {
56 0 : m_defaultProjector = make_sp(new RefinementProjector);
57 0 : }
58 :
59 0 : ProjectionHandler::
60 : ProjectionHandler (SPIGeometry3d geometry,
61 0 : ISubsetHandler* psh) :
62 : RefinementProjector (geometry),
63 0 : m_sh (psh)
64 : {
65 0 : m_defaultProjector = make_sp(new RefinementProjector);
66 0 : }
67 :
68 0 : ProjectionHandler::
69 0 : ~ProjectionHandler () {}
70 :
71 0 : void ProjectionHandler::
72 : clear()
73 : {
74 : m_projectors.clear();
75 0 : m_defaultProjector = make_sp(new RefinementProjector);
76 0 : }
77 :
78 0 : void ProjectionHandler::
79 : set_geometry (SPIGeometry3d geometry)
80 : {
81 0 : RefinementProjector::set_geometry (geometry);
82 0 : m_defaultProjector->set_geometry(geometry);
83 0 : }
84 :
85 0 : void ProjectionHandler::
86 : set_geometry_all (SPIGeometry3d geometry)
87 : {
88 0 : set_geometry(geometry);
89 0 : m_defaultProjector->set_geometry(geometry);
90 0 : for(size_t i = 0; i < m_projectors.size(); ++i){
91 0 : if(m_projectors[i].valid())
92 0 : m_projectors[i]->set_geometry(geometry);
93 : }
94 0 : }
95 :
96 0 : void ProjectionHandler::
97 : set_subset_handler (ISubsetHandler* psh)
98 : {
99 0 : if(m_spSH.valid())
100 0 : m_spSH = SmartPtr<ISubsetHandler>();
101 0 : m_sh = psh;
102 0 : }
103 :
104 0 : void ProjectionHandler::
105 : set_subset_handler (SmartPtr<ISubsetHandler> psh)
106 : {
107 0 : m_spSH = psh;
108 0 : m_sh = psh.get();
109 0 : }
110 :
111 :
112 0 : void ProjectionHandler::
113 : set_default_projector (SPRefinementProjector projector)
114 : {
115 0 : m_defaultProjector = projector;
116 0 : }
117 :
118 0 : void ProjectionHandler::
119 : set_projector (int subsetIndex, SPRefinementProjector projector)
120 : {
121 0 : UG_COND_THROW (subsetIndex < -1,
122 : "Bad subset-index in ProjectionHandler::set_projector: "
123 : << subsetIndex << ". Indices have to be >= -1");
124 :
125 0 : projector_required(subsetIndex);
126 :
127 0 : m_projectors [subsetIndex + 1] = projector;
128 :
129 : // we want to make sure that a default geometry exists
130 0 : if(geometry().invalid() && projector->geometry().valid())
131 0 : set_geometry (projector->geometry());
132 0 : }
133 :
134 0 : void ProjectionHandler::
135 : set_projector (const char* subsetName, SPRefinementProjector projector)
136 : {
137 0 : UG_COND_THROW (!m_sh, "Please set a valid SubsetHandler to 'ProjectionHandler' "
138 : "before calling 'set_projector' with a subset-name.");
139 0 : int si = m_sh->get_subset_index(subsetName);
140 0 : set_projector (si, projector);
141 0 : }
142 :
143 : ////////////////////////////////////////
144 : // IMPLEMENTATION OF RefinementProjector
145 0 : bool ProjectionHandler::
146 : refinement_begins_requires_subgrid () const
147 : {
148 0 : for(size_t i = 0; i < m_projectors.size(); ++i){
149 : if(m_projectors[i].valid()
150 0 : && m_projectors[i]->refinement_begins_requires_subgrid())
151 : {
152 : return true;
153 : }
154 : }
155 : return false;
156 : }
157 :
158 0 : void ProjectionHandler::
159 : refinement_begins (const ISubGrid* psg)
160 : {
161 0 : RefinementProjector::refinement_begins(psg);
162 :
163 0 : UG_COND_THROW(!m_sh, "Please set a valid SubsetHandler to "
164 : "'ProjectionHandler' before using it during refinement.");
165 :
166 :
167 0 : if(!m_defaultProjector->geometry().valid())
168 0 : m_defaultProjector->set_geometry(geometry());
169 :
170 : // make sure that the internal vector of projectors is at least as large
171 : // as there are subsets in the associated subset handler
172 0 : projector_required((int)m_sh->num_subsets()-1);
173 :
174 : // this selector will be used if we have to pass sub-grids to individual projectors
175 0 : Selector sel;
176 :
177 0 : for(size_t i = 0;
178 0 : i < std::min<size_t>(m_projectors.size(), m_sh->num_subsets() + 1);
179 : ++i)
180 : {
181 0 : if(!m_projectors[i].valid())
182 0 : continue;
183 :
184 : RefinementProjector& proj = *m_projectors[i];
185 0 : if(!proj.geometry().valid())
186 0 : proj.set_geometry(geometry());
187 :
188 : //todo: move this somewhere where it is only triggered if required.
189 : // e.g. to 'set_subset_handler' and 'add_projector'
190 0 : proj.set_concerned_elements(make_sp(new IsInSubset(*m_sh, i-1)));
191 :
192 0 : if(!proj.refinement_begins_requires_subgrid()) {
193 0 : proj.refinement_begins(NULL);
194 : }
195 : else{
196 : const ISubGrid& sg = *psg;
197 :
198 0 : if(!sel.grid())
199 0 : sel.assign_grid(geom().grid());
200 :
201 0 : sel.clear();
202 : bool selectionPerformed = false;
203 :
204 : // this is a small optimization. We can either iterate over the elements
205 : // of sg or of subset (i-1), i>0. Choose the one with less elements.
206 0 : GridObjectCollection subsetGoc;
207 0 : if(i > 0){
208 0 : subsetGoc = m_sh->get_grid_objects_in_subset(i - 1);
209 : // todo: this check would be more precise if only those element-types
210 : // were considered which exist in both goc's
211 0 : if(subsetGoc.num_vertices() + subsetGoc.num_edges()
212 0 : + subsetGoc.num_faces() + subsetGoc.num_volumes()
213 0 : < sg.goc().num_vertices() + sg.goc().num_edges()
214 0 : + sg.goc().num_faces() + sg.goc().num_volumes())
215 : {
216 0 : if(sg.goc().num_vertices() > 0){
217 0 : lg_for_each_const(Vertex, e, subsetGoc){
218 0 : if(sg.is_contained(e))
219 : sel.select(e);
220 : }lg_end_for;
221 : }
222 0 : if(sg.goc().num_edges() > 0){
223 0 : lg_for_each_const(Edge, e, subsetGoc){
224 0 : if(sg.is_contained(e))
225 : sel.select(e);
226 : }lg_end_for;
227 : }
228 0 : if(sg.goc().num_faces() > 0){
229 0 : lg_for_each_const(Face, e, subsetGoc){
230 0 : if(sg.is_contained(e))
231 : sel.select(e);
232 : }lg_end_for;
233 : }
234 0 : if(sg.goc().num_volumes() > 0){
235 0 : lg_for_each_const(Volume, e, subsetGoc){
236 0 : if(sg.is_contained(e))
237 : sel.select(e);
238 : }lg_end_for;
239 : }
240 :
241 : selectionPerformed = true;
242 : }
243 : }
244 :
245 : if(!selectionPerformed){
246 0 : if(i == 0 || subsetGoc.num_vertices() > 0){
247 0 : lg_for_each_const(Vertex, e, sg.goc()){
248 0 : if(m_sh->get_subset_index(e) + 1 == (int)i)
249 : sel.select(e);
250 : }lg_end_for;
251 : }
252 0 : if(i == 0 || subsetGoc.num_edges() > 0){
253 0 : lg_for_each_const(Edge, e, sg.goc()){
254 0 : if(m_sh->get_subset_index(e) + 1 == (int)i)
255 : sel.select(e);
256 : }lg_end_for;
257 : }
258 0 : if(i == 0 || subsetGoc.num_faces() > 0){
259 0 : lg_for_each_const(Face, e, sg.goc()){
260 0 : if(m_sh->get_subset_index(e) + 1 == (int)i)
261 : sel.select(e);
262 : }lg_end_for;
263 : }
264 0 : if(i == 0 || subsetGoc.num_volumes() > 0){
265 0 : lg_for_each_const(Volume, e, sg.goc()){
266 0 : if(m_sh->get_subset_index(e) + 1 == (int)i)
267 : sel.select(e);
268 : }lg_end_for;
269 : }
270 : }
271 :
272 0 : SubGrid<IsSelected> tsg(sel.get_grid_objects(), IsSelected(sel));
273 0 : proj.refinement_begins(&tsg);
274 : }
275 : }
276 0 : }
277 :
278 0 : void ProjectionHandler::
279 : refinement_ends()
280 : {
281 : RefinementProjector::refinement_ends();
282 0 : for(size_t i = 0; i < m_projectors.size(); ++i){
283 0 : if(m_projectors[i].valid())
284 0 : m_projectors[i]->refinement_ends();
285 : }
286 0 : }
287 :
288 0 : number ProjectionHandler::
289 : new_vertex (Vertex* vrt, Vertex* parent)
290 : {
291 0 : return handle_new_vertex (vrt, parent);
292 : }
293 :
294 0 : number ProjectionHandler::
295 : new_vertex (Vertex* vrt, Edge* parent)
296 : {
297 0 : return handle_new_vertex (vrt, parent);
298 : }
299 :
300 0 : number ProjectionHandler::
301 : new_vertex (Vertex* vrt, Face* parent)
302 : {
303 0 : return handle_new_vertex (vrt, parent);
304 : }
305 :
306 0 : number ProjectionHandler::
307 : new_vertex (Vertex* vrt, Volume* parent)
308 : {
309 0 : return handle_new_vertex (vrt, parent);
310 : }
311 :
312 :
313 :
314 0 : void ProjectionHandler::
315 : projector_required(int index) {
316 : // in order to automatically treat subset '-1' correctly, internally we add 1
317 : // to each subset-index
318 0 : if(index + 1 >= (int)m_projectors.size())
319 0 : m_projectors.resize(index + 2);
320 0 : }
321 :
322 : template <class TParent>
323 0 : number ProjectionHandler::
324 : handle_new_vertex (Vertex* vrt, TParent* parent)
325 : {
326 0 : int si = m_sh->get_subset_index(parent);
327 :
328 : UG_ASSERT (si + 1 < (int) m_projectors.size(),
329 : "Please make sure to call 'refinement_begins' before calling "
330 : "'new_vertex' for the first time for a given subset-assignment.");
331 :
332 :
333 : number ia = 0;
334 0 : if(m_projectors [si + 1].valid())
335 : {
336 0 : ia = m_projectors [si + 1]->new_vertex (vrt, parent);
337 :
338 0 : if(ia < 1){
339 : vector3 p = pos (vrt);
340 0 : m_defaultProjector->new_vertex (vrt, parent);
341 : vector3 lp = pos (vrt);
342 : p *= ia;
343 0 : lp *= (1. - ia);
344 : p += lp;
345 : set_pos(vrt, p);
346 : }
347 : }
348 0 : else m_defaultProjector->new_vertex (vrt, parent);
349 :
350 0 : return 1;
351 : }
352 :
353 : }// end of namespace
|