Dune Core Modules (unstable)

vbvector.hh
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright © 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 
14 #include <dune/common/ftraits.hh>
16 #include "istlexception.hh"
17 #include "bvector.hh"
18 
19 #include <dune/istl/blocklevel.hh>
20 
25 namespace Dune {
26 
42  template<class B, class A=std::allocator<B> >
43  class VariableBlockVector : public Imp::block_vector_unmanaged<B,typename A::size_type>
44  // this derivation gives us all the blas level 1 and norms
45  // on the large array. However, access operators have to be
46  // overwritten.
47  {
48  // just a shorthand
49  typedef Imp::BlockVectorWindow<B,A> window_type;
50 
51  public:
52 
53  //===== type definitions and constants
54 
56  using field_type = typename Imp::BlockTraits<B>::field_type;
57 
59  typedef A allocator_type;
60 
65  typedef window_type& reference;
66 
71  typedef const window_type& const_reference;
72 
74  typedef typename A::size_type size_type;
75 
82 
86 
87  //===== constructors and such
88 
92  VariableBlockVector () : Imp::block_vector_unmanaged<B,size_type>()
93  {
94  // nothing is known ...
95  nblocks = 0;
96  block = nullptr;
97  initialized = false;
98  }
99 
103  explicit VariableBlockVector (size_type _nblocks) : Imp::block_vector_unmanaged<B,size_type>()
104  {
105  // we can allocate the windows now
106  nblocks = _nblocks;
107  if (nblocks>0)
108  {
109  block = windowAllocator_.allocate(nblocks);
110  new (block) window_type[nblocks];
111  }
112  else
113  {
114  nblocks = 0;
115  block = nullptr;
116  }
117 
118  // Note: memory in base class still not allocated
119  // the vector not usable
120  initialized = false;
121  }
122 
129  VariableBlockVector (size_type _nblocks, size_type m) : Imp::block_vector_unmanaged<B,size_type>()
130  {
131  // and we can allocate the big array in the base class
132  this->n = _nblocks*m;
133  if (this->n>0)
134  {
135  this->p = allocator_.allocate(this->n);
136  new (this->p)B[this->n];
137  }
138  else
139  {
140  this->n = 0;
141  this->p = nullptr;
142  }
143 
144  // we can allocate the windows now
145  nblocks = _nblocks;
146  if (nblocks>0)
147  {
148  // allocate and construct the windows
149  block = windowAllocator_.allocate(nblocks);
150  new (block) window_type[nblocks];
151 
152  // set the windows into the big array
153  for (size_type i=0; i<nblocks; ++i)
154  block[i].set(m,this->p+(i*m));
155  }
156  else
157  {
158  nblocks = 0;
159  block = nullptr;
160  }
161 
162  // and the vector is usable
163  initialized = true;
164  }
165 
168  {
169  // allocate the big array in the base class
170  this->n = a.n;
171  if (this->n>0)
172  {
173  // allocate and construct objects
174  this->p = allocator_.allocate(this->n);
175  new (this->p)B[this->n];
176 
177  // copy data
178  for (size_type i=0; i<this->n; i++) this->p[i]=a.p[i];
179  }
180  else
181  {
182  this->n = 0;
183  this->p = nullptr;
184  }
185 
186  // we can allocate the windows now
187  nblocks = a.nblocks;
188  if (nblocks>0)
189  {
190  // alloc
191  block = windowAllocator_.allocate(nblocks);
192  new (block) window_type[nblocks];
193 
194  // and we must set the windows
195  block[0].set(a.block[0].getsize(),this->p); // first block
196  for (size_type i=1; i<nblocks; ++i) // and the rest
197  block[i].set(a.block[i].getsize(),block[i-1].getptr()+block[i-1].getsize());
198  }
199  else
200  {
201  nblocks = 0;
202  block = nullptr;
203  }
204 
205  // and we have a usable vector
206  initialized = true;
207  }
208 
211  {
212  if (this->n>0) {
213  size_type i=this->n;
214  while (i)
215  this->p[--i].~B();
216  allocator_.deallocate(this->p,this->n);
217  }
218  if (nblocks>0) {
219  size_type i=nblocks;
220  while (i)
221  block[--i].~window_type();
222  windowAllocator_.deallocate(block,nblocks);
223  }
224 
225  }
226 
227 
229  void resize (size_type _nblocks)
230  {
231  // deconstruct objects and deallocate memory if necessary
232  if (this->n>0) {
233  size_type i=this->n;
234  while (i)
235  this->p[--i].~B();
236  allocator_.deallocate(this->p,this->n);
237  }
238  if (nblocks>0) {
239  size_type i=nblocks;
240  while (i)
241  block[--i].~window_type();
242  windowAllocator_.deallocate(block,nblocks);
243  }
244  this->n = 0;
245  this->p = nullptr;
246 
247  // we can allocate the windows now
248  nblocks = _nblocks;
249  if (nblocks>0)
250  {
251  block = windowAllocator_.allocate(nblocks);
252  new (block) window_type[nblocks];
253  }
254  else
255  {
256  nblocks = 0;
257  block = nullptr;
258  }
259 
260  // and the vector not fully usable
261  initialized = false;
262  }
263 
265  void resize (size_type _nblocks, size_type m)
266  {
267  // deconstruct objects and deallocate memory if necessary
268  if (this->n>0) {
269  size_type i=this->n;
270  while (i)
271  this->p[--i].~B();
272  allocator_.deallocate(this->p,this->n);
273  }
274  if (nblocks>0) {
275  size_type i=nblocks;
276  while (i)
277  block[--i].~window_type();
278  windowAllocator_.deallocate(block,nblocks);
279  }
280 
281  // and we can allocate the big array in the base class
282  this->n = _nblocks*m;
283  if (this->n>0)
284  {
285  this->p = allocator_.allocate(this->n);
286  new (this->p)B[this->n];
287  }
288  else
289  {
290  this->n = 0;
291  this->p = nullptr;
292  }
293 
294  // we can allocate the windows now
295  nblocks = _nblocks;
296  if (nblocks>0)
297  {
298  // allocate and construct objects
299  block = windowAllocator_.allocate(nblocks);
300  new (block) window_type[nblocks];
301 
302  // set the windows into the big array
303  for (size_type i=0; i<nblocks; ++i)
304  block[i].set(m,this->p+(i*m));
305  }
306  else
307  {
308  nblocks = 0;
309  block = nullptr;
310  }
311 
312  // and the vector is usable
313  initialized = true;
314  }
315 
318  {
319  if (&a!=this) // check if this and a are different objects
320  {
321  // reallocate arrays if necessary
322  // Note: still the block sizes may vary !
323  if (this->n!=a.n || nblocks!=a.nblocks)
324  {
325  // deconstruct objects and deallocate memory if necessary
326  if (this->n>0) {
327  size_type i=this->n;
328  while (i)
329  this->p[--i].~B();
330  allocator_.deallocate(this->p,this->n);
331  }
332  if (nblocks>0) {
333  size_type i=nblocks;
334  while (i)
335  block[--i].~window_type();
336  windowAllocator_.deallocate(block,nblocks);
337  }
338 
339  // allocate the big array in the base class
340  this->n = a.n;
341  if (this->n>0)
342  {
343  // allocate and construct objects
344  this->p = allocator_.allocate(this->n);
345  new (this->p)B[this->n];
346  }
347  else
348  {
349  this->n = 0;
350  this->p = nullptr;
351  }
352 
353  // we can allocate the windows now
354  nblocks = a.nblocks;
355  if (nblocks>0)
356  {
357  // alloc
358  block = windowAllocator_.allocate(nblocks);
359  new (block) window_type[nblocks];
360  }
361  else
362  {
363  nblocks = 0;
364  block = nullptr;
365  }
366  }
367 
368  // copy block structure, might be different although
369  // sizes are the same !
370  if (nblocks>0)
371  {
372  block[0].set(a.block[0].getsize(),this->p); // first block
373  for (size_type i=1; i<nblocks; ++i) // and the rest
374  block[i].set(a.block[i].getsize(),block[i-1].getptr()+block[i-1].getsize());
375  }
376 
377  // and copy the data
378  for (size_type i=0; i<this->n; i++) this->p[i]=a.p[i];
379  }
380 
381  // and we have a usable vector
382  initialized = true;
383 
384  return *this; // Return reference to make constructions like a=b=c; work.
385  }
386 
387 
388  //===== assignment from scalar
389 
392  {
393  (static_cast<Imp::block_vector_unmanaged<B,size_type>&>(*this)) = k;
394  return *this;
395  }
396 
397 
398  //===== the creation interface
399 
400  class CreateIterator;
401 
402 #ifndef DOXYGEN
403 
404  // The window_type does not hand out a reference to its size,
405  // so in order to provide a valid iterator, we need a workaround
406  // to make assignment possible. This proxy enables just that by
407  // implicitly converting to the stored size for read access and
408  // tunneling assignment to the accessor method of the window.
409  struct SizeProxy
410  {
411 
412  operator size_type() const
413  {
414  return target->getsize();
415  }
416 
417  SizeProxy& operator=(size_type size)
418  {
419  target->setsize(size);
420  return *this;
421  }
422 
423  private:
424 
425  friend class CreateIterator;
426 
427  SizeProxy(window_type& t)
428  : target(&t)
429  {}
430 
431  window_type* target;
432  };
433 
434 #endif // DOXYGEN
435 
438  {
439  public:
441  using iterator_category = std::output_iterator_tag;
442 
445 
452  using difference_type = void;
453 
455  using pointer = size_type*;
456 
458  using reference = SizeProxy;
459 
461  CreateIterator (VariableBlockVector& _v, int _i, bool _isEnd) :
462  v(_v),
463  i(_i),
464  isEnd(_isEnd) {}
465 
466  ~CreateIterator() {
467  // When the iterator gets destructed, we allocate the memory
468  // for the VariableBlockVector if
469  // 1. the current iterator was not created as enditerator
470  // 2. we're at the last block
471  // 3. the vector hasn't been initialized earlier
472  if (not isEnd && i==v.nblocks && not v.initialized)
473  v.allocate();
474  }
475 
478  {
479  // go to next block
480  ++i;
481 
482  return *this;
483  }
484 
487  {
488  CreateIterator tmp(*this);
489  this->operator++();
490  return tmp;
491  }
492 
494  bool operator!= (const CreateIterator& it) const
495  {
496  return (i!=it.i) || (&v!=&it.v);
497  }
498 
500  bool operator== (const CreateIterator& it) const
501  {
502  return (i==it.i) && (&v==&it.v);
503  }
504 
506  size_type index () const
507  {
508  return i;
509  }
510 
512  void setblocksize (size_type _k)
513  {
514  v.block[i].setsize(_k);
515  }
516 
518 #ifdef DOXYGEN
519  size_type&
520 #else
521  SizeProxy
522 #endif
524  {
525  return {v.block[i]};
526  }
527 
528  private:
529  VariableBlockVector& v; // my vector
530  size_type i; // current block to be defined
531  const bool isEnd; // flag if this object was created as the end iterator.
532  };
533 
534  // CreateIterator wants to set all the arrays ...
535  friend class CreateIterator;
536 
539  {
540 #ifdef DUNE_ISTL_WITH_CHECKING
541  if (initialized) DUNE_THROW(ISTLError,"no CreateIterator in initialized state");
542 #endif
543  return CreateIterator(*this,0, false);
544  }
545 
548  {
549  return CreateIterator(*this,nblocks, true);
550  }
551 
552 
553  //===== access to components
554  // has to be overwritten from base class because it must
555  // return access to the windows
556 
558  window_type& operator[] (size_type i)
559  {
560 #ifdef DUNE_ISTL_WITH_CHECKING
561  if (i>=nblocks) DUNE_THROW(ISTLError,"index out of range");
562 #endif
563  return block[i];
564  }
565 
567  const window_type& operator[] (size_type i) const
568  {
569 #ifdef DUNE_ISTL_WITH_CHECKING
570  if (i<0 || i>=nblocks) DUNE_THROW(ISTLError,"index out of range");
571 #endif
572  return block[i];
573  }
574 
576  template <class T, class R>
578  : public RandomAccessIteratorFacade<RealIterator<T,R>, T, R>
579  {
580  public:
583  {
584  p = nullptr;
585  i = 0;
586  }
587 
589  RealIterator (window_type* _p, size_type _i)
590  : p(_p), i(_i)
591  {}
592 
594  void increment()
595  {
596  ++i;
597  }
598 
600  void decrement()
601  {
602  --i;
603  }
604 
606  bool equals (const RealIterator& it) const
607  {
608  return (p+i)==(it.p+it.i);
609  }
610 
612  window_type& dereference () const
613  {
614  return p[i];
615  }
616 
617  void advance(std::ptrdiff_t d)
618  {
619  i+=d;
620  }
621 
622  std::ptrdiff_t distanceTo(const RealIterator& o) const
623  {
624  return o.i-i;
625  }
626 
627  // Needed for operator[] of the iterator
628  window_type& elementAt (std::ptrdiff_t offset) const
629  {
630  return p[i+offset];
631  }
632 
634  size_type index() const
635  {
636  return i;
637  }
638 
639  private:
640  window_type* p;
641  size_type i;
642  };
643 
644  using Iterator = RealIterator<value_type,window_type&>;
645 
648  {
649  return Iterator(block,0);
650  }
651 
654  {
655  return Iterator(block,nblocks);
656  }
657 
661  {
662  return Iterator(block,nblocks-1);
663  }
664 
668  {
669  return Iterator(block,-1);
670  }
671 
673  using iterator = Iterator;
674 
677 
679  using const_iterator = ConstIterator;
680 
683  {
684  return ConstIterator(block,0);
685  }
686 
689  {
690  return ConstIterator(block,nblocks);
691  }
692 
696  {
697  return ConstIterator(block,nblocks-1);
698  }
699 
702  {
703  return ConstIterator(block,-1);
704  }
705 
707  Iterator find (size_type i)
708  {
709  return Iterator(block,std::min(i,nblocks));
710  }
711 
713  ConstIterator find (size_type i) const
714  {
715  return ConstIterator(block,std::min(i,nblocks));
716  }
717 
718  //===== sizes
719 
721  size_type N () const
722  {
723  return nblocks;
724  }
725 
730  size_type size () const
731  {
732  return nblocks;
733  }
734 
735 
736  private:
737 
738  void allocate() {
739  if (this->initialized)
740  DUNE_THROW(ISTLError, "Attempt to re-allocate already initialized VariableBlockVector");
741 
742  // calculate space needed:
743  this->n=0;
744  for(size_type i = 0; i < nblocks; i++) {
745  this->n += block[i].size();
746  }
747 
748  // now we can allocate the big array in the base class of v
749  if (this->n>0)
750  {
751  // allocate and construct objects
752  this->p = allocator_.allocate(this->n);
753  new (this->p)B[this->n];
754  }
755  else
756  {
757  this->p = nullptr;
758  }
759 
760  // and we set the window pointers
761  this->block[0].setptr(this->p); // pointer to first block
762  for (size_type j=1; j<nblocks; ++j) // and the rest
763  block[j].setptr(block[j-1].getptr()+block[j-1].getsize());
764 
765  // and the vector is ready
766  this->initialized = true;
767  }
768 
769  size_type nblocks; // number of blocks in vector
770  window_type* block; // array of blocks pointing to the array in the base class
771  bool initialized; // true if vector has been initialized
772 
773  A allocator_;
774 
775  typename std::allocator_traits<A>::template rebind_alloc<window_type> windowAllocator_;
776  };
777 
781  template<class B, class A>
782  struct FieldTraits< VariableBlockVector<B, A> >
783  {
784  typedef typename FieldTraits<B>::field_type field_type;
785  typedef typename FieldTraits<B>::real_type real_type;
786  };
794 } // end namespace
795 
796 #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:392
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:438
bool operator==(const CreateIterator &it) const
equality
Definition: vbvector.hh:500
size_type index() const
dereferencing
Definition: vbvector.hh:506
SizeProxy reference
reference type
Definition: vbvector.hh:458
CreateIterator & operator++()
prefix increment
Definition: vbvector.hh:477
size_type * pointer
pointer type
Definition: vbvector.hh:455
bool operator!=(const CreateIterator &it) const
inequality
Definition: vbvector.hh:494
size_type value_type
value type
Definition: vbvector.hh:444
CreateIterator(VariableBlockVector &_v, int _i, bool _isEnd)
constructor
Definition: vbvector.hh:461
void setblocksize(size_type _k)
set size of current block
Definition: vbvector.hh:512
std::output_iterator_tag iterator_category
iterator category
Definition: vbvector.hh:441
size_type & operator*()
Access size of current block.
Definition: vbvector.hh:523
void difference_type
difference type (unused)
Definition: vbvector.hh:452
Iterator class for sequential access.
Definition: vbvector.hh:579
RealIterator(window_type *_p, size_type _i)
constructor
Definition: vbvector.hh:589
window_type & dereference() const
dereferencing
Definition: vbvector.hh:612
bool equals(const RealIterator &it) const
equality
Definition: vbvector.hh:606
size_type index() const
Return the index of the entry this iterator is pointing to.
Definition: vbvector.hh:634
void decrement()
prefix decrement
Definition: vbvector.hh:600
void increment()
prefix increment
Definition: vbvector.hh:594
RealIterator()
constructor, no arguments
Definition: vbvector.hh:582
A Vector of blocks with different blocksizes.
Definition: vbvector.hh:47
VariableBlockVector()
Definition: vbvector.hh:92
typename Imp::BlockTraits< B >::field_type field_type
export the type representing the field
Definition: vbvector.hh:56
A allocator_type
export the allocator type
Definition: vbvector.hh:59
VariableBlockVector(size_type _nblocks, size_type m)
Definition: vbvector.hh:129
size_type size() const
Definition: vbvector.hh:730
size_type N() const
number of blocks in the vector (are of variable size here)
Definition: vbvector.hh:721
VariableBlockVector(const VariableBlockVector &a)
copy constructor, has copy semantics
Definition: vbvector.hh:167
VariableBlockVector(size_type _nblocks)
Definition: vbvector.hh:103
~VariableBlockVector()
free dynamic memory
Definition: vbvector.hh:210
CreateIterator createend()
get create iterator pointing to one after the last block
Definition: vbvector.hh:547
Iterator beforeBegin() const
Definition: vbvector.hh:667
CreateIterator createbegin()
get initial create iterator
Definition: vbvector.hh:538
VariableBlockVector & operator=(const VariableBlockVector &a)
assignment
Definition: vbvector.hh:317
ConstIterator rend() const
end ConstIterator
Definition: vbvector.hh:701
A::size_type size_type
The size type for the index access.
Definition: vbvector.hh:74
ConstIterator find(size_type i) const
random access returning iterator (end if not contained)
Definition: vbvector.hh:713
ConstIterator beforeEnd() const
Definition: vbvector.hh:695
Iterator find(size_type i)
random access returning iterator (end if not contained)
Definition: vbvector.hh:707
const window_type & const_reference
Export type used for const references to container entries.
Definition: vbvector.hh:71
RealIterator< const value_type, const window_type & > ConstIterator
Const iterator.
Definition: vbvector.hh:676
Iterator end()
end Iterator
Definition: vbvector.hh:653
ConstIterator begin() const
begin ConstIterator
Definition: vbvector.hh:682
BlockVector< B, A > value_type
Type of the elements of the outer vector, i.e., dynamic vectors of B.
Definition: vbvector.hh:81
window_type & operator[](size_type i)
random access to blocks
Definition: vbvector.hh:558
ConstIterator end() const
end ConstIterator
Definition: vbvector.hh:688
BlockVector< B, A > block_type
Same as value_type, here for historical reasons.
Definition: vbvector.hh:85
void resize(size_type _nblocks, size_type m)
same effect as constructor with same argument
Definition: vbvector.hh:265
window_type & reference
Export type used for references to container entries.
Definition: vbvector.hh:65
void resize(size_type _nblocks)
same effect as constructor with same argument
Definition: vbvector.hh:229
Iterator beforeEnd()
Definition: vbvector.hh:660
Iterator begin()
begin Iterator
Definition: vbvector.hh:647
Type traits to determine the type of reals (when working with complex numbers)
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
constexpr auto min
Function object that returns the smaller of the given values.
Definition: hybridutilities.hh:506
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.80.0 (Apr 27, 22:29, 2024)