Dune Core Modules (2.9.0)

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 
18 #include <dune/istl/blocklevel.hh>
19 
24 namespace 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 
460  using pointer = size_type*;
461 
463  using reference = SizeProxy;
464 
466  CreateIterator (VariableBlockVector& _v, int _i, bool _isEnd) :
467  v(_v),
468  i(_i),
469  isEnd(_isEnd) {}
470 
471  ~CreateIterator() {
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 
511  size_type index () const
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 
599  void increment()
600  {
601  ++i;
602  }
603 
605  void decrement()
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 
639  size_type index() const
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 
735  size_type size () const
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
CreateIterator & operator++()
prefix increment
Definition: vbvector.hh:482
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
std::output_iterator_tag iterator_category
iterator category
Definition: vbvector.hh:446
size_type & operator*()
Access size of current block.
Definition: vbvector.hh:528
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
window_type & dereference() const
dereferencing
Definition: vbvector.hh:617
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
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
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
window_type & operator[](size_type i)
random access to blocks
Definition: vbvector.hh:563
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.80.0 (May 3, 22:32, 2024)