FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
vector_mirror.hpp
1// FEAT3: Finite Element Analysis Toolbox, Version 3
2// Copyright (C) 2010 by Stefan Turek & the FEAT group
3// FEAT3 is released under the GNU General Public License version 3,
4// see the file 'copyright.txt' in the top level directory for details.
5
6#pragma once
7
8// includes, FEAT
9#include <kernel/lafem/container.hpp>
10#include <kernel/lafem/dense_vector.hpp>
11#include <kernel/lafem/dense_vector_blocked.hpp>
12#include <kernel/lafem/sparse_vector.hpp>
13#include <kernel/lafem/sparse_vector_blocked.hpp>
14#include <kernel/lafem/sparse_matrix_csr.hpp>
15#include <kernel/lafem/arch/mirror.hpp>
16
17namespace FEAT
18{
19 namespace LAFEM
20 {
49 template<typename DT_, typename IT_>
51 public Container<DT_, IT_>
52 {
53 public:
57 typedef DT_ DataType;
59 typedef IT_ IndexType;
60
62 template <typename DT2_ = DT_, typename IT2_ = IT_>
64
66 template <typename DataType2_, typename IndexType2_>
68
70 typedef IT_* ImageIterator;
71
72 public:
75 BaseClass(0)
76 {
77 this->_scalar_index.push_back(0); // number of indices
78 }
79
94 explicit VectorMirror(Index size_in, Index num_idx) :
95 BaseClass(size_in)
96 {
97 this->_scalar_index.push_back(num_idx); // number of indices
98 if(num_idx > Index(0))
99 {
100 this->_indices.push_back(MemoryPool::template allocate_memory<IndexType>(num_idx));
101 this->_indices_size.push_back(num_idx);
102 }
103 }
104
107 BaseClass(std::forward<BaseClass>(other))
108 {
109 }
110
113 {
114 if(this == &other)
115 return *this;
116
117 this->move(std::forward<BaseClass>(other));
118
119 return *this;
120 }
121
131 {
132 VectorMirror mir(size_in, size_in);
133 IndexType* idx = mir.indices();
134 for(Index i(0); i < size_in; ++i)
135 idx[i] = IndexType(i);
136 return mir;
137 }
138
148 {
149 return VectorMirror(tmpl_vec.size(), 0u);
150 }
151
160 template<int block_size_>
162 {
163 return VectorMirror(tmpl_vec.template size<LAFEM::Perspective::native>(), 0u);
164 }
165
174 {
175 VectorMirror t;
176 t.clone(*this, clone_mode);
177 return t;
178 }
179
188 template<typename DT2_, typename IT2_>
189 void clone(const VectorMirror<DT2_, IT2_> & other, CloneMode clone_mode = CloneMode::Weak)
190 {
191 Container<DT_, IT_>::clone(other, clone_mode);
192 }
193
200 template<typename DT2_, typename IT2_>
202 {
203 this->assign(other);
204 }
205
212 {
213 return this->_scalar_index.empty() ? Index(0) : this->_scalar_index.at(1);
214 }
215
221 bool empty() const
222 {
223 return (this->num_indices() == Index(0));
224 }
225
231 IT_* indices()
232 {
233 return this->_indices.empty() ? nullptr : this->_indices.at(0);
234 }
235
237 const IT_* indices() const
238 {
239 return this->_indices.empty() ? nullptr : this->_indices.at(0);
240 }
241
248 template<typename DT2_, typename IT2_>
249 Index buffer_size(const DenseVector<DT2_, IT2_>& DOXY(vector)) const
250 {
251 return num_indices();
252 }
253
260 template<typename DT2_, typename IT2_, int block_size_>
262 {
263 return num_indices()*Index(block_size_);
264 }
265
272 template<typename DT2_, typename IT2_>
273 Index buffer_size(const SparseVector<DT2_, IT2_>& DOXY(vector)) const
274 {
275 return num_indices();
276 }
277
284 template<typename DT2_, typename IT2_, int block_size_>
286 {
287 return num_indices()*Index(block_size_);
288 }
289
296 template<typename Vector_>
298 {
300 }
301
314 void gather(
317 const Index buffer_offset = Index(0)) const
318 {
319 XASSERT(buffer_offset + this->num_indices() <= buffer.size());
320 XASSERTM(this->size() == vector.size(), "size mismatch between mirror and vector");
321
322 if(this->empty())
323 return;
324
325 LAFEM::Arch::Mirror::gather_dv(
326 buffer_offset, this->num_indices(), this->indices(), buffer.elements(), vector.elements());
327 }
328
347 const DataType alpha = DataType(1),
348 const Index buffer_offset = Index(0)) const
349 {
350 XASSERT(buffer_offset + this->num_indices() <= buffer.size());
351 XASSERTM(this->size() == vector.size(), "size mismatch between mirror and vector");
352
353 if(this->empty())
354 return;
355
356 LAFEM::Arch::Mirror::scatter_dv(
357 buffer_offset, this->num_indices(), this->indices(), buffer.elements(), vector.elements(), alpha);
358 }
359
372 template<int block_size_>
373 void gather(
376 const Index buffer_offset = Index(0)) const
377 {
378 XASSERT(buffer_offset + Index(block_size_)*this->num_indices() <= buffer.size());
379 XASSERTM(this->size() == vector.size(), "size mismatch between mirror and vector");
380
381 if(this->empty())
382 return;
383
384 LAFEM::Arch::Mirror::gather_dvb(
385 Index(block_size_), buffer_offset, this->num_indices(), this->indices(),
386 buffer.elements(), vector.template elements<Perspective::pod>());
387 }
388
404 template<int block_size_>
408 const DataType alpha = DataType(1),
409 const Index buffer_offset = Index(0)) const
410 {
411 XASSERT(buffer_offset + Index(block_size_)*this->num_indices() <= buffer.size());
412 XASSERTM(this->size() == vector.size(), "size mismatch between mirror and vector");
413
414 if(this->empty())
415 return;
416
417 LAFEM::Arch::Mirror::scatter_dvb(
418 Index(block_size_), buffer_offset, this->num_indices(), this->indices(),
419 buffer.elements(), vector.template elements<Perspective::pod>(), alpha);
420 }
421
434 void gather(
437 const Index buffer_offset = Index(0)) const
438 {
439 XASSERT(buffer_offset + this->num_indices() <= buffer.size());
440 XASSERTM(this->size() == vector.size(), "size mismatch between mirror and vector");
441
442 if(this->empty())
443 return;
444
445 LAFEM::Arch::Mirror::gather_sv(
446 buffer_offset, this->num_indices(), this->indices(), buffer.elements(),
447 vector.used_elements(), vector.elements(), vector.indices());
448 }
449
468 const DataType alpha = DataType(1),
469 const Index buffer_offset = Index(0)) const
470 {
471 XASSERT(buffer_offset + this->num_indices() <= buffer.size());
472 XASSERTM(this->size() == vector.size(), "size mismatch between mirror and vector");
473
474 if(this->empty())
475 return;
476
477 LAFEM::Arch::Mirror::scatter_sv(
478 buffer_offset, this->num_indices(), this->indices(), buffer.elements(),
479 vector.used_elements(), vector.elements(), vector.indices(), alpha);
480 }
481
494 template<int block_size_>
495 void gather(
498 const Index buffer_offset = Index(0)) const
499 {
500 XASSERT(buffer_offset + Index(block_size_)*this->num_indices() <= buffer.size());
501 XASSERTM(this->size() == vector.size(), "size mismatch between mirror and vector");
502
503 if(this->empty())
504 return;
505
506 LAFEM::Arch::Mirror::gather_svb(
507 Index(block_size_), buffer_offset, this->num_indices(), this->indices(),buffer.elements(),
508 vector.used_elements(), vector.template elements<Perspective::pod>(), vector.indices());
509 }
510
526 template<int block_size_>
530 const DataType alpha = DataType(1),
531 const Index buffer_offset = Index(0)) const
532 {
533 XASSERT(buffer_offset + Index(block_size_)*this->num_indices() <= buffer.size());
534 XASSERTM(this->size() == vector.size(), "size mismatch between mirror and vector");
535
536 if(this->empty())
537 return;
538
539 LAFEM::Arch::Mirror::scatter_svb(
540 Index(block_size_), buffer_offset, this->num_indices(), this->indices(), buffer.elements(),
541 vector.used_elements(), vector.template elements<Perspective::pod>(), vector.indices(), alpha);
542 }
543
566 template<Perspective perspective_, typename DT2_, typename IT2_>
567 Index mask_scatter(const DenseVector<DT2_, IT2_>& vector, std::vector<int>& mask,
568 const int value, const Index offset = Index(0)) const
569 {
570 XASSERT(Index(mask.size()) >= vector.template size<perspective_>());
571 XASSERT(Index(mask.size()) >= this->size() + offset);
572 const Index n = this->num_indices();
573 const IT_* idx = this->indices();
574
575 for(Index i(0); i < n; ++i)
576 mask[offset + idx[i]] = value;
577
578 return vector.template size<perspective_>();
579 }
580
603 template<Perspective perspective_, typename DT2_, typename IT2_, int block_size_>
605 const int value, const Index offset = Index(0)) const
606 {
607 XASSERT(Index(mask.size()) >= vector.template size<perspective_>());
608 const Index n = this->num_indices();
609 const IT_* idx = this->indices();
610
611 if(perspective_ == LAFEM::Perspective::native)
612 {
613 XASSERT(Index(mask.size()) >= this->size() + offset);
614 for(Index i(0); i < n; ++i)
615 mask[offset + idx[i]] = value;
616 }
617 else // POD
618 {
619 XASSERT(Index(mask.size()) >= Index(block_size_)*this->size() + offset);
620 for(Index i(0); i < n; ++i)
621 {
622 const Index ibs = idx[i] * Index(block_size_);
623 for(int k(0); k < block_size_; ++k)
624 mask[offset + ibs + Index(k)] = value;
625 }
626 }
627 return vector.template size<perspective_>();
628 }
629
630
631 friend std::ostream & operator<< (std::ostream & lhs, const VectorMirror & b)
632 {
633 Index n = b.num_indices();
634 const IT_* idx = b.indices();
635
636 lhs << "[";
637 for (Index i(0) ; i < n ; ++i)
638 {
639 lhs << " " << idx[i];
640 }
641 lhs << "]";
642
643 return lhs;
644 }
645
646 /* ******************************************************************* */
647 /* A D J A C T O R I N T E R F A C E I M P L E M E N T A T I O N */
648 /* ******************************************************************* */
649 public:
652 {
653 return this->num_indices();
654 }
655
658 {
659 return this->size();
660 }
661
663 ImageIterator image_begin(Index domain_node) const
664 {
665 XASSERTM(domain_node < num_indices(), "Domain node index out of range");
666 return &this->_indices.at(0)[domain_node];
667 }
668
670 ImageIterator image_end(Index domain_node) const
671 {
672 XASSERTM(domain_node < num_indices(), "Domain node index out of range");
673 return &this->_indices.at(0)[domain_node+1];
674 }
675 }; // class VectorMirror<...>
676 } // namespace LAFEM
677} // namespace FEAT
#define XASSERT(expr)
Assertion macro definition.
Definition: assertion.hpp:262
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Definition: assertion.hpp:263
Container base class.
Definition: container.hpp:220
Index size() const
Returns the containers size.
Definition: container.hpp:1136
void assign(const Container< DT2_, IT2_ > &other)
Assignment operation.
Definition: container.hpp:280
std::vector< IT_ * > _indices
List of pointers to all IT_ dependent arrays.
Definition: container.hpp:228
void clone(const Container &other, CloneMode clone_mode=CloneMode::Weak)
Clone operation.
Definition: container.hpp:902
void move(Container &&other)
Assignment move operation.
Definition: container.hpp:989
std::vector< Index > _indices_size
List of corresponding IT_ array sizes.
Definition: container.hpp:232
std::vector< Index > _scalar_index
List of scalars with datatype index.
Definition: container.hpp:234
Blocked Dense data vector class template.
Index size() const
The number of elements.
Dense data vector class template.
DT_ * elements()
Get a pointer to the data array.
Sparse vector class template.
Index size() const
The number of elements.
Index used_elements() const
Retrieve non zero element count.
IT_ * indices()
Get a pointer to the non zero indices array.
Sparse vector class template.
DT_ * elements()
Get a pointer to the data array.
IT_ * indices()
Get a pointer to the non zero indices array.
Index used_elements() const
Retrieve non zero element count.
Handles vector prolongation, restriction and serialization.
static VectorMirror make_identity(Index size_in)
Creates and returns an identity mirror.
void gather(LAFEM::DenseVector< DataType, IndexType > &buffer, const LAFEM::SparseVectorBlocked< DataType, IndexType, block_size_ > &vector, const Index buffer_offset=Index(0)) const
Gathers the buffer entries from a SparseVector.
const IT_ * indices() const
Get a pointer to the non zero indices array.
static VectorMirror make_empty(const DenseVector< DT_, IT_ > &tmpl_vec)
Creates and returns an empty mirror.
Index mask_scatter(const DenseVectorBlocked< DT2_, IT2_, block_size_ > &vector, std::vector< int > &mask, const int value, const Index offset=Index(0)) const
Updates a scatter mask vector for this mirror.
void gather(LAFEM::DenseVector< DataType, IndexType > &buffer, const LAFEM::DenseVector< DataType, IndexType > &vector, const Index buffer_offset=Index(0)) const
Gathers the buffer entries from a DenseVector.
Index buffer_size(const DenseVectorBlocked< DT2_, IT2_, block_size_ > &vector) const
Computes the required buffer size for a DenseVectorBlocked.
ImageIterator image_end(Index domain_node) const
Index get_num_nodes_domain() const
void scatter_axpy(LAFEM::SparseVectorBlocked< DataType, IndexType, block_size_ > &vector, const LAFEM::DenseVector< DataType, IndexType > &buffer, const DataType alpha=DataType(1), const Index buffer_offset=Index(0)) const
Scatters the buffer entries onto a SparseVectorBlocked.
void scatter_axpy(LAFEM::SparseVector< DataType, IndexType > &vector, const LAFEM::DenseVector< DataType, IndexType > &buffer, const DataType alpha=DataType(1), const Index buffer_offset=Index(0)) const
Scatters the buffer entries onto a SparseVector.
void gather(LAFEM::DenseVector< DataType, IndexType > &buffer, const LAFEM::SparseVector< DataType, IndexType > &vector, const Index buffer_offset=Index(0)) const
Gathers the buffer entries from a SparseVector.
Index buffer_size(const DenseVector< DT2_, IT2_ > &vector) const
Computes the required buffer size for a DenseVector.
IT_ IndexType
index-type typedef
DenseVector< DataType, IndexType > create_buffer(const Vector_ &vector) const
Creates a new buffer vector for a vector.
VectorMirror(Index size_in, Index num_idx)
Constructor.
VectorMirror()
default constructor
VectorMirror & operator=(VectorMirror &&other)
move-assign operator
void gather(LAFEM::DenseVector< DataType, IndexType > &buffer, const LAFEM::DenseVectorBlocked< DataType, IndexType, block_size_ > &vector, const Index buffer_offset=Index(0)) const
Gathers the buffer entries from a DenseVectorBlocked.
VectorMirror clone(CloneMode clone_mode=CloneMode::Weak) const
Clone operation.
Index buffer_size(const SparseVector< DT2_, IT2_ > &vector) const
Computes the required buffer size for a SparseVector.
Index mask_scatter(const DenseVector< DT2_, IT2_ > &vector, std::vector< int > &mask, const int value, const Index offset=Index(0)) const
Updates a scatter mask vector for this mirror.
void scatter_axpy(LAFEM::DenseVector< DataType, IndexType > &vector, const LAFEM::DenseVector< DataType, IndexType > &buffer, const DataType alpha=DataType(1), const Index buffer_offset=Index(0)) const
Scatters the buffer entries onto a DenseVector.
Index get_num_nodes_image() const
void scatter_axpy(LAFEM::DenseVectorBlocked< DataType, IndexType, block_size_ > &vector, const LAFEM::DenseVector< DataType, IndexType > &buffer, const DataType alpha=DataType(1), const Index buffer_offset=Index(0)) const
Scatters the buffer entries onto a DenseVectorBlocked.
IT_ * indices()
Get a pointer to the non zero indices array.
IT_ * ImageIterator
ImageIterator for Adjactor interface implementation.
static VectorMirror make_empty(const DenseVectorBlocked< DT_, IT_, block_size_ > &tmpl_vec)
Creates and returns an empty mirror.
Index num_indices() const
Returns the number of indices in the mirror.
Index buffer_size(const SparseVectorBlocked< DT2_, IT2_, block_size_ > &vector) const
Computes the required buffer size for a SparseVectorBlocked.
void clone(const VectorMirror< DT2_, IT2_ > &other, CloneMode clone_mode=CloneMode::Weak)
Clone operation.
DT_ DataType
data-type typedef
VectorMirror(VectorMirror &&other)
move-ctor
void convert(const VectorMirror< DT2_, IT2_ > &other)
Conversion method.
bool empty() const
Checks whether the mirror is empty.
Container< DT_, IT_ > BaseClass
our base class
ImageIterator image_begin(Index domain_node) const
FEAT namespace.
Definition: adjactor.hpp:12
@ value
specifies whether the space should supply basis function values
std::uint64_t Index
Index data type.