Line data Source code
1 : /*
2 : * Copyright (c) 2012-2015: G-CSC, Goethe University Frankfurt
3 : * Author: Martin Scherer
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 PERIODIC_IDENTIFIER_H_
34 : #define PERIODIC_IDENTIFIER_H_
35 :
36 : #include "lib_grid/grid/grid.h"
37 : #include "lib_grid/multi_grid.h"
38 : #include "lib_grid/grid/grid_base_objects.h"
39 :
40 : #include <set>
41 :
42 : namespace ug {
43 :
44 : /// Interface to match periodic geometric elements
45 : /**
46 : *
47 : */
48 : class IIdentifier {
49 : public:
50 : virtual ~IIdentifier() {}
51 : virtual bool match(Vertex*, Vertex*) = 0;
52 : virtual bool match(Edge*, Edge*) = 0;
53 : virtual bool match(Face*, Face*) = 0;
54 0 : virtual bool match(Volume*, Volume*) {UG_THROW("not impled, because volume identification is not supported.")}
55 : };
56 :
57 : /// This class matches geometric elements which are parallel translated.
58 : /**
59 : * Usage: class needs to be instantiated with the position attachment used on the Domain.
60 : * Before using any match methods, the translation vector needs to be set with set_shift()
61 : * \tparam <TPosAA>{class needs to be instantiated with the
62 : * position attachment used on the Domain.}
63 : */
64 : template<class TPosAA> class ParallelShiftIdentifier: public IIdentifier {
65 : public:
66 0 : virtual bool match(Vertex* v1, Vertex* v2) {return match_impl(v1, v2);}
67 0 : virtual bool match(Edge* e1, Edge* e2) {return match_impl(e1, e2);}
68 0 : virtual bool match(Face* f1, Face* f2) {return match_impl(f1, f2);}
69 :
70 0 : virtual ~ParallelShiftIdentifier() {}
71 : typedef typename TPosAA::ValueType AttachmentType;
72 0 : ParallelShiftIdentifier(TPosAA& aa) : m_aaPos(aa) {}
73 : void set_shift(AttachmentType& shift) {m_shift = shift; VecScale(m_shift_opposite, m_shift, -1);}
74 : protected:
75 : AttachmentType m_shift;
76 : AttachmentType m_shift_opposite;
77 : TPosAA& m_aaPos;
78 : template<class TElem> bool match_impl(TElem*, TElem*) const;
79 : };
80 :
81 :
82 : //template<class TPosAA, int dim> class TransformationBasedIdentifier : public IIdentifier {
83 : //public:
84 : // TransformationBasedIdentifier(TPosAA& aa) : m_aaPos(aa) {}
85 : // void setTransformation(MathMatrix<dim,dim>& T) {this->T = T;}
86 : //
87 : // virtual bool match(Vertex*, Vertex*);
88 : // virtual bool match(Edge*, Edge*);
89 : // virtual bool match(Face*, Face*);
90 : //protected:
91 : // MathMatrix<dim,dim> T;
92 : // TPosAA& m_aaPos;
93 : //};
94 :
95 : ///
96 : /**
97 : *
98 : */
99 : class PeriodicBoundaryManager : public GridObserver {
100 : public:
101 :
102 : /**
103 : * A Group instance holds a master of type TElem and several children.
104 : */
105 : template <class TElem, class Container = std::vector<TElem*> >
106 0 : class Group
107 : {
108 : public:
109 : typedef Container SlaveContainer;
110 : typedef typename Container::iterator SlaveIterator;
111 : // the set typedefs are used to check for periodicity after identification
112 : typedef typename std::pair<TElem*, TElem*> master_slave_pair;
113 : typedef typename std::set<master_slave_pair> unique_pairs;
114 :
115 0 : Group(TElem* m = NULL) : m_master(m) {}
116 :
117 : void add_slave(TElem* e) {
118 : UG_ASSERT(e, "add_slave: slave not valid");
119 : UG_ASSERT(e != m_master, "element already master!");
120 0 : m_slaves.push_back(e); }
121 :
122 0 : Container& get_slaves() { return m_slaves; }
123 : TElem* m_master;
124 :
125 : protected:
126 : Container m_slaves;
127 : };
128 :
129 : enum PeriodicStatus {
130 : P_SLAVE, P_SLAVE_MASTER_UNKNOWN, P_MASTER, P_NOT_PERIODIC
131 : };
132 :
133 : PeriodicBoundaryManager();
134 : ~PeriodicBoundaryManager();
135 :
136 : // sets grid and inits group info attachment accessors
137 : void set_grid(Grid* g);
138 : Grid* get_grid() const;
139 :
140 : // sets the subset handler to use for element lookup
141 : // void set_subset_handler(ISubsetHandler* sh);
142 :
143 : ///
144 : /**
145 : * ATTENTION: method assumes, that e1 and e2 are matching!
146 : * identifies element e1 with e2. If element type has sides, it will recursively
147 : * ascend to the lowest dimension type (vertex) and identifies them.
148 : * @param e1
149 : * @param e2
150 : * @param i identifier to use to perform geometrical matching of elements
151 : */
152 : template <class TElem> void identify(TElem* e1, TElem* e2, IIdentifier& i);
153 :
154 : template <class TElem> bool is_periodic(TElem* e) const;
155 : template <class TElem> bool is_slave(TElem*) const;
156 : template <class TElem> bool is_master(TElem*) const;
157 : template <class TElem> TElem* master(TElem* e) const;
158 : template <class TElem> typename Group<TElem>::SlaveContainer* slaves(
159 : TElem* e) const;
160 : template <class TElem> void print_identification() const;
161 :
162 :
163 : /// grid observation methods
164 : virtual void grid_to_be_destroyed(Grid* grid);
165 : virtual void vertex_created(Grid* grid, Vertex* vrt,
166 : GridObject* pParent = NULL,
167 : bool replacesParent = false);
168 :
169 : virtual void edge_created(Grid* grid, Edge* e,
170 : GridObject* pParent = NULL,
171 : bool replacesParent = false);
172 :
173 : virtual void face_created(Grid* grid, Face* f,
174 : GridObject* pParent = NULL,
175 : bool replacesParent = false);
176 :
177 : virtual void vertex_to_be_erased(Grid* grid, Vertex* vrt,
178 : Vertex* replacedBy = NULL);
179 :
180 : virtual void edge_to_be_erased(Grid* grid, Edge* e,
181 : Edge* replacedBy = NULL);
182 :
183 : virtual void face_to_be_erased(Grid* grid, Face* f,
184 : Face* replacedBy = NULL);
185 :
186 : /// checks that all elements of given gocs are periodic (called after identification)
187 : bool check_periodicity(const GridObjectCollection& goc1,
188 : const GridObjectCollection& goc2,
189 : ISubsetHandler* sh = NULL);
190 :
191 : /** makes sure that all master/slave identifications are correct and that
192 : * no unconnected masters or slaves exist.
193 : * This method iterates over all elements of the grid and is thus rather expensive.*/
194 : void validity_check();
195 :
196 : /**
197 : * sets the identifier instance to use for subset index si
198 : * @param i identifier pointer
199 : * @param si
200 : */
201 : // void set_identifier(SmartPtr<IIdentifier> i, size_t si);
202 :
203 : protected:
204 : // no copy construction allowed
205 : PeriodicBoundaryManager(const PeriodicBoundaryManager&) {}
206 :
207 : /// grid instance we operate on
208 : MultiGrid* m_pGrid;
209 :
210 : /// store subset handler of domain to lookup element subset ids
211 : // ISubsetHandler* m_pSH;
212 :
213 : /// identifier mapping to subset indices
214 : /**
215 : * stores IIdentifier pointers to subset index position to look them up
216 : * in constant time.
217 : */
218 : // std::vector<SmartPtr<IIdentifier> > m_vIdentifier;
219 :
220 : /// attachment accessors for Groups
221 : Grid::AttachmentAccessor<Vertex, Attachment<Group<Vertex>* > > m_aaGroupVRT;
222 : Grid::AttachmentAccessor<Edge, Attachment<Group<Edge>* > > m_aaGroupEDG;
223 : Grid::AttachmentAccessor<Face, Attachment<Group<Face>* > > m_aaGroupFCE;
224 :
225 : /// attachment accessors for PeriodicStatus
226 : Grid::AttachmentAccessor<Vertex, Attachment<PeriodicStatus> > m_aaPeriodicStatusVRT;
227 : Grid::AttachmentAccessor<Edge, Attachment<PeriodicStatus> > m_aaPeriodicStatusEDG;
228 : Grid::AttachmentAccessor<Face, Attachment<PeriodicStatus> > m_aaPeriodicStatusFCE;
229 :
230 : /// make element e slave of group g
231 : template <class TElem> void make_slave(Group<TElem>* g, TElem* e);
232 : template <class TElem> bool remove_slave(TElem* slave);
233 :
234 : // make e a master of g
235 : template <class TElem> void make_master(Group<TElem>* g, TElem* e);
236 :
237 : template <class TElem> void merge_groups(Group<TElem>* g0, Group<TElem>* g1);
238 :
239 : // get typed attachment accessor for group attachment
240 : template <class TElem>
241 : const Grid::AttachmentAccessor<TElem, Attachment<Group<TElem>* > >&
242 : get_group_accessor() const;
243 :
244 : template <class TElem>
245 : Grid::AttachmentAccessor<TElem, Attachment<Group<TElem>* > >&
246 : get_group_accessor();
247 :
248 : // get typed attachment accessor for periodic status attachment
249 : template <class TElem>
250 : const Grid::AttachmentAccessor<TElem, Attachment<PeriodicStatus> >&
251 : get_periodic_status_accessor() const;
252 :
253 : template <class TElem>
254 : Grid::AttachmentAccessor<TElem, Attachment<PeriodicStatus> >&
255 : get_periodic_status_accessor();
256 :
257 : // gets group of given element e
258 : template <class TElem> Group<TElem>* group(TElem* e) const;
259 : // set group attachment to element e
260 : template <class TElem> void set_group(Group<TElem>* g, TElem* e);
261 : template <class TElem> void remove_group(Group<TElem>* g);
262 :
263 : /// replaces all group occurrances of pParent by the specified elem
264 : template <class TElem>
265 : void replace_parent(TElem* e, TElem* pParent);
266 :
267 : /// handles creation of element type
268 : template <class TElem, class TParent>
269 : void handle_creation(TElem* e, TParent* pParent);
270 :
271 : /// handles deletion of element type
272 : template <class TElem>
273 : void handle_deletion(TElem* e, TElem* replacedBy);
274 :
275 : /// casts parent pointer to exact type before calling handle_creation
276 : template <class TElem>
277 : void handle_creation_cast_wrapper(TElem* e, GridObject* parent, bool replacesParent);
278 :
279 : template <class TElem, class TIterator>
280 : void check_elements_periodicity(
281 : TIterator begin,
282 : TIterator end,
283 : typename Group<TElem>::unique_pairs& s,
284 : ISubsetHandler* sh);
285 :
286 : template <class TElem>
287 : void validity_check();
288 :
289 : };
290 :
291 : /// Accesses attachements with consideration to periodic boundaries
292 : /** Slave element redirects to related master element
293 : * also works in case of no periodic boundary conditions
294 : * (but is then probably slower than standard attachment accessor)
295 : */
296 : template <class TElem,class TAttachment>
297 : class PeriodicAttachmentAccessor
298 : {
299 : public:
300 : typedef typename TAttachment::ValueType ValueType;
301 : typedef typename attachment_value_traits<ValueType>::reference RefType;
302 : typedef typename attachment_value_traits<ValueType>::const_reference ConstRefType;
303 :
304 : PeriodicAttachmentAccessor() : m_pbm(NULL) {}
305 :
306 : PeriodicAttachmentAccessor(Grid& g, TAttachment& a) : m_pbm(NULL)
307 : {
308 : access(g, a);
309 : }
310 :
311 : PeriodicAttachmentAccessor(PeriodicBoundaryManager& pbm) : m_pbm(&pbm) {}
312 :
313 : bool access(Grid& g, TAttachment& a)
314 : {
315 : if (!(m_pbm)) m_pbm = g.periodic_boundary_manager();
316 : return m_aa.access(g, a);
317 : }
318 :
319 : RefType operator[](TElem* e) {
320 : if(m_pbm && m_pbm->is_slave(e))
321 : return m_aa[m_pbm->master(e)];
322 : return m_aa[e];
323 : }
324 :
325 : ConstRefType operator[](TElem* e) const {
326 : if(m_pbm && m_pbm->is_slave(e))
327 : return m_aa[m_pbm->master(e)];
328 : return m_aa[e];
329 : }
330 :
331 : private:
332 : Grid::AttachmentAccessor<TElem, TAttachment> m_aa;
333 : PeriodicBoundaryManager* m_pbm;
334 : };
335 :
336 :
337 : /**
338 : * \brief identifies subset 1 with subset 2. If the grid of given domain has no
339 : * periodic boundary manager attached, one will be created.
340 : *
341 : * \param dom Domain the periodic boundary should be defined on
342 : * \param sInd1 subset index which elements should be identified with elements from
343 : * those of sInd2
344 : * \param sInd2 \see{sInd1}
345 : */
346 : template <class TDomain>
347 : void IdentifySubsets(TDomain& dom, int sInd1, int sInd2);
348 :
349 : /**
350 : * \brief identifies subset 1 with subset 2. If the grid of given domain has no
351 : * periodic boundary manager attached, one will be created.
352 : *
353 : * \param dom Domain the periodic boundary should be defined on
354 : * \param sName1 subset name which elements should be identified with elements from
355 : * those of sName2
356 : * \param sName2 \see {sName1}
357 : */
358 : template <class TDomain>
359 : void IdentifySubsets(TDomain& dom, const char* sName1, const char* sName2);
360 :
361 : } // end of namespace ug
362 :
363 : // include implementation
364 : #include "./periodic_boundary_manager_impl.hpp"
365 :
366 : #endif /* PERIODIC_IDENTIFIER_H_ */
|