Dune Core Modules (2.9.1)

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