Line data Source code
1 : /*
2 : * Copyright (c) 2009-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 __UTIL__ATTACHMENT_PIPE__IMPL__
34 : #define __UTIL__ATTACHMENT_PIPE__IMPL__
35 :
36 : #include "attachment_pipe.h"
37 : #include "common/profiler/profiler.h"
38 :
39 : namespace ug
40 : {
41 : template <class TElem, class TElemHandler>
42 : AttachmentPipe<TElem, TElemHandler>::
43 : AttachmentPipe() :
44 : m_attachmentEntryIteratorHash(13),
45 : m_numElements(0),
46 : m_numDataEntries(0),
47 : m_containerSize(0),
48 : m_pHandler(NULL)
49 : {
50 : }
51 :
52 : template <class TElem, class TElemHandler>
53 4 : AttachmentPipe<TElem, TElemHandler>::
54 : AttachmentPipe(typename atraits::ElemHandlerPtr pHandler) :
55 4 : m_attachmentEntryIteratorHash(13),
56 4 : m_numElements(0),
57 4 : m_numDataEntries(0),
58 4 : m_containerSize(0),
59 4 : m_pHandler(pHandler)
60 : {
61 4 : }
62 :
63 : template <class TElem, class TElemHandler>
64 4 : AttachmentPipe<TElem, TElemHandler>::
65 : ~AttachmentPipe()
66 : {
67 : // clear attachment entries
68 4 : for(AttachmentEntryIterator iter = m_attachmentEntryContainer.begin();
69 8 : iter != m_attachmentEntryContainer.end(); iter++)
70 : {
71 4 : delete (*iter).m_pAttachment;
72 4 : delete (*iter).m_pContainer;
73 : }
74 4 : }
75 :
76 : template <class TElem, class TElemHandler>
77 : void
78 : AttachmentPipe<TElem, TElemHandler>::
79 : clear()
80 : {
81 : clear_elements();
82 : clear_attachments();
83 : }
84 :
85 : template <class TElem, class TElemHandler>
86 : void
87 : AttachmentPipe<TElem, TElemHandler>::
88 : clear_elements()
89 : {
90 : m_stackFreeEntries = UINTStack();
91 : resize_attachment_containers(0);
92 : m_numElements = 0;
93 : m_numDataEntries = 0;
94 : }
95 :
96 : template <class TElem, class TElemHandler>
97 : void
98 : AttachmentPipe<TElem, TElemHandler>::
99 : clear_attachments()
100 : {
101 : m_attachmentEntryContainer.clear();
102 : m_attachmentEntryIteratorHash.clear();
103 : }
104 :
105 : template <class TElem, class TElemHandler>
106 : void
107 : AttachmentPipe<TElem, TElemHandler>::
108 : reset_values(size_t dataIndex)
109 : {
110 0 : for(AttachmentEntryIterator iter = m_attachmentEntryContainer.begin();
111 0 : iter != m_attachmentEntryContainer.end(); iter++)
112 : {
113 0 : (*iter).m_pContainer->reset_entry(dataIndex);
114 : }
115 : }
116 :
117 :
118 :
119 : template <class TElem, class TElemHandler>
120 : void
121 : AttachmentPipe<TElem, TElemHandler>::
122 : reserve(size_t numElems)
123 : {
124 0 : if(numElems > get_container_size())
125 : resize_attachment_containers(numElems);
126 : }
127 :
128 : template <class TElem, class TElemHandler>
129 : void
130 7 : AttachmentPipe<TElem, TElemHandler>::
131 : register_element(TElem elem)
132 : {
133 : size_t newInd;
134 : // check if there is a free entry
135 :
136 7 : if(!m_stackFreeEntries.empty())
137 : {
138 : // take it
139 0 : newInd = m_stackFreeEntries.top();
140 : m_stackFreeEntries.pop();
141 :
142 : // initialize attachments with default constructor
143 : reset_values(newInd);
144 : }
145 : else
146 : {
147 : // add a new entry
148 7 : newInd = m_numDataEntries++;
149 : // make sure that the data containers are big enough.
150 : grow_attachment_containers(m_numDataEntries);
151 : }
152 :
153 : // assign new attachment index to the element
154 7 : atraits::set_data_index(m_pHandler, elem, newInd);
155 :
156 : // increase element count
157 7 : m_numElements++;
158 7 : }
159 :
160 : template <class TElem, class TElemHandler>
161 : void
162 7 : AttachmentPipe<TElem, TElemHandler>::
163 : unregister_element(const TElem& elem)
164 : {
165 : // get the attachment index
166 7 : size_t ind = atraits::get_data_index(m_pHandler, elem);
167 : // store the index in the stack of free entries
168 : m_stackFreeEntries.push(ind);
169 : // decrease element count
170 7 : m_numElements--;
171 7 : }
172 :
173 :
174 : template <class TElem, class TElemHandler>
175 : template <class TAttachment>
176 : void
177 0 : AttachmentPipe<TElem, TElemHandler>::
178 : attach(TAttachment& attachment,
179 : const typename TAttachment::ValueType& defaultValue,
180 : uint options)
181 : {
182 : // make sure, that the attachment is not already attached
183 0 : if(!has_attachment(attachment))
184 : {
185 : // create a new element and insert it into the entryContainer.
186 : // resize the new data-container to the size of the element container.
187 : // store the returned iterator in the iteratorHash to allow fast access.
188 0 : IAttachment* pClonedAttachment = attachment.clone();
189 0 : IAttachmentDataContainer* pClonedContainer = attachment.create_container(defaultValue);
190 0 : pClonedContainer->resize(get_container_size());
191 : AttachmentEntryIterator iter = m_attachmentEntryContainer.
192 0 : insert(m_attachmentEntryContainer.end(),
193 0 : AttachmentEntry(pClonedAttachment,
194 : pClonedContainer, options));
195 0 : m_attachmentEntryIteratorHash.insert(pClonedAttachment->id(), iter);
196 : }
197 : else
198 : {
199 : //TODO: do something!
200 : }
201 0 : }
202 :
203 : template <class TElem, class TElemHandler>
204 : void
205 11 : AttachmentPipe<TElem, TElemHandler>::
206 : attach(IAttachment& attachment, uint options)
207 : {
208 : // make sure, that the attachment is not already attached
209 11 : if(!has_attachment(attachment))
210 : {
211 : // create a new element and insert it into the entryContainer.
212 : // resize the new data-container to the size of the element container.
213 : // store the returned iterator in the iteratorHash to allow fast access.
214 11 : IAttachment* pClonedAttachment = attachment.clone();
215 11 : IAttachmentDataContainer* pClonedContainer = pClonedAttachment->create_container();
216 11 : pClonedContainer->resize(get_container_size());
217 11 : AttachmentEntryIterator iter = m_attachmentEntryContainer.insert(m_attachmentEntryContainer.end(), AttachmentEntry(pClonedAttachment, pClonedContainer, options));
218 11 : m_attachmentEntryIteratorHash.insert(pClonedAttachment->id(), iter);
219 : }
220 : else
221 : {
222 : //TODO: do something!
223 : }
224 11 : }
225 :
226 : template <class TElem, class TElemHandler>
227 : void
228 7 : AttachmentPipe<TElem, TElemHandler>::
229 : detach(IAttachment& attachment)
230 : {
231 7 : if(has_attachment(attachment))
232 : {
233 7 : AttachmentEntryIterator iter = m_attachmentEntryIteratorHash.get_entry(attachment.id());
234 7 : delete ((*iter).m_pAttachment);
235 7 : ((*iter).m_pAttachment) = NULL;
236 7 : delete((*iter).m_pContainer);
237 7 : ((*iter).m_pContainer) = NULL;
238 7 : m_attachmentEntryContainer.erase(iter);
239 7 : m_attachmentEntryIteratorHash.erase(attachment.id());
240 : }
241 7 : }
242 :
243 : template <class TElem, class TElemHandler>
244 : bool
245 : AttachmentPipe<TElem, TElemHandler>::
246 : has_attachment(IAttachment& attachment) const
247 : {
248 : return m_attachmentEntryIteratorHash.has_entry(attachment.id());
249 : }
250 :
251 :
252 : template <class TElem, class TElemHandler>
253 : template <class TAttachment>
254 : typename TAttachment::ValueType*
255 : AttachmentPipe<TElem, TElemHandler>::
256 : get_data_array(TAttachment& attachment)
257 : {
258 : if(has_attachment(attachment))
259 : return get_data_container(attachment)->get_ptr();
260 :
261 : return NULL;
262 : }
263 :
264 : template <class TElem, class TElemHandler>
265 : IAttachmentDataContainer*
266 0 : AttachmentPipe<TElem, TElemHandler>::
267 : get_data_container(IAttachment& attachment) const
268 : {
269 : AttachmentEntryIterator iter;
270 0 : if(m_attachmentEntryIteratorHash.get_entry(iter, attachment.id()))
271 0 : return iter->m_pContainer;
272 : return NULL;
273 : }
274 :
275 : template <class TElem, class TElemHandler>
276 : template <class TAttachment>
277 : typename TAttachment::ContainerType*
278 11 : AttachmentPipe<TElem, TElemHandler>::
279 : get_data_container(TAttachment& attachment)
280 : {
281 : AttachmentEntryIterator iter;
282 11 : if(m_attachmentEntryIteratorHash.get_entry(iter, attachment.id()))
283 11 : return static_cast<typename TAttachment::ContainerType*>(iter->m_pContainer);
284 : return NULL;
285 : }
286 :
287 : template <class TElem, class TElemHandler>
288 : void
289 : AttachmentPipe<TElem, TElemHandler>::
290 : defragment()
291 : {
292 : if(!is_fragmented())
293 : return;
294 :
295 : // if num_elements == 0, then simply resize all data-containers to 0.
296 : if(num_elements() == 0)
297 : {
298 : // just clear the attachment containers.
299 : for(AttachmentEntryIterator iter = m_attachmentEntryContainer.begin();
300 : iter != m_attachmentEntryContainer.end(); iter++)
301 : {
302 : (*iter).m_pContainer->resize(0);
303 : }
304 : m_stackFreeEntries = UINTStack();
305 : m_numDataEntries = 0;
306 : }
307 : else
308 : {
309 : // calculate the fragmentation array. It has to be of the same size as the fragmented data containers.
310 : std::vector<uint> vNewIndices(num_data_entries(), INVALID_ATTACHMENT_INDEX);
311 :
312 : // iterate through the elements and calculate the new index of each
313 : size_t counter = 0;
314 : typename atraits::element_iterator iter = atraits::elements_begin(m_pHandler);
315 : typename atraits::element_iterator end = atraits::elements_end(m_pHandler);
316 :
317 : for(; iter != end; ++iter){
318 : vNewIndices[atraits::get_data_index(m_pHandler, (*iter))] = counter;
319 : atraits::set_data_index(m_pHandler, (*iter), counter);
320 : ++counter;
321 : }
322 :
323 : // after defragmentation there are no free indices.
324 : m_stackFreeEntries = UINTStack();
325 : m_numDataEntries = counter;
326 :
327 : // now iterate through the attached data-containers and defragment each one.
328 : {
329 : for(AttachmentEntryIterator iter = m_attachmentEntryContainer.begin();
330 : iter != m_attachmentEntryContainer.end(); iter++)
331 : {
332 : (*iter).m_pContainer->defragment(&vNewIndices.front(), num_elements());
333 : }
334 : }
335 : }
336 : }
337 :
338 : /*
339 : template <class TElem, class TElemHandler>
340 : void
341 : AttachmentPipe<TElem, TElemHandler>::
342 : defragment()
343 : {
344 : if(!is_fragmented())
345 : return;
346 :
347 : // if num_elements == 0, then simply resize all data-containers to 0.
348 : if(num_elements() == 0)
349 : {
350 : // just clear the attachment containers.
351 : for(AttachmentEntryIterator iter = m_attachmentEntryContainer.begin();
352 : iter != m_attachmentEntryContainer.end(); iter++)
353 : {
354 : (*iter).m_pContainer->resize(0);
355 : }
356 : }
357 : else
358 : {
359 : // calculate the fragmentation array. It has to be of the same size as the fragmented data containers.
360 : std::vector<uint> vNewIndices(num_data_entries(), INVALID_ATTACHMENT_INDEX);
361 :
362 : // iterate through the elements and calculate the new index of each
363 : size_t counter = 0;
364 : {
365 : typename ElemEntryVec::iterator iter;
366 : typename ElemEntryVec::iterator copyHere = m_vEntries.begin();
367 : for(iter = m_vEntries.begin(); iter != m_vEntries.end(); ++iter)
368 : {
369 : if(!atraits::entry_is_invalid(*iter))
370 : {
371 : vNewIndices[atraits::get_data_index(m_pHandler, (*iter))] = counter;
372 : atraits::set_data_index(m_pHandler, (*iter), counter);
373 : ++counter;
374 :
375 : // copy entries
376 : *copyHere = *iter;
377 : ++copyHere;
378 : }
379 : }
380 :
381 : // resize m_vEntries
382 : m_vEntries.resize(counter);
383 : }
384 :
385 : // now iterate through the attached data-containers and defragment each one.
386 : {
387 : for(AttachmentEntryIterator iter = m_attachmentEntryContainer.begin();
388 : iter != m_attachmentEntryContainer.end(); iter++)
389 : {
390 : (*iter).m_pContainer->defragment(&vNewIndices.front(), num_elements());
391 : }
392 : }
393 : }
394 : }
395 : */
396 : template <class TElem, class TElemHandler>
397 : void
398 : AttachmentPipe<TElem, TElemHandler>::
399 : resize_attachment_containers(size_t newSize)
400 : {
401 : //UG_LOG("resizing attachment containers\n");
402 : //PROFILE_BEGIN(AttachmentResize);
403 7 : m_containerSize = newSize;
404 7 : for(AttachmentEntryIterator iter = m_attachmentEntryContainer.begin();
405 23 : iter != m_attachmentEntryContainer.end(); iter++)
406 : {
407 16 : (*iter).m_pContainer->resize(newSize);
408 : }
409 : //PROFILE_END();
410 : //UG_LOG("done\n");
411 : }
412 :
413 : template <class TElem, class TElemHandler>
414 : void
415 : AttachmentPipe<TElem, TElemHandler>::
416 : grow_attachment_containers(size_t newMinSize)
417 : {
418 : //if(!m_attachmentEntryContainer.empty())
419 : {
420 : // if the container-size is smaller than newMinSize, we will increase it
421 : // by a factor of 2 (at least)
422 : size_t actSize = get_container_size();
423 :
424 7 : if(actSize < newMinSize)
425 : {
426 7 : size_t newSize = actSize * 2;
427 7 : if(newSize < newMinSize)
428 : newSize = newMinSize;
429 :
430 : resize_attachment_containers(newSize);
431 : }
432 : }
433 : }
434 :
435 : template <class TElem, class TElemHandler>
436 : size_t
437 : AttachmentPipe<TElem, TElemHandler>::
438 : get_container_size()
439 : {
440 18 : return m_containerSize;
441 : }
442 :
443 : ////////////////////////////////////////////////////////////////////////
444 : ////////////////////////////////////////////////////////////////////////
445 : // AttachmentAccessor
446 : template <class TElem, class TAttachment, class TElemHandler>
447 5 : AttachmentAccessor<TElem, TAttachment, TElemHandler>::
448 12 : AttachmentAccessor() : m_pContainer(NULL), m_pHandler(NULL)
449 : {
450 : }
451 :
452 : template <class TElem, class TAttachment, class TElemHandler>
453 3 : AttachmentAccessor<TElem, TAttachment, TElemHandler>::
454 : AttachmentAccessor(const AttachmentAccessor& aa)
455 : {
456 14 : m_pContainer = aa.m_pContainer;
457 35 : m_pHandler = aa.m_pHandler;
458 : }
459 :
460 : template <class TElem, class TAttachment, class TElemHandler>
461 0 : AttachmentAccessor<TElem, TAttachment, TElemHandler>::
462 : AttachmentAccessor(AttachmentPipe<TElem, TElemHandler>& attachmentPipe, TAttachment& attachment)
463 : {
464 1 : m_pContainer = static_cast<typename TAttachment::ContainerType*>(attachmentPipe.get_data_container(attachment));
465 0 : m_pHandler = attachmentPipe.get_elem_handler();
466 : assert(m_pContainer && "ERROR in AttachmentAccessor::AttachmentAccessor(attachmentPipe, attachment): attachment not attached to attachmentPipe!");
467 : }
468 :
469 : template <class TElem, class TAttachment, class TElemHandler>
470 : bool
471 10 : AttachmentAccessor<TElem, TAttachment, TElemHandler>::
472 : access(AttachmentPipe<TElem, TElemHandler>& attachmentPipe, TAttachment& attachment)
473 : {
474 10 : if(!attachmentPipe.has_attachment(attachment))
475 : return false;
476 :
477 10 : m_pContainer = static_cast<typename TAttachment::ContainerType*>(attachmentPipe.get_data_container(attachment));
478 10 : m_pHandler = attachmentPipe.get_elem_handler();
479 : assert(m_pContainer && "ERROR in AttachmentAccessor::access(attachmentPipe, attachment): attachment not attached to attachmentPipe!");
480 :
481 10 : return true;
482 : }
483 :
484 : }// end of namespace
485 :
486 : #endif
|