dune-istl  2.11
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>
15 #include <dune/common/indexediterator.hh>
16 #include <dune/common/iteratorfacades.hh>
17 #include "istlexception.hh"
18 #include "bvector.hh"
19 
20 #include <dune/istl/blocklevel.hh>
21 
26 namespace Dune {
27 
43  template<class B, class A=std::allocator<B> >
44  class VariableBlockVector : public Imp::block_vector_unmanaged<B,typename A::size_type>
45  // this derivation gives us all the blas level 1 and norms
46  // on the large array. However, access operators have to be
47  // overwritten.
48  {
49  using Base = Imp::block_vector_unmanaged<B,typename A::size_type>;
50 
51  // just a shorthand
52  using window_type = Imp::BlockVectorWindow<B,A>;
53 
54  // data-structure holding the windows (but not the actual data)
55  using VectorWindows = std::vector<window_type, typename std::allocator_traits<A>::template rebind_alloc<window_type>>;
56 
57  // block type bool is not supported since std::vector<bool> is used for storage
58  static_assert(not std::is_same_v<B,bool>, "Block type 'bool' not supported by VariableBlockVector.");
59 
60  public:
61 
62  //===== type definitions and constants
63 
65  using field_type = typename Imp::BlockTraits<B>::field_type;
66 
68  using allocator_type = A;
69 
74  using reference = window_type&;
75 
80  using const_reference = const window_type&;
81 
83  using size_type = typename A::size_type;
84 
91 
95 
96  //===== constructors and such
97 
103  Base()
104  {}
105 
112  explicit VariableBlockVector (size_type numBlocks) :
113  Base(),
114  block(numBlocks)
115  {}
116 
125  VariableBlockVector (size_type numBlocks, size_type blockSize) :
126  Base(),
127  block(numBlocks),
128  storage_(numBlocks*blockSize)
129  {
130  // and we can allocate the big array in the base class
131  syncBaseArray();
132 
133  // set the windows into the big array
134  for (size_type i=0; i<numBlocks; ++i)
135  block[i].set(blockSize,this->p+(i*blockSize));
136 
137  // and the vector is usable
138  initialized = true;
139  }
140 
143  Base(static_cast<const Base&>(a)),
144  block(a.block),
145  storage_(a.storage_)
146  {
147  syncBaseArray();
148 
149  // and we must set the windows
150  if (block.size()>0) {
151  block[0].set(block[0].getsize(),this->p); // first block
152  for (size_type i=1; i<block.size(); ++i) // and the rest
153  block[i].set(block[i].getsize(),block[i-1].getptr()+block[i-1].getsize());
154  }
155 
156  // and we have a usable vector
157  initialized = a.initialized;
158  }
159 
162  Base()
163  {
164  tmp.swap(*this);
165  }
166 
167  ~VariableBlockVector () = default;
168 
169 
172  {
173  tmp.swap(*this);
174  return *this;
175  }
176 
178  void swap (VariableBlockVector& other) noexcept
179  {
180  using std::swap;
181  swap(storage_, other.storage_);
182  swap(block, other.block);
183  swap(initialized, other.initialized);
184 
185  other.syncBaseArray();
186  syncBaseArray();
187  }
188 
190  friend void swap (VariableBlockVector& lhs, VariableBlockVector& rhs) noexcept
191  {
192  lhs.swap(rhs);
193  }
194 
196  void resize (size_type numBlocks)
197  {
198  storage_.clear();
199 
200  syncBaseArray();
201 
202  // we can allocate the windows now
203  block.resize(numBlocks);
204 
205  // and the vector not fully usable
206  initialized = false;
207  }
208 
210  void resize (size_type numBlocks, size_type blockSize)
211  {
212  // and we can allocate the big array in the base class
213  storage_.resize(numBlocks*blockSize);
214  block.resize(numBlocks);
215  syncBaseArray();
216 
217  // set the windows into the big array
218  for (size_type i=0; i<block.size(); ++i)
219  block[i].set(blockSize,this->p+(i*blockSize));
220 
221  // and the vector is usable
222  initialized = true;
223  }
224 
225  //===== assignment from scalar
226 
229  {
230  (static_cast<Imp::block_vector_unmanaged<B,size_type>&>(*this)) = k;
231  return *this;
232  }
233 
234 
235  //===== the creation interface
236 
237  class CreateIterator;
238 
239 #ifndef DOXYGEN
240 
241  // The window_type does not hand out a reference to its size,
242  // so in order to provide a valid iterator, we need a workaround
243  // to make assignment possible. This proxy enables just that by
244  // implicitly converting to the stored size for read access and
245  // tunneling assignment to the accessor method of the window.
246  struct SizeProxy
247  {
248 
249  operator size_type () const
250  {
251  return target->getsize();
252  }
253 
254  SizeProxy& operator= (size_type size)
255  {
256  target->setsize(size);
257  return *this;
258  }
259 
260  private:
261 
262  friend class CreateIterator;
263 
264  SizeProxy (window_type& t) :
265  target(&t)
266  {}
267 
268  window_type* target;
269  };
270 
271 #endif // DOXYGEN
272 
275  {
276  public:
278  using iterator_category = std::output_iterator_tag;
279 
282 
289  using difference_type = void;
290 
292  using pointer = size_type*;
293 
295  using reference = SizeProxy;
296 
298  CreateIterator (VariableBlockVector& _v, int _i, bool _isEnd) :
299  v(&_v),
300  i(_i),
301  isEnd(_isEnd)
302  {}
303 
305  {
306  // When the iterator gets destructed, we allocate the memory
307  // for the VariableBlockVector if
308  // 1. the current iterator was not created as enditerator
309  // 2. we're at the last block
310  // 3. the vector hasn't been initialized earlier
311  if (not isEnd && i==v->block.size() && not v->initialized)
312  v->allocate();
313  }
314 
317  {
318  // go to next block
319  ++i;
320 
321  return *this;
322  }
323 
326  {
327  CreateIterator tmp(*this);
328  this->operator++();
329  return tmp;
330  }
331 
333  bool operator!= (const CreateIterator& it) const
334  {
335  return not (*this == it);
336  }
337 
339  bool operator== (const CreateIterator& it) const
340  {
341  return (i==it.i) && (v==it.v);
342  }
343 
345  size_type index () const
346  {
347  return i;
348  }
349 
352  {
353  v->block[i].setsize(_k);
354  }
355 
357 #ifdef DOXYGEN
358  size_type&
359 #else
360  SizeProxy
361 #endif
363  {
364  return {v->block[i]};
365  }
366 
367  private:
368  VariableBlockVector* v; // my vector
369  size_type i; // current block to be defined
370  bool isEnd; // flag if this object was created as the end iterator.
371  };
372 
373  // CreateIterator wants to set all the arrays ...
374  friend class CreateIterator;
375 
378  {
379 #ifdef DUNE_ISTL_WITH_CHECKING
380  if (initialized) DUNE_THROW(ISTLError,"no CreateIterator in initialized state");
381 #endif
382  return CreateIterator(*this, 0, false);
383  }
384 
387  {
388  return CreateIterator(*this, block.size(), true);
389  }
390 
391 
392  //===== access to components
393  // has to be overwritten from base class because it must
394  // return access to the windows
395 
397  window_type& operator[] (size_type i)
398  {
399 #ifdef DUNE_ISTL_WITH_CHECKING
400  if (i>=block.size()) DUNE_THROW(ISTLError,"index out of range");
401 #endif
402  return block[i];
403  }
404 
406  const window_type& operator[] (size_type i) const
407  {
408 #ifdef DUNE_ISTL_WITH_CHECKING
409  if (i<0 || i>=block.size()) DUNE_THROW(ISTLError,"index out of range");
410 #endif
411  return block[i];
412  }
413 
414  using Iterator = IndexedIterator<typename VectorWindows::iterator>;
415 
418  {
419  return Iterator{block.begin()};
420  }
421 
424  {
425  return Iterator{block.end()};
426  }
427 
431  {
432  return Iterator{--block.end()};
433  }
434 
438  {
439  return Iterator{--block.begin()};
440  }
441 
444 
446  using ConstIterator = IndexedIterator<typename VectorWindows::const_iterator>;
447 
450 
453  {
454  return ConstIterator{block.begin()};
455  }
456 
459  {
460  return ConstIterator{block.end()};
461  }
462 
466  {
467  return ConstIterator{--block.end()};
468  }
469 
473  {
474  return ConstIterator{--block.begin()};
475  }
476 
479  {
480  return ConstIterator{block.rend()};
481  }
482 
485  {
486  Iterator tmp = block.begin();
487  tmp+=std::min(i, block.size());
488  return tmp;
489  }
490 
493  {
494  ConstIterator tmp = block.begin();
495  tmp+=std::min(i, block.size());
496  return tmp;
497  }
498 
499  //===== sizes
500 
502  size_type N () const noexcept
503  {
504  return block.size();
505  }
506 
511  size_type size () const noexcept
512  {
513  return block.size();
514  }
515 
516 
517  private:
518 
519  void allocate ()
520  {
521  if (this->initialized)
522  DUNE_THROW(ISTLError, "Attempt to re-allocate already initialized VariableBlockVector");
523 
524  // calculate space needed:
525  size_type storageNeeded = 0;
526  for(size_type i = 0; i < block.size(); i++)
527  storageNeeded += block[i].size();
528 
529  storage_.resize(storageNeeded);
530  syncBaseArray();
531 
532  // and we set the window pointers
533  block[0].setptr(this->p); // pointer to first block
534  for (size_type j=1; j<block.size(); ++j) // and the rest
535  block[j].setptr(block[j-1].getptr()+block[j-1].getsize());
536 
537  // and the vector is ready
538  this->initialized = true;
539  }
540 
541  void syncBaseArray () noexcept
542  {
543  this->p = storage_.data();
544  this->n = storage_.size();
545  }
546 
547  VectorWindows block = {}; // vector of blocks pointing to the array in the base class
548  std::vector<B, A> storage_ = {};
549  bool initialized = false; // true if vector has been initialized
550  };
551 
555  template<class B, class A>
556  struct FieldTraits< VariableBlockVector<B, A> >
557  {
558  typedef typename FieldTraits<B>::field_type field_type;
559  typedef typename FieldTraits<B>::real_type real_type;
560  };
568 } // end namespace
569 
570 #endif
ConstIterator beforeBegin() const
Definition: vbvector.hh:472
A allocator_type
export the allocator type
Definition: vbvector.hh:68
bool operator==(const CreateIterator &it) const
equality
Definition: vbvector.hh:339
derive error class from the base class in common
Definition: istlexception.hh:19
void setblocksize(size_type _k)
set size of current block
Definition: vbvector.hh:351
size_type & operator*()
Access size of current block.
Definition: vbvector.hh:362
void resize(size_type numBlocks)
same effect as constructor with same argument
Definition: vbvector.hh:196
FieldTraits< B >::real_type real_type
Definition: vbvector.hh:559
A Vector of blocks with different blocksizes.
Definition: vbvector.hh:44
ConstIterator begin() const
begin ConstIterator
Definition: vbvector.hh:452
CreateIterator createbegin()
get initial create iterator
Definition: vbvector.hh:377
IndexedIterator< typename VectorWindows::iterator > Iterator
Definition: vbvector.hh:414
Iterator beforeEnd()
Definition: vbvector.hh:430
VariableBlockVector(size_type numBlocks, size_type blockSize)
Construct a vector with given number of blocks each having a constant size.
Definition: vbvector.hh:125
bool operator!=(const CreateIterator &it) const
inequality
Definition: vbvector.hh:333
VariableBlockVector()
Constructor without arguments makes an empty vector.
Definition: vbvector.hh:102
window_type & operator[](size_type i)
random access to blocks
Definition: vbvector.hh:397
window_type & reference
Export type used for references to container entries.
Definition: vbvector.hh:74
const window_type & const_reference
Export type used for const references to container entries.
Definition: vbvector.hh:80
size_type value_type
value type
Definition: vbvector.hh:281
FieldTraits< B >::field_type field_type
Definition: vbvector.hh:558
SizeProxy reference
reference type
Definition: vbvector.hh:295
Iterator find(size_type i)
random access returning iterator (end if not contained)
Definition: vbvector.hh:484
VariableBlockVector(const VariableBlockVector &a)
Copy constructor, has copy semantics.
Definition: vbvector.hh:142
VariableBlockVector(size_type numBlocks)
Construct a vector with given number of blocks, but size of each block is not yet known...
Definition: vbvector.hh:112
~CreateIterator()
Definition: vbvector.hh:304
size_type size() const noexcept
Definition: vbvector.hh:511
std::output_iterator_tag iterator_category
iterator category
Definition: vbvector.hh:278
Helper functions for determining the vector/matrix block level.
ConstIterator end() const
end ConstIterator
Definition: vbvector.hh:458
void swap(VariableBlockVector &other) noexcept
Exchange the storage and internal state with other.
Definition: vbvector.hh:178
CreateIterator(VariableBlockVector &_v, int _i, bool _isEnd)
constructor
Definition: vbvector.hh:298
ConstIterator const_iterator
Export the const iterator type using std naming rules.
Definition: vbvector.hh:449
This file implements a vector space as a tensor product of a given vector space. The number of compon...
size_type N() const noexcept
number of blocks in the vector (are of variable size here)
Definition: vbvector.hh:502
ConstIterator beforeEnd() const
Definition: vbvector.hh:465
IndexedIterator< typename VectorWindows::const_iterator > ConstIterator
Const iterator.
Definition: vbvector.hh:446
ConstIterator find(size_type i) const
random access returning iterator (end if not contained)
Definition: vbvector.hh:492
Iterator beforeBegin()
Definition: vbvector.hh:437
typename Imp::BlockTraits< B >::field_type field_type
export the type representing the field
Definition: vbvector.hh:65
size_type index() const
dereferencing
Definition: vbvector.hh:345
ConstIterator rend() const
end ConstIterator
Definition: vbvector.hh:478
friend void swap(VariableBlockVector &lhs, VariableBlockVector &rhs) noexcept
Free function to swap the storage and internal state of lhs with rhs.
Definition: vbvector.hh:190
Iterator end()
end Iterator
Definition: vbvector.hh:423
Iterator begin()
begin Iterator
Definition: vbvector.hh:417
friend class CreateIterator
Definition: vbvector.hh:374
VariableBlockVector & operator=(VariableBlockVector tmp)
Copy and move assignment.
Definition: vbvector.hh:171
Iterator class for sequential creation of blocks.
Definition: vbvector.hh:274
CreateIterator & operator++()
prefix increment
Definition: vbvector.hh:316
Iterator iterator
Export the iterator type using std naming rules.
Definition: vbvector.hh:443
void resize(size_type numBlocks, size_type blockSize)
same effect as constructor with same argument
Definition: vbvector.hh:210
size_type * pointer
pointer type
Definition: vbvector.hh:292
Definition: allocator.hh:11
typename A::size_type size_type
The size type for the index access.
Definition: vbvector.hh:83
A vector of blocks with memory management.
Definition: bvector.hh:391
CreateIterator createend()
get create iterator pointing to one after the last block
Definition: vbvector.hh:386
VariableBlockVector(VariableBlockVector &&tmp)
Move constructor:
Definition: vbvector.hh:161
void difference_type
difference type (unused)
Definition: vbvector.hh:289