Line data Source code
1 : /*
2 : * Copyright (c) 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 : #ifndef __H__UG_global_attachments
34 : #define __H__UG_global_attachments
35 :
36 : #include "attachments/attachment_info_traits.h"
37 : #include "attachments/attachment_io_traits.h"
38 : #include "algorithms/serialization.h"
39 : #include <algorithm>
40 :
41 : namespace ug{
42 :
43 : /// Global attachments are automatically read/written from/to files and are considered during redistribution
44 : class GlobalAttachments {
45 : public:
46 : template <class TAttachment>
47 0 : static void declare_attachment (const std::string& name,
48 : bool passOnBehaviour = false)
49 : {
50 : const char* typeName = attachment_info_traits<TAttachment>::type_name();
51 0 : if(attachments()[name].attachment != NULL) {
52 0 : UG_COND_THROW(
53 : dynamic_cast<TAttachment*> (attachments()[name].attachment) == NULL,
54 : "Attachment with name '" << name
55 : << "' was already declared in GlobalAttachments with a different type. "
56 : << "Old type: " << attachments()[name].type <<
57 : ", new type: " << typeName);
58 : return;
59 : }
60 :
61 0 : int fi = static_cast<int> (attachment_names().size());
62 0 : attachment_names().push_back(name);
63 0 : attachments()[name] =
64 0 : AttachmentEntry(new TAttachment(passOnBehaviour), typeName, fi);
65 0 : functions<Vertex>().push_back(FunctionEntry<Vertex, TAttachment>());
66 0 : functions<Edge>().push_back(FunctionEntry<Edge, TAttachment>());
67 0 : functions<Face>().push_back(FunctionEntry<Face, TAttachment>());
68 0 : functions<Volume>().push_back(FunctionEntry<Volume, TAttachment>());
69 : }
70 :
71 : template <class TAttachment>
72 : static void undeclare_attachment(const std::string& name) {
73 : UG_COND_THROW(!is_declared(name), "Trying undeclaring a non-declared attachment.");
74 : AttachmentEntry& ae = attachment_entry(name);
75 : remove_function_entry<Volume>(ae);
76 : remove_function_entry<Face>(ae);
77 : remove_function_entry<Edge>(ae);
78 : remove_function_entry<Vertex>(ae);
79 : attachment_names().erase(std::remove(attachment_names().begin(), attachment_names().end(), name), attachment_names().end());
80 : attachments().erase(name);
81 : const char* typeName = attachment_info_traits<TAttachment>::type_name();
82 : attachment_types().erase(typeName);
83 : }
84 :
85 0 : static void declare_attachment (const std::string& name,
86 : const std::string& typeName,
87 : bool passOnBehaviour = false)
88 : {
89 0 : UG_COND_THROW(attachment_types()[typeName].declareFunc == 0,
90 : "Unregistered attachment type used in "
91 : << "GlobalAttachments::declare_attachment: '"
92 : << typeName << "' during declaration of attachment '"
93 : << name << "'.");
94 0 : attachment_types()[typeName].declareFunc(name, passOnBehaviour);
95 0 : }
96 :
97 : template <class TAttachment>
98 0 : static void register_attachment_type ()
99 : {
100 0 : std::string typeName = attachment_info_traits<TAttachment>::type_name();
101 0 : attachment_types()[typeName] = AttachmentType<TAttachment>();
102 0 : }
103 :
104 : static const std::vector<std::string>&
105 : declared_attachment_names ()
106 : {
107 : return attachment_names();
108 : }
109 :
110 : static
111 0 : bool is_declared(const std::string& name)
112 : {
113 0 : return attachments().find(name) != attachments().end();
114 : }
115 :
116 : static
117 0 : bool attachment_pass_on_behaviour(const std::string& name)
118 : {
119 0 : UG_COND_THROW(!is_declared(name), "Undeclared attachment queried: " << name);
120 0 : return attachments()[name].attachment->default_pass_on_behaviour();
121 : }
122 :
123 : static
124 0 : bool type_is_registered(const std::string& typeName)
125 : {
126 0 : return attachment_types().find(typeName) != attachment_types().end();
127 : }
128 :
129 : #ifdef UG_PARALLEL
130 : static void SynchronizeDeclaredGlobalAttachments(Grid& grid, int procId)
131 : {
132 : if (procId < 0) return; // this is not a parallel run
133 :
134 : //declare global attachments on all processors
135 : pcl::ProcessCommunicator procComm;
136 : std::vector<std::string> possible_attachment_names = GlobalAttachments::declared_attachment_names();
137 : // only master proc loaded the grid
138 : if (procId == 0)
139 : procComm.broadcast<std::vector<std::string> >(possible_attachment_names, procId);
140 : else
141 : UG_THROW("There are more than one proc loading the grid"<<
142 : "please make sure all processes broadcast their GlobalAttachments");
143 :
144 : std::vector<byte> locDeclared(possible_attachment_names.size(), 0);
145 : std::vector<byte> globDeclared(possible_attachment_names.size(), 0);
146 : // record local info
147 : for(size_t i = 0; i < possible_attachment_names.size(); ++i){
148 : byte& b = locDeclared[i];
149 : if(GlobalAttachments::is_declared(possible_attachment_names[i])){
150 : b |= 1;
151 : if(GlobalAttachments::is_attached<Vertex>(grid, possible_attachment_names[i]))
152 : b |= 1<<1;
153 : if(GlobalAttachments::is_attached<Edge>(grid, possible_attachment_names[i]))
154 : b |= 1<<2;
155 : if(GlobalAttachments::is_attached<Face>(grid, possible_attachment_names[i]))
156 : b |= 1<<3;
157 : if(GlobalAttachments::is_attached<Volume>(grid, possible_attachment_names[i]))
158 : b |= 1<<4;
159 : }
160 : }
161 : // sum up all the local to the global
162 : procComm.allreduce(locDeclared, globDeclared, PCL_RO_BOR);
163 : // update the local with the global
164 : for(size_t i = 0; i < possible_attachment_names.size(); ++i){
165 : byte& b = globDeclared[i];
166 : if(b & 1){
167 : if(!GlobalAttachments::is_declared(possible_attachment_names[i]))
168 : GlobalAttachments::declare_attachment(possible_attachment_names[i], "double", true);
169 : if(b & 1<<1)
170 : GlobalAttachments::attach<Vertex>(grid, possible_attachment_names[i]);
171 : if(b & 1<<2)
172 : GlobalAttachments::attach<Edge>(grid, possible_attachment_names[i]);
173 : if(b & 1<<3)
174 : GlobalAttachments::attach<Face>(grid, possible_attachment_names[i]);
175 : if(b & 1<<4)
176 : GlobalAttachments::attach<Volume>(grid, possible_attachment_names[i]);
177 : }
178 : }
179 :
180 : }
181 : #endif
182 :
183 : template <class TElem>
184 : static
185 : void attach(Grid& g, const std::string& name)
186 : {
187 : AttachmentEntry& ae = attachment_entry(name);
188 : IFunctionEntry& fe = function_entry<TElem>(ae);
189 : fe.attach(g, *ae.attachment);
190 : }
191 :
192 : template <class TElem>
193 : static
194 0 : bool is_attached(Grid& g, const std::string& name)
195 : {
196 0 : AttachmentEntry& ae = attachment_entry(name);
197 0 : return g.has_attachment<TElem>(*ae.attachment);
198 : }
199 :
200 : template <class TAttachment>
201 : static
202 0 : TAttachment attachment (const std::string& name)
203 : {
204 0 : AttachmentEntry& e = attachment_entry(name);
205 0 : TAttachment* a = dynamic_cast<TAttachment*>(e.attachment);
206 0 : UG_COND_THROW(!a, "Attachment with invalid type queried. Given type "
207 : "is " << e.type << ", queried type is " <<
208 : attachment_info_traits<TAttachment>::type_name());
209 0 : return *a;
210 : }
211 :
212 : static
213 : const char* type_name (const std::string& name)
214 : {
215 0 : AttachmentEntry& e = attachment_entry(name);
216 0 : return e.type;
217 : }
218 :
219 : template <class TElem>
220 : static
221 0 : void read_attachment_values (std::istream& in,
222 : Grid& grid,
223 : const std::string& name)
224 : {
225 0 : AttachmentEntry& ae = attachment_entry(name);
226 0 : IFunctionEntry& fe = function_entry<TElem>(ae);
227 0 : fe.readFunc(in, grid, *ae.attachment);
228 0 : }
229 :
230 :
231 : template <class TElem>
232 : static
233 0 : void write_attachment_values (std::ostream& out,
234 : Grid& grid,
235 : const std::string& name)
236 : {
237 0 : AttachmentEntry& ae = attachment_entry(name);
238 0 : function_entry<TElem>(ae).writeFunc(out, grid, *ae.attachment);
239 0 : }
240 :
241 : template <class TElem>
242 : static
243 : void add_data_serializer(GridDataSerializationHandler& handler,
244 : Grid& grid,
245 : const std::string& name)
246 : {
247 : AttachmentEntry& ae = attachment_entry(name);
248 : IFunctionEntry& fe = function_entry<TElem>(ae);
249 : fe.addSerializer(handler, grid, *ae.attachment);
250 : }
251 :
252 :
253 : private:
254 : ////////////////////////////////////////
255 : // TYPES
256 : struct AttachmentEntry {
257 0 : AttachmentEntry () : attachment(NULL), type(""), functionIndex(-1) {}
258 : AttachmentEntry (IAttachment* a, const char* t, int fi) :
259 : attachment(a), type(t), functionIndex(fi) {}
260 : IAttachment* attachment;
261 : const char* type;
262 : int functionIndex;
263 : };
264 :
265 : struct IFunctionEntry {
266 0 : IFunctionEntry() : readFunc(0), writeFunc(0), addSerializer(0), attach(0) {}
267 : void (*readFunc ) (std::istream&, Grid&, IAttachment&);
268 : void (*writeFunc) (std::ostream&, Grid&, IAttachment&);
269 : void (*addSerializer) (GridDataSerializationHandler&, Grid&, IAttachment&);
270 : void (*attach) (Grid&, IAttachment&);
271 : };
272 :
273 : template <class TElem, class TAttachment>
274 : struct FunctionEntry : public IFunctionEntry {
275 : FunctionEntry() {
276 0 : readFunc = &read_attachment_from_stream<TElem, TAttachment>;
277 0 : writeFunc = &write_attachment_to_stream<TElem, TAttachment>;
278 0 : addSerializer = &add_attachment_serializer<TElem, TAttachment>;
279 0 : attach = &cast_and_attach<TElem, TAttachment>;
280 : }
281 : };
282 :
283 : struct IAttachmentType {
284 0 : IAttachmentType() : declareFunc(0) {}
285 : void (*declareFunc) (const std::string&, bool);
286 : };
287 :
288 : template <class TAttachment>
289 : struct AttachmentType : public IAttachmentType {
290 : AttachmentType() {
291 : declareFunc = &declare_attachment<TAttachment>;
292 : }
293 : };
294 :
295 :
296 : typedef std::map<std::string, AttachmentEntry> AttachmentMap;
297 : typedef std::map<std::string, IAttachmentType> AttachmentTypeMap;
298 : typedef std::vector<IFunctionEntry> FunctionVec;
299 :
300 :
301 : ////////////////////////////////////////
302 : // METHODS
303 : static
304 0 : GlobalAttachments& inst ()
305 : {
306 0 : static GlobalAttachments h;
307 0 : return h;
308 : }
309 :
310 0 : GlobalAttachments () {}
311 :
312 0 : ~GlobalAttachments ()
313 0 : {
314 : AttachmentMap& m = attachments();
315 0 : for(AttachmentMap::iterator i = m.begin(); i != m.end(); ++i) {
316 0 : if(i->second.attachment)
317 0 : delete i->second.attachment;
318 : }
319 0 : }
320 :
321 : static
322 : std::vector<std::string>& attachment_names() {
323 0 : return inst().m_attachmentNames;
324 : }
325 :
326 : static
327 : AttachmentMap& attachments() {
328 0 : return inst().m_attachmentMap;
329 : }
330 :
331 : static
332 0 : AttachmentTypeMap& attachment_types() {
333 : static bool initialized = false;
334 0 : if(!initialized){
335 0 : initialized = true;
336 0 : register_standard_attachment_types();
337 : }
338 0 : return inst().m_attachmentTypeMap;
339 : }
340 :
341 : template <class TElem>
342 : static
343 : FunctionVec& functions() {
344 0 : return inst().m_functionVecs[TElem::BASE_OBJECT_ID];
345 : }
346 :
347 : static
348 0 : AttachmentEntry& attachment_entry(const std::string& name)
349 : {
350 0 : AttachmentEntry& e = attachments()[name];
351 0 : UG_COND_THROW(!e.attachment, "Undeclared attachment queried: " << name);
352 0 : return e;
353 : }
354 :
355 : template <class TElem>
356 : static
357 : IFunctionEntry& function_entry(const std::string& name)
358 : {
359 : return function_entry<TElem>(attachment_entry(name));
360 : }
361 :
362 : template <class TElem>
363 : static
364 0 : IFunctionEntry& function_entry(const AttachmentEntry& ae)
365 : {
366 0 : return functions<TElem>().at(ae.functionIndex);
367 : }
368 :
369 : template <class TElem>
370 : static
371 : void remove_function_entry(const AttachmentEntry& ae) {
372 : functions<TElem>().erase(functions<TElem>().begin() + ae.functionIndex);
373 : }
374 :
375 : template <class TElem, class TAttachment>
376 : static
377 0 : void read_attachment_from_stream (
378 : std::istream& in,
379 : Grid& grid,
380 : IAttachment& attachment)
381 : {
382 0 : TAttachment& a = dynamic_cast<TAttachment&>(attachment);
383 :
384 0 : if(!grid.has_attachment<TElem>(a))
385 0 : grid.attach_to<TElem>(a);
386 :
387 : Grid::AttachmentAccessor<TElem, TAttachment> aaVal(grid, a);
388 :
389 : for(typename Grid::traits<TElem>::iterator iter = grid.begin<TElem>();
390 0 : iter != grid.end<TElem>(); ++iter)
391 : {
392 0 : attachment_io_traits<TAttachment>::read_value(in, aaVal[*iter]);
393 0 : UG_COND_THROW(!in, "Failed to read attachment entry.\n");
394 : }
395 0 : }
396 :
397 :
398 : template <class TElem, class TAttachment>
399 : static
400 0 : void write_attachment_to_stream (
401 : std::ostream& out,
402 : Grid& grid,
403 : IAttachment& attachment)
404 : {
405 0 : TAttachment& a = dynamic_cast<TAttachment&>(attachment);
406 :
407 0 : if(!grid.has_attachment<TElem>(a))
408 : return;
409 :
410 : Grid::AttachmentAccessor<TElem, TAttachment> aaVal(grid, a);
411 :
412 : const typename Grid::traits<TElem>::iterator iterEnd = grid.end<TElem>();
413 : for(typename Grid::traits<TElem>::iterator iter = grid.begin<TElem>();
414 0 : iter != iterEnd;)
415 : {
416 0 : attachment_io_traits<TAttachment>::write_value(out, aaVal[*iter]);
417 0 : UG_COND_THROW(!out, "Failed to write attachment entry.\n");
418 : ++iter;
419 0 : if(iter != iterEnd)
420 0 : out << " ";
421 : }
422 : }
423 :
424 : template <class TElem, class TAttachment>
425 : static
426 : void//SmartPtr<GeomObjDataSerializer<TElem> >
427 0 : add_attachment_serializer (
428 : GridDataSerializationHandler& handler,
429 : Grid& g,
430 : IAttachment& attachment)
431 : {
432 0 : TAttachment& a = dynamic_cast<TAttachment&>(attachment);
433 0 : handler.add(GeomObjAttachmentSerializer<TElem, TAttachment>::
434 : create(g, a));
435 0 : }
436 :
437 : template <class TElem, class TAttachment>
438 : static
439 0 : void cast_and_attach (
440 : Grid& grid,
441 : IAttachment& attachment)
442 : {
443 0 : TAttachment& a = dynamic_cast<TAttachment&>(attachment);
444 :
445 0 : if(!grid.has_attachment<TElem>(a))
446 0 : grid.attach_to<TElem>(a);
447 0 : }
448 :
449 : static
450 0 : void register_standard_attachment_types()
451 : {
452 : //todo: explicit registration of common types in
453 : // GlobalAttachments itself isn't really the best way to go
454 : // (e.g. requires inclusion of 'ugmath_types.h').
455 0 : register_attachment_type<Attachment<bool> >();
456 0 : register_attachment_type<Attachment<char> >();
457 0 : register_attachment_type<Attachment<byte> >();
458 0 : register_attachment_type<Attachment<int> >();
459 0 : register_attachment_type<Attachment<uint> >();
460 0 : register_attachment_type<Attachment<float> >();
461 0 : register_attachment_type<Attachment<double> >();
462 :
463 0 : register_attachment_type<Attachment<vector1> >();
464 0 : register_attachment_type<Attachment<vector2> >();
465 0 : register_attachment_type<Attachment<vector3> >();
466 0 : register_attachment_type<Attachment<vector4> >();
467 0 : }
468 : ////////////////////////////////////////
469 : // VARIABLES
470 : std::vector<std::string> m_attachmentNames;
471 : AttachmentMap m_attachmentMap;
472 : AttachmentTypeMap m_attachmentTypeMap;
473 : FunctionVec m_functionVecs[4];
474 : };
475 :
476 : }// end of namespace
477 :
478 : #endif //__H__UG_global_attachments
|