Loading [MathJax]/extensions/tex2jax.js
ug4
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
attachment_pipe.hpp
Go to the documentation of this file.
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"
38
39namespace ug
40{
41template <class TElem, class TElemHandler>
44 m_attachmentEntryIteratorHash(13),
45 m_numElements(0),
46 m_numDataEntries(0),
47 m_containerSize(0),
48 m_pHandler(NULL)
49{
50}
51
52template <class TElem, class TElemHandler>
54AttachmentPipe(typename atraits::ElemHandlerPtr pHandler) :
55 m_attachmentEntryIteratorHash(13),
56 m_numElements(0),
57 m_numDataEntries(0),
58 m_containerSize(0),
59 m_pHandler(pHandler)
60{
61}
62
63template <class TElem, class TElemHandler>
66{
67// clear attachment entries
68 for(AttachmentEntryIterator iter = m_attachmentEntryContainer.begin();
69 iter != m_attachmentEntryContainer.end(); iter++)
70 {
71 delete (*iter).m_pAttachment;
72 delete (*iter).m_pContainer;
73 }
74}
75
76template <class TElem, class TElemHandler>
77void
79clear()
80{
81 clear_elements();
82 clear_attachments();
83}
84
85template <class TElem, class TElemHandler>
86void
89{
90 m_stackFreeEntries = UINTStack();
91 resize_attachment_containers(0);
92 m_numElements = 0;
93 m_numDataEntries = 0;
94}
95
96template <class TElem, class TElemHandler>
97void
100{
101 m_attachmentEntryContainer.clear();
102 m_attachmentEntryIteratorHash.clear();
103}
104
105template <class TElem, class TElemHandler>
106void
108reset_values(size_t dataIndex)
109{
110 for(AttachmentEntryIterator iter = m_attachmentEntryContainer.begin();
111 iter != m_attachmentEntryContainer.end(); iter++)
112 {
113 (*iter).m_pContainer->reset_entry(dataIndex);
114 }
115}
116
117
118
119template <class TElem, class TElemHandler>
120void
122reserve(size_t numElems)
123{
124 if(numElems > get_container_size())
125 resize_attachment_containers(numElems);
126}
127
128template <class TElem, class TElemHandler>
129void
131register_element(TElem elem)
132{
133 size_t newInd;
134// check if there is a free entry
135
136 if(!m_stackFreeEntries.empty())
137 {
138 // take it
139 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 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 atraits::set_data_index(m_pHandler, elem, newInd);
155
156// increase element count
157 m_numElements++;
158}
159
160template <class TElem, class TElemHandler>
161void
163unregister_element(const TElem& elem)
164{
165// get the attachment index
166 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 m_numElements--;
171}
172
173
174template <class TElem, class TElemHandler>
175template <class TAttachment>
176void
178attach(TAttachment& attachment,
179 const typename TAttachment::ValueType& defaultValue,
180 uint options)
181{
182// make sure, that the attachment is not already attached
183 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 IAttachment* pClonedAttachment = attachment.clone();
189 IAttachmentDataContainer* pClonedContainer = attachment.create_container(defaultValue);
190 pClonedContainer->resize(get_container_size());
191 AttachmentEntryIterator iter = m_attachmentEntryContainer.
192 insert(m_attachmentEntryContainer.end(),
193 AttachmentEntry(pClonedAttachment,
194 pClonedContainer, options));
195 m_attachmentEntryIteratorHash.insert(pClonedAttachment->id(), iter);
196 }
197 else
198 {
199//TODO: do something!
200 }
201}
202
203template <class TElem, class TElemHandler>
204void
206attach(IAttachment& attachment, uint options)
207{
208// make sure, that the attachment is not already attached
209 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 IAttachment* pClonedAttachment = attachment.clone();
215 IAttachmentDataContainer* pClonedContainer = pClonedAttachment->create_container();
216 pClonedContainer->resize(get_container_size());
217 AttachmentEntryIterator iter = m_attachmentEntryContainer.insert(m_attachmentEntryContainer.end(), AttachmentEntry(pClonedAttachment, pClonedContainer, options));
218 m_attachmentEntryIteratorHash.insert(pClonedAttachment->id(), iter);
219 }
220 else
221 {
222//TODO: do something!
223 }
224}
225
226template <class TElem, class TElemHandler>
227void
229detach(IAttachment& attachment)
230{
231 if(has_attachment(attachment))
232 {
233 AttachmentEntryIterator iter = m_attachmentEntryIteratorHash.get_entry(attachment.id());
234 delete ((*iter).m_pAttachment);
235 ((*iter).m_pAttachment) = NULL;
236 delete((*iter).m_pContainer);
237 ((*iter).m_pContainer) = NULL;
238 m_attachmentEntryContainer.erase(iter);
239 m_attachmentEntryIteratorHash.erase(attachment.id());
240 }
241}
242
243template <class TElem, class TElemHandler>
244bool
246has_attachment(IAttachment& attachment) const
247{
248 return m_attachmentEntryIteratorHash.has_entry(attachment.id());
249}
250
251
252template <class TElem, class TElemHandler>
253template <class TAttachment>
254typename TAttachment::ValueType*
256get_data_array(TAttachment& attachment)
257{
258 if(has_attachment(attachment))
259 return get_data_container(attachment)->get_ptr();
260
261 return NULL;
262}
263
264template <class TElem, class TElemHandler>
267get_data_container(IAttachment& attachment) const
268{
270 if(m_attachmentEntryIteratorHash.get_entry(iter, attachment.id()))
271 return iter->m_pContainer;
272 return NULL;
273}
274
275template <class TElem, class TElemHandler>
276template <class TAttachment>
277typename TAttachment::ContainerType*
279get_data_container(TAttachment& attachment)
280{
282 if(m_attachmentEntryIteratorHash.get_entry(iter, attachment.id()))
283 return static_cast<typename TAttachment::ContainerType*>(iter->m_pContainer);
284 return NULL;
285}
286
287template <class TElem, class TElemHandler>
288void
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/*
339template <class TElem, class TElemHandler>
340void
341AttachmentPipe<TElem, TElemHandler>::
342defragment()
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)
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);
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;
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());
392 }
393 }
394}
395*/
396template <class TElem, class TElemHandler>
397void
399resize_attachment_containers(size_t newSize)
400{
401//UG_LOG("resizing attachment containers\n");
402 //PROFILE_BEGIN(AttachmentResize);
403 m_containerSize = newSize;
404 for(AttachmentEntryIterator iter = m_attachmentEntryContainer.begin();
405 iter != m_attachmentEntryContainer.end(); iter++)
406 {
407 (*iter).m_pContainer->resize(newSize);
409 //PROFILE_END();
410//UG_LOG("done\n");
411}
413template <class TElem, class TElemHandler>
414void
417{
418 //if(!m_attachmentEntryContainer.empty())
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 if(actSize < newMinSize)
425 {
426 size_t newSize = actSize * 2;
427 if(newSize < newMinSize)
428 newSize = newMinSize;
429
430 resize_attachment_containers(newSize);
431 }
432 }
433}
434
435template <class TElem, class TElemHandler>
436size_t
439{
440 return m_containerSize;
441}
442
445// AttachmentAccessor
446template <class TElem, class TAttachment, class TElemHandler>
448AttachmentAccessor() : m_pContainer(NULL), m_pHandler(NULL)
449{
450}
451
452template <class TElem, class TAttachment, class TElemHandler>
459
460template <class TElem, class TAttachment, class TElemHandler>
463{
464 m_pContainer = static_cast<typename TAttachment::ContainerType*>(attachmentPipe.get_data_container(attachment));
465 m_pHandler = attachmentPipe.get_elem_handler();
466 assert(m_pContainer && "ERROR in AttachmentAccessor::AttachmentAccessor(attachmentPipe, attachment): attachment not attached to attachmentPipe!");
467}
468
469template <class TElem, class TAttachment, class TElemHandler>
470bool
472access(AttachmentPipe<TElem, TElemHandler>& attachmentPipe, TAttachment& attachment)
473{
474 if(!attachmentPipe.has_attachment(attachment))
475 return false;
476
477 m_pContainer = static_cast<typename TAttachment::ContainerType*>(attachmentPipe.get_data_container(attachment));
478 m_pHandler = attachmentPipe.get_elem_handler();
479 assert(m_pContainer && "ERROR in AttachmentAccessor::access(attachmentPipe, attachment): attachment not attached to attachmentPipe!");
480
481 return true;
482}
483
484}// end of namespace
485
486#endif
Used to access data that has been attached to an attachment pipe.
Definition attachment_pipe.h:510
TElemHandler * m_pHandler
Definition attachment_pipe.h:588
bool access(attachment_pipe &attachmentPipe, TAttachment &attachment)
Definition attachment_pipe.hpp:472
ContainerType * m_pContainer
Definition attachment_pipe.h:587
TAttachment attachment
Definition attachment_pipe.h:512
AttachmentAccessor()
Definition attachment_pipe.hpp:448
Handles data which has been attached to the pipe using callbacks for the element.
Definition attachment_pipe.h:337
size_t get_container_size()
Definition attachment_pipe.hpp:438
void attach(TAttachment &attachment, const typename TAttachment::ValueType &defaultValue, uint options)
attaches a new data-array to the pipe.
Definition attachment_pipe.hpp:178
void resize_attachment_containers(size_t newSize)
Definition attachment_pipe.hpp:399
void reset_values(size_t dataIndex)
fills the attached data at the given index with the default values.
Definition attachment_pipe.hpp:108
TAttachment::ValueType * get_data_array(TAttachment &attachment)
Lets you access the raw data array associated with the given attachment.
Definition attachment_pipe.hpp:256
std::stack< size_t > UINTStack
Definition attachment_pipe.h:474
void clear_elements()
clears elements and associated data but keeps registered attachments
Definition attachment_pipe.hpp:88
void grow_attachment_containers(size_t newMinSize)
Definition attachment_pipe.hpp:416
void reserve(size_t numElems)
Reserves memory for element- and data-entries.
Definition attachment_pipe.hpp:122
void clear()
calls both clear_elements and clear_attachments.
Definition attachment_pipe.hpp:79
void register_element(TElem elem)
Registers a new element at the attachment pipe.
Definition attachment_pipe.hpp:131
void clear_attachments()
clears registered attachments and associated data but keeps existing elements.
Definition attachment_pipe.hpp:99
void detach(IAttachment &attachment)
Removes the data associated with the given attachment from the pipe.
Definition attachment_pipe.hpp:229
AttachmentPipe()
Definition attachment_pipe.hpp:43
void defragment()
Definition attachment_pipe.hpp:290
AttachmentEntryContainer::iterator AttachmentEntryIterator
Definition attachment_pipe.h:342
~AttachmentPipe()
Definition attachment_pipe.hpp:65
IAttachmentDataContainer * get_data_container(IAttachment &attachment) const
Returns the data container managing the data array for the given attachment.
Definition attachment_pipe.hpp:267
bool has_attachment(IAttachment &attachment) const
Returns true if the given attachment is currently attached to the pipe.
Definition attachment_pipe.hpp:246
void unregister_element(const TElem &elem)
Unregisters the given element.
Definition attachment_pipe.hpp:163
atraits::ElemHandlerPtr get_elem_handler()
Definition attachment_pipe.h:352
the interface for an attachment-data-container.
Definition attachment_pipe.h:72
virtual void resize(size_t iSize)=0
resize the data array
the interface for attachments.
Definition attachment_pipe.h:239
virtual IAttachment * clone()=0
virtual IAttachmentDataContainer * create_container()=0
unsigned int id() const
Definition uid.h:60
void element_iterator
Definition attachment_pipe.h:313
void * ElemHandlerPtr
Definition attachment_pipe.h:310
unsigned int uint
Definition types.h:114
the ug namespace
@ INVALID_ATTACHMENT_INDEX
Definition attachment_pipe.h:58
This struct is used by AttachmentPipe in order to manage its attachments.
Definition attachment_pipe.h:287