KASKADE 7 development version
linearspace.hh
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the library KASKADE 7 */
4/* https://www.zib.de/research/projects/kaskade7-finite-element-toolbox */
5/* */
6/* Copyright (C) 2002-2023 Zuse Institute Berlin */
7/* */
8/* KASKADE 7 is distributed under the terms of the ZIB Academic License. */
9/* see $KASKADE/academic.txt */
10/* */
11/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13#ifndef LINEARSPACE_HH
14#define LINEARSPACE_HH
15
16#include <cmath>
17#include <type_traits>
18
19#include <boost/version.hpp>
20#include <boost/fusion/algorithm.hpp>
21#include <boost/fusion/sequence.hpp>
22
23#include "fem/functionspace.hh"
24
25#include "linalg/crsutil.hh"
26
27namespace Kaskade
28{
30 // forward declaration
31 template <class> class VariableSet;
32
33 namespace LinearSpace_Detail
34 {
35
36 template <class Space0, class Space2, int id> struct Copy;
37
38 template <class Space, int id, class VSDescriptions>
39 struct Copy<VariableSet<VSDescriptions>,Space,id>
40 {
41 static void apply(const VariableSet<VSDescriptions>& from, Space& to)
42 {
43 boost::fusion::at_c<id>(to.data) = boost::fusion::at_c<id>(from.data).coefficients();
44 Copy<VariableSet<VSDescriptions>,Space,id-1>::apply(from,to);
45 }
46 };
47
48 template <class Space, class VSDescriptions>
49 struct Copy<VariableSet<VSDescriptions>,Space,0>
50 {
51 static void apply(const VariableSet<VSDescriptions>& from, Space& to)
52 {
53 boost::fusion::at_c<0>(to.data) = boost::fusion::at_c<0>(from.data).coefficients();
54 }
55 };
56 }
58
75 template <class Scalar_, class Seq>
77 {
78 private:
80
81 // forward declarations (definitions at end of file)
82 struct Add;
83 struct Sub;
84 struct Assign;
85 struct ScalarMult;
86 struct Axpy;
87 struct ScalarProduct;
88 template <typename> struct ReadBlock;
89 template <typename> struct WriteBlock;
90
91 public:
93 typedef Scalar_ Scalar;
94 typedef Scalar field_type; // for compatibility with Dune conventions
95
97 typedef Seq Sequence;
98 typedef Seq Functions;
99
103 template <int m>
104 using Component = std::remove_reference_t<typename boost::fusion::result_of::at_c<Sequence const,m>::type>;
105
106
107 // use with care: default constructed subvectors may not be properly initialized (e.g. size?)
109
116
121
123 template <class VSDescriptions>
125 {
126 *this = y;
127 }
128
135 template <class S>
136 explicit LinearProductSpace(S const& init): data(init)
137 {}
138
139 template <typename... Args>
140 explicit LinearProductSpace(boost::fusion::transform_view<Args...> const& data_) : data(data_)
141 {
142 applyUnaryOp(Assign(0));
143 }
144
154 size_t dim() const
155 {
156 return boost::fusion::accumulate(data,0,[](auto dim, auto const& v) { return dim+v.dim(); });
157 }
158
165 Self& operator=(Self const& y) { if (this!=&y) data = y.data; return *this; }
166
168 template <class VSDescriptions>
170 {
171 using namespace boost::fusion;
172 static_assert(result_of::size<Sequence>::type::value == VSDescriptions::noOfVariables,"Numbers of variables do not match.");
174 result_of::size<typename VSDescriptions::RepresentationData>::type::value-1>::apply(y,*this);
175 return *this;
176 } // need not check for self assignment here
177
179 template <class OtherSeq>
181 {
182 using namespace boost::fusion;
183 static_assert(result_of::size<Sequence>::type::value == result_of::size<OtherSeq>::type::value, "Numbers of variables do not match.");
184 data = y.data;
185 return *this;
186 } // need not check for self assignment here
187
189 template <class FunctionSpace, int m>
191 {
192 data = fse.coefficients();
193 return *this;
194 }
195
198 {
199 return applyUnaryOp(Assign(a));
200 }
201
203 template <class First, class Last>
204 Self& operator=(boost::fusion::iterator_range<First,Last> range)
205 {
206 static_assert(boost::fusion::result_of::size<Sequence>::type::value == boost::fusion::result_of::distance<First,Last>::type::value,
207 "Numbers of variables do not match.");
208 data = range;
209 return *this;
210 }
211
213 Self& operator*=(Scalar a) { return applyUnaryOp(ScalarMult(a)); }
214
220 template <class SequenceY>
222 {
223 return applyBinaryOp(Add(),y);
224 }
225
227 Self& operator-=(Self const& y)
228 {
229 return applyBinaryOp(Sub(),y);
230 }
231
233 Self& axpy(Scalar a, Self const& y)
234 {
235 return applyBinaryOp(Axpy(a),y);
236 }
237
244 template <class InIterator>
245 void read(InIterator i) [[deprecated]]
246 {
247 vectorFromSequence(*this,i);
248 }
249
254 template <class InIterator>
255 void read(int rbegin, int rend, InIterator i) { boost::fusion::for_each(data,ReadBlock<InIterator>(rbegin,rend,i)); }
256
263 template <class OutIterator>
264 void write(OutIterator i) const [[deprecated]]
265 {
266 vectorToSequence(*this,i);
267 }
268
273 template <class DataOutIter>
274 void write(int rbegin, int rend, DataOutIter i) const
275 {
276 boost::fusion::for_each(data,WriteBlock<DataOutIter>(rbegin,rend,i));
277 }
278
292 field_type operator*(Self const& y) const
293 {
294 using namespace boost::fusion;
295 zip_view<vector<Sequence const&,Sequence const&> > zipped(vector<Sequence const&,Sequence const&>(data,y.data));
296 field_type s = 0;
297 for_each(zipped,[&](auto const& p) { s += at_c<0>(p) * at_c<1>(p); });
298 return s;
299 }
300
302 field_type dot(Self const& y) const
303 {
304 return *this * y;
305 }
306
310 double two_norm2() const
311 {
312 return (*this)*(*this);
313 }
314
318 double two_norm() const
319 {
320 return std::sqrt(two_norm2());
321 }
322
329
330 private:
331
332 // applies a binary operator to the elements of a pair
333 template <class BinaryOp>
334 struct PairOp
335 {
336 PairOp(BinaryOp const& op_): op(op_) {}
337
338 template <class Pair> void operator()(Pair p) const {
339 op(boost::fusion::at_c<0>(p),boost::fusion::at_c<1>(p));
340 }
341
342 private:
343 BinaryOp const& op;
344 };
345
346 template <class UnaryOp>
347 Self& applyUnaryOp(UnaryOp const& op) {
348 boost::fusion::for_each(data,op);
349 return *this;
350 }
351
352 template <class BinaryOp, class SpaceY>
353 Self& applyBinaryOp(BinaryOp const& op, SpaceY const& y) {
354 using namespace boost::fusion;
355 typedef typename SpaceY::Sequence SequenceY;
356 zip_view<vector<Sequence&,SequenceY const&> > zipped(vector<Sequence&,SequenceY const&>(data,y.data));
357 for_each(zipped,PairOp<BinaryOp>(op));
358 return *this;
359 }
360
361 struct Add { template <class T, class S> void operator()(T& a, S const& b) const { a += b; } };
362 struct Sub { template <class T> void operator()(T& a, T const& b) const { a -= b; } };
363 struct Assign {
364 Assign(Scalar s_): s(s_) {}
365 template <class T> void operator()(T& a) const { a = s; }
366 private: Scalar s;
367 };
368
369
370 struct ScalarMult {
371 ScalarMult(Scalar s_): s(s_) {}
372 template <class Element> void operator()(Element& e) const { e *= s; }
373 private: Scalar s;
374 };
375
376 struct Axpy
377 {
378 Axpy(Scalar s_): s(s_) {}
379 template <class T> void operator()(T& a, T const& b) const {
380
381 // Funny runtime error could only be avoided by this funny code.
382 // Probably a compiler bug.
383 // assert(a.size()==b.size());
384 std::cout << "";
385
386
387 a.axpy(s,b);
388 }
389
390 private: Scalar s;
391 };
392
393 template <class DataOutIter>
394 struct WriteBlock
395 {
396 WriteBlock(int& rbegin_, int& rend_, DataOutIter& out_): rbegin(rbegin_), rend(rend_), out(out_) {}
397 template <class VectorBlock> void operator()(VectorBlock const& v) const
398 {
399 if (rbegin<=0 && rend>0)
400 vectorToSequence(v,out);
401 --rbegin;
402 --rend;
403 }
404 private:
405 int& rbegin;
406 int& rend;
407 DataOutIter& out;
408
409 };
410
411 template <class DataInIter>
412 struct ReadBlock
413 {
414 ReadBlock(int& rbegin_, int& rend_, DataInIter& in_): rbegin(rbegin_), rend(rend_), in(in_) {}
415
416 template <class VectorBlock> void operator()(VectorBlock& v) const
417 {
418 if (rbegin<=0 && rend>0)
419 vectorFromSequence(v,in);
420 --rbegin;
421 --rend;
422 }
423 private:
424 int& rbegin;
425 int& rend;
426 DataInIter& in;
427
428 };
429
430 };
431
432 // ----------------------------------------------------------------------------------------------
433
456 template <int m, class Scalar, class Sequence>
458 {
459 return boost::fusion::at_c<m>(x.data);
460 }
461
462 template <int m, class Scalar, class Sequence>
464 {
465 return boost::fusion::at_c<m>(x.data);
466 }
467
468 // ----------------------------------------------------------------------------------------------
469
470
477 template <class X0, class ...Xs>
478 auto cartesianProduct(X0 const& x0, Xs const&... xs)
479 {
480 using Sequence = boost::fusion::vector<X0,Xs...>;
482 }
483
484 // ----------------------------------------------------------------------------------------------
485
486
492 template <class Scalar, class Seq, class OutIter>
494 {
495 boost::fusion::for_each(v.data,[&](auto& x) { i = vectorToSequence(x,i); });
496 return i;
497 }
498
504 template <class Scalar, class Seq, class InIter>
506 {
507 boost::fusion::for_each(v.data,[&](auto& x) { i = vectorFromSequence(x,i); });
508 return i;
509 }
510
511} // end of namespace Kaskade
512
513
514#endif
A class for representing finite element functions.
StorageType const & coefficients() const
Provides read-only access to the coefficients of the finite element basis functions.
Self & axpy(Scalar a, Self const &y)
this <- this + a*y
Definition: linearspace.hh:233
LinearProductSpace(S const &init)
Constructor with explicit data.
Definition: linearspace.hh:136
void read(int rbegin, int rend, InIterator i)
Reads the coefficients of the subrange [rbegin,rend[ sequentially from an input iterator....
Definition: linearspace.hh:255
LinearProductSpace(LinearProductSpace< Scalar, Sequence > &&y)
Move constructor.
Definition: linearspace.hh:120
Self & operator+=(LinearProductSpace< Scalar, SequenceY > const &y)
In place addition.
Definition: linearspace.hh:221
Self & operator=(boost::fusion::iterator_range< First, Last > range)
Assignment from a (hopefully compatible) boost::fusion iterator range.
Definition: linearspace.hh:204
void read(InIterator i)
DEPRECATED use vectorFromSequence instead.
Definition: linearspace.hh:245
Self & operator=(VariableSet< VSDescriptions > const &y)
Assignment from a different (hopefully compatible) type.
Definition: linearspace.hh:169
LinearProductSpace(boost::fusion::transform_view< Args... > const &data_)
Definition: linearspace.hh:140
Self & operator*=(Scalar a)
Scaling.
Definition: linearspace.hh:213
size_t dim() const
Number of scalar degrees of freedom. This computes the total number of degrees of freedom,...
Definition: linearspace.hh:154
LinearProductSpace(LinearProductSpace< Scalar, Sequence > const &y)
Copy constructor.
Definition: linearspace.hh:115
Self & operator=(FunctionSpaceElement< FunctionSpace, m > const &fse)
Assignment from a (hopefully compatible) FunctionSpaceElement.
Definition: linearspace.hh:190
field_type operator*(Self const &y) const
Scalar product.
Definition: linearspace.hh:292
Self & operator=(LinearProductSpace< Scalar, OtherSeq > const &y)
Assignment from a different (hopefully compatible) type.
Definition: linearspace.hh:180
Scalar_ Scalar
scalar type
Definition: linearspace.hh:93
Self & operator=(Scalar a)
Assignment to constant scalar.
Definition: linearspace.hh:197
void write(int rbegin, int rend, DataOutIter i) const
Writes the coefficients of the subrange [rbegin,rend[ sequentially to an output iterator....
Definition: linearspace.hh:274
field_type dot(Self const &y) const
Scalar product.
Definition: linearspace.hh:302
Self & operator-=(Self const &y)
In place subtraction.
Definition: linearspace.hh:227
double two_norm2() const
squared euclidean norm
Definition: linearspace.hh:310
LinearProductSpace(const VariableSet< VSDescriptions > &y)
Copy from VariableSet.
Definition: linearspace.hh:124
std::remove_reference_t< typename boost::fusion::result_of::at_c< Sequence const, m >::type > Component
The type of the m-th component.
Definition: linearspace.hh:104
void write(OutIterator i) const
DEPRECATED use vectorToSequence instead.
Definition: linearspace.hh:264
Seq Sequence
boost::fusion::vector of element vectors.
Definition: linearspace.hh:97
double two_norm() const
euclidean norm
Definition: linearspace.hh:318
Self & operator=(Self const &y)
Assignment from the same type.
Definition: linearspace.hh:165
A class for storing a heterogeneous collection of FunctionSpaceElement s.
Definition: variables.hh:341
FEFunctionSpace and FunctionSpaceElement and the like.
OutIter vectorToSequence(LinearProductSpace< Scalar, Seq > const &v, OutIter i)
writes the coefficients of a vector to a flat scalar sequence <Scalar,Seq>
Definition: linearspace.hh:493
auto const & component(LinearProductSpace< Scalar, Sequence > const &x)
Provides access to the m-th component of a product space.
Definition: linearspace.hh:457
InIter vectorFromSequence(LinearProductSpace< Scalar, Seq > &v, InIter i)
reads the coefficients of a vector from a flat scalar sequence <Scalar,Seq>
Definition: linearspace.hh:505
auto cartesianProduct(X0 const &x0, Xs const &... xs)
Creates a cartesian product of the given vectors, i.e. a LinearProductSpace object.
Definition: linearspace.hh:478
auto & component(LinearProductSpace< Scalar, Sequence > &x)
Definition: linearspace.hh:463
static void apply(const VariableSet< VSDescriptions > &from, Space &to)
Definition: linearspace.hh:51
static void apply(const VariableSet< VSDescriptions > &from, Space &to)
Definition: linearspace.hh:41