Dune Core Modules (2.8.0)

vbvector.hh
Go to the documentation of this file.
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3#ifndef DUNE_ISTL_VBVECTOR_HH
4#define DUNE_ISTL_VBVECTOR_HH
5
6#include <cmath>
7#include <complex>
8#include <iostream>
9#include <iterator>
10#include <memory>
11
13#include "istlexception.hh"
14#include "bvector.hh"
15
17
22namespace Dune {
23
39 template<class B, class A=std::allocator<B> >
40 class VariableBlockVector : public Imp::block_vector_unmanaged<B,A>
41 // this derivation gives us all the blas level 1 and norms
42 // on the large array. However, access operators have to be
43 // overwritten.
44 {
45 // just a shorthand
46 typedef Imp::BlockVectorWindow<B,A> window_type;
47
48 public:
49
50 //===== type definitions and constants
51
53 using field_type = typename Imp::BlockTraits<B>::field_type;
54
56 typedef A allocator_type;
57
62 typedef window_type& reference;
63
68 typedef const window_type& const_reference;
69
71 typedef typename A::size_type size_type;
72
79
83
87 [[deprecated("Use free function blockLevel(). Will be removed after 2.8.")]]
88 static constexpr auto blocklevel = blockLevel<B>()+2;
89
90 //===== constructors and such
91
95 VariableBlockVector () : Imp::block_vector_unmanaged<B,A>()
96 {
97 // nothing is known ...
98 nblocks = 0;
99 block = nullptr;
100 initialized = false;
101 }
102
106 explicit VariableBlockVector (size_type _nblocks) : Imp::block_vector_unmanaged<B,A>()
107 {
108 // we can allocate the windows now
109 nblocks = _nblocks;
110 if (nblocks>0)
111 {
112 block = windowAllocator_.allocate(nblocks);
113 new (block) window_type[nblocks];
114 }
115 else
116 {
117 nblocks = 0;
118 block = nullptr;
119 }
120
121 // Note: memory in base class still not allocated
122 // the vector not usable
123 initialized = false;
124 }
125
132 VariableBlockVector (size_type _nblocks, size_type m) : Imp::block_vector_unmanaged<B,A>()
133 {
134 // and we can allocate the big array in the base class
135 this->n = _nblocks*m;
136 if (this->n>0)
137 {
138 this->p = allocator_.allocate(this->n);
139 new (this->p)B[this->n];
140 }
141 else
142 {
143 this->n = 0;
144 this->p = nullptr;
145 }
146
147 // we can allocate the windows now
148 nblocks = _nblocks;
149 if (nblocks>0)
150 {
151 // allocate and construct the windows
152 block = windowAllocator_.allocate(nblocks);
153 new (block) window_type[nblocks];
154
155 // set the windows into the big array
156 for (size_type i=0; i<nblocks; ++i)
157 block[i].set(m,this->p+(i*m));
158 }
159 else
160 {
161 nblocks = 0;
162 block = nullptr;
163 }
164
165 // and the vector is usable
166 initialized = true;
167 }
168
171 {
172 // allocate the big array in the base class
173 this->n = a.n;
174 if (this->n>0)
175 {
176 // allocate and construct objects
177 this->p = allocator_.allocate(this->n);
178 new (this->p)B[this->n];
179
180 // copy data
181 for (size_type i=0; i<this->n; i++) this->p[i]=a.p[i];
182 }
183 else
184 {
185 this->n = 0;
186 this->p = nullptr;
187 }
188
189 // we can allocate the windows now
190 nblocks = a.nblocks;
191 if (nblocks>0)
192 {
193 // alloc
194 block = windowAllocator_.allocate(nblocks);
195 new (block) window_type[nblocks];
196
197 // and we must set the windows
198 block[0].set(a.block[0].getsize(),this->p); // first block
199 for (size_type i=1; i<nblocks; ++i) // and the rest
200 block[i].set(a.block[i].getsize(),block[i-1].getptr()+block[i-1].getsize());
201 }
202 else
203 {
204 nblocks = 0;
205 block = nullptr;
206 }
207
208 // and we have a usable vector
209 initialized = true;
210 }
211
214 {
215 if (this->n>0) {
216 size_type i=this->n;
217 while (i)
218 this->p[--i].~B();
219 allocator_.deallocate(this->p,this->n);
220 }
221 if (nblocks>0) {
222 size_type i=nblocks;
223 while (i)
224 block[--i].~window_type();
225 windowAllocator_.deallocate(block,nblocks);
226 }
227
228 }
229
230
232 void resize (size_type _nblocks)
233 {
234 // deconstruct objects and deallocate memory if necessary
235 if (this->n>0) {
236 size_type i=this->n;
237 while (i)
238 this->p[--i].~B();
239 allocator_.deallocate(this->p,this->n);
240 }
241 if (nblocks>0) {
242 size_type i=nblocks;
243 while (i)
244 block[--i].~window_type();
245 windowAllocator_.deallocate(block,nblocks);
246 }
247 this->n = 0;
248 this->p = nullptr;
249
250 // we can allocate the windows now
251 nblocks = _nblocks;
252 if (nblocks>0)
253 {
254 block = windowAllocator_.allocate(nblocks);
255 new (block) window_type[nblocks];
256 }
257 else
258 {
259 nblocks = 0;
260 block = nullptr;
261 }
262
263 // and the vector not fully usable
264 initialized = false;
265 }
266
268 void resize (size_type _nblocks, size_type m)
269 {
270 // deconstruct objects and deallocate memory if necessary
271 if (this->n>0) {
272 size_type i=this->n;
273 while (i)
274 this->p[--i].~B();
275 allocator_.deallocate(this->p,this->n);
276 }
277 if (nblocks>0) {
278 size_type i=nblocks;
279 while (i)
280 block[--i].~window_type();
281 windowAllocator_.deallocate(block,nblocks);
282 }
283
284 // and we can allocate the big array in the base class
285 this->n = _nblocks*m;
286 if (this->n>0)
287 {
288 this->p = allocator_.allocate(this->n);
289 new (this->p)B[this->n];
290 }
291 else
292 {
293 this->n = 0;
294 this->p = nullptr;
295 }
296
297 // we can allocate the windows now
298 nblocks = _nblocks;
299 if (nblocks>0)
300 {
301 // allocate and construct objects
302 block = windowAllocator_.allocate(nblocks);
303 new (block) window_type[nblocks];
304
305 // set the windows into the big array
306 for (size_type i=0; i<nblocks; ++i)
307 block[i].set(m,this->p+(i*m));
308 }
309 else
310 {
311 nblocks = 0;
312 block = nullptr;
313 }
314
315 // and the vector is usable
316 initialized = true;
317 }
318
321 {
322 if (&a!=this) // check if this and a are different objects
323 {
324 // reallocate arrays if necessary
325 // Note: still the block sizes may vary !
326 if (this->n!=a.n || nblocks!=a.nblocks)
327 {
328 // deconstruct objects and deallocate memory if necessary
329 if (this->n>0) {
330 size_type i=this->n;
331 while (i)
332 this->p[--i].~B();
333 allocator_.deallocate(this->p,this->n);
334 }
335 if (nblocks>0) {
336 size_type i=nblocks;
337 while (i)
338 block[--i].~window_type();
339 windowAllocator_.deallocate(block,nblocks);
340 }
341
342 // allocate the big array in the base class
343 this->n = a.n;
344 if (this->n>0)
345 {
346 // allocate and construct objects
347 this->p = allocator_.allocate(this->n);
348 new (this->p)B[this->n];
349 }
350 else
351 {
352 this->n = 0;
353 this->p = nullptr;
354 }
355
356 // we can allocate the windows now
357 nblocks = a.nblocks;
358 if (nblocks>0)
359 {
360 // alloc
361 block = windowAllocator_.allocate(nblocks);
362 new (block) window_type[nblocks];
363 }
364 else
365 {
366 nblocks = 0;
367 block = nullptr;
368 }
369 }
370
371 // copy block structure, might be different although
372 // sizes are the same !
373 if (nblocks>0)
374 {
375 block[0].set(a.block[0].getsize(),this->p); // first block
376 for (size_type i=1; i<nblocks; ++i) // and the rest
377 block[i].set(a.block[i].getsize(),block[i-1].getptr()+block[i-1].getsize());
378 }
379
380 // and copy the data
381 for (size_type i=0; i<this->n; i++) this->p[i]=a.p[i];
382 }
383
384 // and we have a usable vector
385 initialized = true;
386
387 return *this; // Gebe Referenz zurueck damit a=b=c; klappt
388 }
389
390
391 //===== assignment from scalar
392
395 {
396 (static_cast<Imp::block_vector_unmanaged<B,A>&>(*this)) = k;
397 return *this;
398 }
399
400
401 //===== the creation interface
402
403 class CreateIterator;
404
405#ifndef DOXYGEN
406
407 // The window_type does not hand out a reference to its size,
408 // so in order to provide a valid iterator, we need a workaround
409 // to make assignment possible. This proxy enables just that by
410 // implicitly converting to the stored size for read access and
411 // tunneling assignment to the accessor method of the window.
412 struct SizeProxy
413 {
414
415 operator size_type() const
416 {
417 return target->getsize();
418 }
419
420 SizeProxy& operator=(size_type size)
421 {
422 target->setsize(size);
423 return *this;
424 }
425
426 private:
427
428 friend class CreateIterator;
429
430 SizeProxy(window_type& t)
431 : target(&t)
432 {}
433
434 window_type* target;
435 };
436
437#endif // DOXYGEN
438
441 {
442 public:
444 using iterator_category = std::output_iterator_tag;
445
448
455 using difference_type = void;
456
459
461 using reference = SizeProxy;
462
464 CreateIterator (VariableBlockVector& _v, int _i, bool _isEnd) :
465 v(_v),
466 i(_i),
467 isEnd(_isEnd) {}
468
470 // When the iterator gets destructed, we allocate the memory
471 // for the VariableBlockVector if
472 // 1. the current iterator was not created as enditerator
473 // 2. we're at the last block
474 // 3. the vector hasn't been initialized earlier
475 if (not isEnd && i==v.nblocks && not v.initialized)
476 v.allocate();
477 }
478
481 {
482 // go to next block
483 ++i;
484
485 return *this;
486 }
487
490 {
491 CreateIterator tmp(*this);
492 this->operator++();
493 return tmp;
494 }
495
497 bool operator!= (const CreateIterator& it) const
498 {
499 return (i!=it.i) || (&v!=&it.v);
500 }
501
503 bool operator== (const CreateIterator& it) const
504 {
505 return (i==it.i) && (&v==&it.v);
506 }
507
510 {
511 return i;
512 }
513
516 {
517 v.block[i].setsize(_k);
518 }
519
521#ifdef DOXYGEN
522 size_type&
523#else
524 SizeProxy
525#endif
527 {
528 return {v.block[i]};
529 }
530
531 private:
532 VariableBlockVector& v; // my vector
533 size_type i; // current block to be defined
534 const bool isEnd; // flag if this object was created as the end iterator.
535 };
536
537 // CreateIterator wants to set all the arrays ...
538 friend class CreateIterator;
539
542 {
543#ifdef DUNE_ISTL_WITH_CHECKING
544 if (initialized) DUNE_THROW(ISTLError,"no CreateIterator in initialized state");
545#endif
546 return CreateIterator(*this,0, false);
547 }
548
551 {
552 return CreateIterator(*this,nblocks, true);
553 }
554
555
556 //===== access to components
557 // has to be overwritten from base class because it must
558 // return access to the windows
559
561 window_type& operator[] (size_type i)
562 {
563#ifdef DUNE_ISTL_WITH_CHECKING
564 if (i>=nblocks) DUNE_THROW(ISTLError,"index out of range");
565#endif
566 return block[i];
567 }
568
570 const window_type& operator[] (size_type i) const
571 {
572#ifdef DUNE_ISTL_WITH_CHECKING
573 if (i<0 || i>=nblocks) DUNE_THROW(ISTLError,"index out of range");
574#endif
575 return block[i];
576 }
577
579 template <class T, class R>
581 : public RandomAccessIteratorFacade<RealIterator<T,R>, T, R>
582 {
583 public:
586 {
587 p = nullptr;
588 i = 0;
589 }
590
592 RealIterator (window_type* _p, size_type _i)
593 : p(_p), i(_i)
594 {}
595
598 {
599 ++i;
600 }
601
604 {
605 --i;
606 }
607
609 bool equals (const RealIterator& it) const
610 {
611 return (p+i)==(it.p+it.i);
612 }
613
615 window_type& dereference () const
616 {
617 return p[i];
618 }
619
620 void advance(std::ptrdiff_t d)
621 {
622 i+=d;
623 }
624
625 std::ptrdiff_t distanceTo(const RealIterator& o) const
626 {
627 return o.i-i;
628 }
629
630 // Needed for operator[] of the iterator
631 window_type& elementAt (std::ptrdiff_t offset) const
632 {
633 return p[i+offset];
634 }
635
638 {
639 return i;
640 }
641
642 private:
643 window_type* p;
644 size_type i;
645 };
646
647 using Iterator = RealIterator<value_type,window_type&>;
648
651 {
652 return Iterator(block,0);
653 }
654
657 {
658 return Iterator(block,nblocks);
659 }
660
664 {
665 return Iterator(block,nblocks-1);
666 }
667
671 {
672 return Iterator(block,-1);
673 }
674
677
680
683
686 {
687 return ConstIterator(block,0);
688 }
689
692 {
693 return ConstIterator(block,nblocks);
694 }
695
699 {
700 return ConstIterator(block,nblocks-1);
701 }
702
705 {
706 return ConstIterator(block,-1);
707 }
708
711 {
712 return Iterator(block,std::min(i,nblocks));
713 }
714
717 {
718 return ConstIterator(block,std::min(i,nblocks));
719 }
720
721 //===== sizes
722
724 size_type N () const
725 {
726 return nblocks;
727 }
728
734 {
735 return nblocks;
736 }
737
738
739 private:
740
741 void allocate() {
742 if (this->initialized)
743 DUNE_THROW(ISTLError, "Attempt to re-allocate already initialized VariableBlockVector");
744
745 // calculate space needed:
746 this->n=0;
747 for(size_type i = 0; i < nblocks; i++) {
748 this->n += block[i].size();
749 }
750
751 // now we can allocate the big array in the base class of v
752 if (this->n>0)
753 {
754 // allocate and construct objects
755 this->p = allocator_.allocate(this->n);
756 new (this->p)B[this->n];
757 }
758 else
759 {
760 this->p = nullptr;
761 }
762
763 // and we set the window pointers
764 this->block[0].setptr(this->p); // pointer to first block
765 for (size_type j=1; j<nblocks; ++j) // and the rest
766 block[j].setptr(block[j-1].getptr()+block[j-1].getsize());
767
768 // and the vector is ready
769 this->initialized = true;
770 }
771
772 size_type nblocks; // number of blocks in vector
773 window_type* block; // array of blocks pointing to the array in the base class
774 bool initialized; // true if vector has been initialized
775
776 A allocator_;
777
778 typename std::allocator_traits<A>::template rebind_alloc<window_type> windowAllocator_;
779 };
780
781
782
785} // end namespace
786
787#endif
Helper functions for determining the vector/matrix block level.
This file implements a vector space as a tensor product of a given vector space. The number of compon...
A vector of blocks with memory management.
Definition: bvector.hh:393
derive error class from the base class in common
Definition: istlexception.hh:17
Base class for stl conformant forward iterators.
Definition: iteratorfacades.hh:432
Iterator class for sequential creation of blocks.
Definition: vbvector.hh:441
bool operator==(const CreateIterator &it) const
equality
Definition: vbvector.hh:503
size_type index() const
dereferencing
Definition: vbvector.hh:509
SizeProxy reference
reference type
Definition: vbvector.hh:461
size_type * pointer
pointer type
Definition: vbvector.hh:458
bool operator!=(const CreateIterator &it) const
inequality
Definition: vbvector.hh:497
size_type value_type
value type
Definition: vbvector.hh:447
CreateIterator(VariableBlockVector &_v, int _i, bool _isEnd)
constructor
Definition: vbvector.hh:464
void setblocksize(size_type _k)
set size of current block
Definition: vbvector.hh:515
size_type & operator*()
Access size of current block.
Definition: vbvector.hh:526
std::output_iterator_tag iterator_category
iterator category
Definition: vbvector.hh:444
CreateIterator & operator++()
prefix increment
Definition: vbvector.hh:480
void difference_type
difference type (unused)
Definition: vbvector.hh:455
Iterator class for sequential access.
Definition: vbvector.hh:582
RealIterator(window_type *_p, size_type _i)
constructor
Definition: vbvector.hh:592
bool equals(const RealIterator &it) const
equality
Definition: vbvector.hh:609
size_type index() const
Return the index of the entry this iterator is pointing to.
Definition: vbvector.hh:637
void decrement()
prefix decrement
Definition: vbvector.hh:603
void increment()
prefix increment
Definition: vbvector.hh:597
RealIterator()
constructor, no arguments
Definition: vbvector.hh:585
window_type & dereference() const
dereferencing
Definition: vbvector.hh:615
A Vector of blocks with different blocksizes.
Definition: vbvector.hh:44
VariableBlockVector()
Definition: vbvector.hh:95
typename Imp::BlockTraits< B >::field_type field_type
export the type representing the field
Definition: vbvector.hh:53
A allocator_type
export the allocator type
Definition: vbvector.hh:56
VariableBlockVector(size_type _nblocks, size_type m)
Definition: vbvector.hh:132
size_type size() const
Definition: vbvector.hh:733
size_type N() const
number of blocks in the vector (are of variable size here)
Definition: vbvector.hh:724
VariableBlockVector(const VariableBlockVector &a)
copy constructor, has copy semantics
Definition: vbvector.hh:170
VariableBlockVector(size_type _nblocks)
Definition: vbvector.hh:106
~VariableBlockVector()
free dynamic memory
Definition: vbvector.hh:213
window_type & operator[](size_type i)
random access to blocks
Definition: vbvector.hh:561
CreateIterator createend()
get create iterator pointing to one after the last block
Definition: vbvector.hh:550
Iterator beforeBegin() const
Definition: vbvector.hh:670
CreateIterator createbegin()
get initial create iterator
Definition: vbvector.hh:541
VariableBlockVector & operator=(const VariableBlockVector &a)
assignment
Definition: vbvector.hh:320
static constexpr auto blocklevel
Definition: vbvector.hh:88
ConstIterator rend() const
end ConstIterator
Definition: vbvector.hh:704
A::size_type size_type
The size type for the index access.
Definition: vbvector.hh:71
ConstIterator find(size_type i) const
random access returning iterator (end if not contained)
Definition: vbvector.hh:716
ConstIterator beforeEnd() const
Definition: vbvector.hh:698
Iterator find(size_type i)
random access returning iterator (end if not contained)
Definition: vbvector.hh:710
const window_type & const_reference
Export type used for const references to container entries.
Definition: vbvector.hh:68
RealIterator< const value_type, const window_type & > ConstIterator
Const iterator.
Definition: vbvector.hh:679
Iterator end()
end Iterator
Definition: vbvector.hh:656
ConstIterator begin() const
begin ConstIterator
Definition: vbvector.hh:685
BlockVector< B, A > value_type
Type of the elements of the outer vector, i.e., dynamic vectors of B.
Definition: vbvector.hh:78
ConstIterator end() const
end ConstIterator
Definition: vbvector.hh:691
BlockVector< B, A > block_type
Same as value_type, here for historical reasons.
Definition: vbvector.hh:82
void resize(size_type _nblocks, size_type m)
same effect as constructor with same argument
Definition: vbvector.hh:268
window_type & reference
Export type used for references to container entries.
Definition: vbvector.hh:62
void resize(size_type _nblocks)
same effect as constructor with same argument
Definition: vbvector.hh:232
Iterator beforeEnd()
Definition: vbvector.hh:663
Iterator begin()
begin Iterator
Definition: vbvector.hh:650
#define DUNE_THROW(E, m)
Definition: exceptions.hh:216
auto min(ADLTag< 0 >, const V &v1, const V &v2)
implements binary Simd::min()
Definition: defaults.hh:87
This file implements iterator facade classes for writing stl conformant iterators.
Dune namespace.
Definition: alignedallocator.hh:11
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Dec 22, 23:30, 2024)