KASKADE 7 development version
istlinterface.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-2018 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 ISTLINTERFACE_HH
14#define ISTLINTERFACE_HH
15
16#include <memory>
17#include <type_traits>
18
19#include <boost/fusion/algorithm.hpp>
20#include <boost/fusion/sequence.hpp>
21
22#include <dune/istl/operators.hh>
23#include "dune/istl/preconditioners.hh"
24
25#include "fem/fixdune.hh"
26#include "fem/functionspace.hh"
27#include "fem/linearspace.hh"
28
29#include "linalg/triplet.hh"
30#include "linalg/crsutil.hh"
34
36
37//---------------------------------------------------------------------
38
39namespace Kaskade
40{
44 namespace IstlInterfaceDetail {
45
46 template <class T>
47 typename T::iterator begin(T& t)
48 {
49 return t.begin();
50 }
51
52 template <class T>
53 typename T::const_iterator begin(T const& t)
54 {
55 return t.begin();
56 }
57
58 template <class Scalar>
59 typename std::vector<Scalar>::iterator begin(std::vector<Scalar>& vec) { return vec.begin(); }
60
61 template <class Scalar>
62 typename std::vector<Scalar>::const_iterator begin(std::vector<Scalar> const& vec) { return vec.begin(); }
63
64 using namespace boost::fusion;
65
66
78 template <class ElementType, class SparseIdx, int rid, int cid, bool sym, bool trans>
79 struct Block
80 {
81 static int const rowId = rid; // row index of the block
82 static int const colId = cid; // col index of the block
83 static bool const symmetric = sym; // symmetry
84 static bool const transposed = trans; // whether only its mirror image is available in the assembler
85
86 typedef ElementType BlockType;
87 using SparseIndex = SparseIdx;
88 typedef typename BlockType::field_type Scalar;
89 typedef NumaBCRSMatrix<typename Transpose<BlockType,transposed>::type,SparseIndex> Matrix; // Matrix type in assembler
90 typedef Dune::BlockVector<Dune::FieldVector<Scalar,BlockType::cols>> Domain; // take care of transposition
92 typedef NumaBCRSMatrix<BlockType,SparseIndex> TMatrix;
93
94 explicit Block(std::shared_ptr<Matrix const> const& m): matrix(m) {}
95
96 std::shared_ptr<Matrix const> matrix;
97 std::shared_ptr<TMatrix> threadedMatrix;
98 };
99
100 // Provides a heterogeneous sequence of all matrix blocks appearing
101 // conceptually in the Galerkin operator, even if they are not stored
102 // explicitly in the assembler because of symmetry.
103 template <class GOP>
104 class AllBlocks
105 {
106 struct Copy
107 {
108 template <class MBlock>
109 auto operator()(MBlock const& mb) const {
110 typedef std::remove_reference_t<MBlock> MB;
111 typedef Block<typename MB::BlockType,typename MB::SparseIndex,MB::rowId,MB::colId,MB::symmetric,false> type;
112 return type(mb.globalMatrixPointer());
113 }
114 };
115
116 // Filters out flagged blocks with row index -1
117 struct Cleanup {
118 template <class MB> struct apply { typedef boost::mpl::bool_<MB::rowId>=0> type; };
119 };
120
121 // Blocks not to be mirrored are flagged with row index -1 to be filtered out later by Cleanup.
122 struct Mirror
123 {
124 template <class T> struct result {};
125
126 template <class MBlock>
127 struct result<Mirror(MBlock)> {
128 typedef typename std::remove_reference<MBlock>::type MB;
129 typedef typename Transpose<typename MB::BlockType,true>::type ElementType;
130 typedef Block<ElementType, typename MB::SparseIndex,
131 MB::mirror?MB::colId:-1, MB::rowId, MB::symmetric, true> type;
132 };
133
134 template <class MB>
135 typename result<Mirror(MB)>::type operator()(MB const& mb) const {
136 return typename result<Mirror(MB)>::type(mb.globalMatrixPointer());
137 }
138 };
139
140 // It would be more natural to filter the mirror blocks before
141 // actually mirroring them, but this does frequently result in empty
142 // filter lists. For some reasons (don't know why), the filter view
143 // produces wrong type results when empty lists occur.
144
145 typedef typename result_of::transform<typename GOP::MatrixBlockArray const,Copy>::type CopiedBlocks;
146 typedef typename result_of::transform<typename GOP::MatrixBlockArray const,Mirror>::type MirroredBlocks;
147 typedef typename result_of::join<CopiedBlocks const,MirroredBlocks const>::type JointBlocks;
148
149
150 public:
151 typedef typename result_of::filter_if<JointBlocks const,Cleanup>::type const A;
152 typedef typename result_of::as_vector<A>::type result;
153
154 static result apply(GOP const& op) {
155 return filter_if<Cleanup>(join(transform(op.getMatrix(),Copy()),transform(op.getMatrix(),Mirror())));
156 }
157 };
158
159 // A boost fusion predicate that is true for some matrix block if it
160 // lies within the half-open subrange given by the template
161 // parameters.
162 template <int firstRow, int lastRow, int firstCol, int lastCol>
163 struct RangeBlockSelector
164 {
165 template <class Block> struct apply
166 {
167 typedef boost::mpl::bool_<firstRow<=Block::rowId && Block::rowId<lastRow && firstCol<=Block::colId && Block::colId<lastCol> type;
168 };
169 };
170
171 // Shifts row and column indices of matrix blocks downwards and initializes the threaded matrix held by this block.
172 template <int firstRow, int firstCol>
173 struct Translate
174 {
175 // Constructor takes the number of threads onto which the threaded matrix shall be distributed.
176 // As a conservative default, this is 1 (sequential).
177 Translate(int nThreads_=1): nThreads(nThreads_)
178 {
179 }
180
181 template <class T> struct result {};
182
183 template <class Blk>
184 struct result<Translate(Blk)> {
185 typedef typename std::remove_reference<Blk>::type Bl;
186 typedef Block<typename Bl::BlockType,typename Bl::SparseIndex,Bl::rowId-firstRow,Bl::colId-firstCol,Bl::symmetric,Bl::transposed> type;
187 };
188
189 template <class Bl>
190 auto operator()(Bl const& bl) const
191 {
192 Block<typename Bl::BlockType,typename Bl::SparseIndex,Bl::rowId-firstRow,Bl::colId-firstCol,Bl::symmetric,Bl::transposed> blk(bl.matrix);
193 blk.threadedMatrix.reset(new typename Bl::TMatrix(*blk.matrix,bl.symmetric,bl.transposed,false));
194 return blk;
195 }
196
197 private:
198 int nThreads;
199 };
200
202
205 template <class FSElement, class Vector>
206 typename std::enable_if<!std::is_same<FSElement,Vector>::value,void>::type
207 toVector(FSElement const& x, Vector& coefficients)
208 {
209 coefficients.resize(x.dim());
210 vectorToSequence(x,begin(coefficients));
211 }
212
214 template <class FSElement, class Vector>
215 typename std::enable_if<std::is_same<FSElement,Vector>::value,void>::type
216 toVector(FSElement const& x, Vector& coefficients)
217 {
218 coefficients = x;
219 }
220
225 template <class FSElement, class Vector>
226 typename std::enable_if<!std::is_same<FSElement,Vector>::value,void>::type
227 fromVector(Vector const& coefficients, FSElement& x)
228 {
229 assert(coefficients.size()>=x.dim());
230 vectorFromSequence(x,begin(coefficients));
231 }
232
234 template <class FSElement, class Vector>
235 typename std::enable_if<std::is_same<FSElement,Vector>::value,void>::type
236 fromVector(Vector const& coefficients, FSElement& x)
237 {
238 x = coefficients;
239 }
240
241
242 template <class T>
243 void toFile(std::vector<T> const& v, std::string const& filename, size_t precision = 10)
244 {
245 std::ofstream os;
246 os.precision(precision);
247 os.open(filename);
248
249 for(T t : v) os << t << "\t";
250 os << std::endl;
251
252 os.close();
253 }
254
255
256 // Container storing information on blocks
257 template <int firstRow_, int lastRow_, int firstCol_,int lastCol_>
258 struct BlockInfo
259 {
260 static int const firstRow = firstRow_;
261 static int const lastRow = lastRow_;
262 static int const firstCol = firstCol_;
263 static int const lastCol = lastCol_;
264 };
265 } // End of namespace IstlInterfaceDetail
266
271 //---------------------------------------------------------------------
272
273/* template <class Operator>
274 class TransposedOperator
275 {
276 public:
277 typedef typename Operator::Domain Range;
278 typedef typename Operator::Range Domain;
279 typedef typename Operator::Scalar Scalar;
280
281 explicit TransposedOperator(Operator const& A_) : A(A_) {}
282
283 void apply(const Domain &x, Range &b) const { return A.applyTransposed(x,b); }
284
285 void applyscaleadd(Scalar alpha, Domain const& x, Range& b) const { return A.applyscaleaddTransposed(alpha,x,b); }
286
287 Operator const& getOperator() const { return A; }
288
289 private:
290 Operator const& A;
291 };
292*/
293
294
310 template <class Matrix_, class Domain_, class Range_> class [[deprecated]] MatrixRepresentedOperator;
311
312 template <class Scalar_, class SparseInt, class Domain_, class Range_>
313 class [[deprecated]] MatrixRepresentedOperator<MatrixAsTriplet<Scalar_,SparseInt>,Domain_,Range_>
314 : public Dune::LinearOperator<Domain_,Range_>
315 {
316 public:
318 typedef Matrix matrix_type; // for compatibility with Dune::MatrixAdapter
319 typedef Domain_ Domain;
320 typedef Range_ Range;
321 typedef Scalar_ Scalar;
322
323
325
326 explicit MatrixRepresentedOperator(Matrix const& A_) : A(A_)
327 {}
328
329 explicit MatrixRepresentedOperator(Matrix&& A_) : A(A_)
330 {}
331
332 MatrixAsTriplet<Scalar,SparseInt> getTriplet() const { return get<MatrixAsTriplet<Scalar,SparseInt> >(); }
333
335 template <class OtherMatrix=Matrix>
336 typename std::enable_if<std::is_same<Matrix,OtherMatrix>::value, Matrix const&>::type get() const { return A; }
337
338 Matrix& get_non_const() { return A; }
339
341
344 template <class OtherMatrix>
345 typename std::enable_if<!std::is_same<Matrix,OtherMatrix>::value, OtherMatrix>::type get() const { return OtherMatrix(A); }
346
348 void apply(Domain const& x, Range& b) const
349 {
350 std::vector<Scalar> tmpx, tmpb(A.nrows(),0.0);
351 domainToVector(x,tmpx);
352
353 A.mv(tmpx,tmpb);
354
355 vectorToRange(tmpb,b);
356 }
357
358 void applyTransposed(Range const& x, Domain& b) const
359 {
360 std::vector<Scalar> tmpx, tmpb(A.ncols(),0.0);
361 domainToVector(x,tmpx);
362
363 A.mtv(tmpx,tmpb);
364
365 vectorToRange(tmpb,b);
366 }
367
369 template <class OtherMatrix=Matrix>
370 typename std::enable_if<std::is_same<OtherMatrix,Matrix>::value,std::unique_ptr<Matrix> >::type getPointer() const
371 {
372 return std::unique_ptr<Matrix>(new Matrix(A));
373 }
374
376 template <class OtherMatrix>
377 typename std::enable_if<std::is_same<OtherMatrix,Dune::BCRSMatrix<Dune::FieldMatrix<Scalar,1,1> > >::value,std::unique_ptr<OtherMatrix> >::type getPointer() const
378 {
379 return A.toBCRS();
380 }
381
383 void applyscaleadd(Scalar alpha, Domain const& x, Range& b) const
384 {
385// A.usmv(alpha,x,b);
386 std::vector<Scalar> tmpx, tmpb;
387 domainToVector(x,tmpx);
388 rangeToVector(b,tmpb);
389
390 A.usmv(alpha,tmpx, tmpb);
391
392 vectorToRange(tmpb,b);
393 }
394
395 void applyscaleaddTransposed(Scalar alpha, Range const& x, Domain& b) const
396 {
397// A.usmv(alpha,x,b);
398 std::vector<Scalar> tmpx, tmpb;
399 domainToVector(x,tmpx);
400 rangeToVector(b,tmpb);
401
402 A.usmtv(alpha,tmpx, tmpb);
403
404 vectorToRange(tmpb,b);
405 }
407
415 template <class Vector>
416 void rangeToVector(Range const& y, Vector& coefficients) const
417 {
418 IstlInterfaceDetail::toVector(y,coefficients);
419 }
420
422
430 template <class Vector>
431 void domainToVector(Domain const& x, Vector& coefficients) const
432 {
433 IstlInterfaceDetail::toVector(x, coefficients);
434 }
435
437
445 template <class Vector>
446 void vectorToDomain(Vector const& coefficients, Domain& x) const
447 {
448 IstlInterfaceDetail::fromVector(coefficients, x);
449 }
450
452
460 template <class Vector>
461 void vectorToRange(Vector const& coefficients, Range& x) const
462 {
463 IstlInterfaceDetail::fromVector(coefficients, x);
464 }
465
467
469 {
470 A = B; return *this;
471 }
472
474 {
475 A *= alpha; return *this;
476 }
477
479 {
480 A /= alpha; return *this;
481 }
482
484 {
485 A += B; return *this;
486 }
487
488 MatrixRepresentedOperator& operator+= (Matrix const& B)
489 {
490 A += B; return *this;
491 }
492
494 {
495 A -= B; return *this;
496 }
497
498 MatrixRepresentedOperator& operator-= (Matrix const& B)
499 {
500 A -= B; return *this;
501 }
502
508 virtual Dune::SolverCategory::Category category() const override
509 {
510 return Dune::SolverCategory::sequential;
511 }
512
513 private:
514 Matrix A;
515 };
516
517 template <class MatrixBlock, class Allocator, class Domain_, class Range_>
518 class [[deprecated]] MatrixRepresentedOperator<Dune::BCRSMatrix<MatrixBlock,Allocator>,Domain_,Range_>
519 : public Dune::LinearOperator<Domain_,Range_>
520 {
521 public:
522 typedef Dune::BCRSMatrix<MatrixBlock,Allocator> Matrix;
523 typedef Domain_ Domain;
524 typedef Range_ Range;
526
527
529
530 explicit MatrixRepresentedOperator(Matrix const& A_) : A(A_)
531 {}
532
533 explicit MatrixRepresentedOperator(Matrix&& A_) : A(A_)
534 {}
535
536 MatrixAsTriplet<Scalar> getTriplet() const { return get<MatrixAsTriplet<Scalar> >(); }
537
539 template <class OtherMatrix=Matrix>
540 typename std::enable_if<std::is_same<Matrix,OtherMatrix>::value, Matrix const&>::type get() const { return A; }
541
542 Matrix& get_non_const() { return A; }
543
545
548 template <class OtherMatrix>
549 typename std::enable_if<!std::is_same<Matrix,OtherMatrix>::value, OtherMatrix>::type get() const { return OtherMatrix(A); }
550
552 void apply(Domain const& x, Range& b) const
553 {
554 A.mv(x,b);
555 }
556
557 void applyTransposed(Range const& x, Domain& b) const
558 {
559 A.mtv(x,b);
560 }
561
563 template <class OtherMatrix=Matrix>
564 typename std::enable_if<std::is_same<OtherMatrix,Matrix>::value,std::unique_ptr<Matrix> >::type getPointer() const
565 {
566 return std::unique_ptr<Matrix>(new Matrix(A));
567 }
568
570 template <class OtherMatrix>
571 typename std::enable_if<std::is_same<OtherMatrix,Dune::BCRSMatrix<Dune::FieldMatrix<Scalar,1,1> > >::value,std::unique_ptr<OtherMatrix> >::type getPointer() const
572 {
573 return A.toBCRS();
574 }
575
577 void applyscaleadd(Scalar alpha, Domain const& x, Range& b) const
578 {
579 A.usmv(alpha,x,b);
580 }
581
582 void applyscaleaddTransposed(Scalar alpha, Range const& x, Domain& b) const
583 {
584 A.usmtv(alpha,x,b);
585 }
586
588
596 template <class Vector> void rangeToVector(Range const& y, Vector& coefficients) const
597 {
598 IstlInterfaceDetail::toVector(y,coefficients);
599 }
600
602
610 template <class Vector> void domainToVector(Domain const& x, Vector& coefficients) const
611 {
612 IstlInterfaceDetail::toVector(x, coefficients);
613 }
614
616
624 template <class Vector>
625 void vectorToDomain(Vector const& coefficients, Domain& x) const
626 {
627 IstlInterfaceDetail::fromVector(coefficients, x);
628 }
629
631
639 template <class Vector>
640 void vectorToRange(Vector const& coefficients, Range& x) const
641 {
642 IstlInterfaceDetail::fromVector(coefficients, x);
643 }
644
646
648 {
649 A = B; return *this;
650 }
651
653 {
654 A *= alpha; return *this;
655 }
656
658 {
659 A /= alpha; return *this;
660 }
661
663 {
664 A += B; return *this;
665 }
666
667 MatrixRepresentedOperator& operator+= (Matrix const& B)
668 {
669 A += B; return *this;
670 }
671
673 {
674 A -= B; return *this;
675 }
676
677 MatrixRepresentedOperator& operator-= (Matrix const& B)
678 {
679 A -= B; return *this;
680 }
681
687 virtual Dune::SolverCategory::Category category() const override
688 {
689 return Dune::SolverCategory::sequential;
690 }
691
692 private:
693 Matrix A;
694 };
695
696 //-----------------------------------------------------------------------------------------------
697
699 namespace IstlInterfaceDetail
700 {
701
702 // A traits class for determining the correct base class for an assembled Galerkin operator.
703 // For variational functionals (i.e. symmetric problems), this is SymmetricLinearOperator,
704 // otherwise Dune::LinearOperator.
705 template <class Assembler,
706 int firstRow, int lastRow,
707 int firstCol, int lastCol,
708 bool symmetric=false>
709 struct Base
710 {
711 typedef typename Assembler::AnsatzVariableSetDescription::template CoefficientVectorRepresentation<firstCol,lastCol>::type Domain;
712 typedef typename Assembler::TestVariableSetDescription::template CoefficientVectorRepresentation<firstRow,lastRow>::type Range;
713
714 static bool const inferredSymmetry
715 = (Assembler::Functional::type==VariationalFunctional // a diagonally-centered block of a symmetric block matrix
716 && firstRow==firstCol && lastRow==lastCol)
717 || (firstRow+1==lastRow && firstCol+1==lastCol && false); /* true if this one block is symmetric */ // TODO: implement the symmetry check
718
719 using type = std::conditional_t<symmetric,
720 SymmetricLinearOperator<Domain,Range>,
721 Dune::LinearOperator<Domain,Range>>;
722 };
723 } // end of namespace IstlInterfaceDetail
725
726
727
751 template <class Assembler_,
752 int firstRow=0, int lastRow=Assembler_::TestVariableSetDescription::noOfVariables,
753 int firstCol=0, int lastCol=Assembler_::AnsatzVariableSetDescription::noOfVariables,
754 class BlockFilter=IstlInterfaceDetail::RangeBlockSelector<firstRow,lastRow,firstCol,lastCol>,
755 bool symmetric=IstlInterfaceDetail::Base<Assembler_,firstRow,lastRow,firstCol,lastCol>::inferredSymmetry>
757 : public IstlInterfaceDetail::Base<Assembler_,firstRow,lastRow,firstCol,lastCol,symmetric>::type
758 {
759 public:
760 typedef typename IstlInterfaceDetail::Base<Assembler_,firstRow,lastRow,firstCol,lastCol,symmetric>::type Base;
761 typedef Assembler_ Assembler;
762 using Domain = typename Assembler::AnsatzVariableSetDescription::template CoefficientVector<firstCol,lastCol>;
763 using Range = typename Assembler::TestVariableSetDescription::template CoefficientVector<firstRow,lastRow>;
764 typedef typename Assembler::Scalar Scalar;
765
766 typedef IstlInterfaceDetail::BlockInfo<firstRow,lastRow,firstCol,lastCol> BlockInfo;
767
768
775 explicit AssembledGalerkinOperator(Assembler const& assembler_,
776 bool onlyLowerTriangle_=false, int nThreads_=0):
777 onlyLowerTriangle(onlyLowerTriangle_),
778 assembler(assembler_),
779 blocks(boost::fusion::transform(boost::fusion::filter_if<BlockFilter>(IstlInterfaceDetail::AllBlocks<Assembler>::apply(assembler)),
780 IstlInterfaceDetail::Translate<firstRow,firstCol>(nThreads_))),
781 nThreads(nThreads_)
782 { }
783
785
787 void update()
788 {
789 using namespace boost::fusion;
790 blocks = transform(filter_if<BlockFilter>(IstlInterfaceDetail::AllBlocks<Assembler>::apply(assembler)),
791 IstlInterfaceDetail::Translate<firstRow,firstCol>(nThreads));
792 }
793
797 virtual MatrixAsTriplet<Scalar> getTriplet() const __attribute__((deprecated))
798 { return get<MatrixAsTriplet<Scalar>>(); }
799
813 template <class Matrix>
814 Matrix get(int rowFirst=0, int rowLast=lastRow-firstRow, int colFirst=0, int colLast=lastCol-firstCol) const
815 {
816 return assembler.template get<Matrix>(onlyLowerTriangle, firstRow, lastRow, firstCol, lastCol);
817 }
818
820 template <class Matrix>
821 std::unique_ptr<Matrix> getPointer() const
822 {
823 return assembler.template getPointer<Matrix,firstRow,lastRow,firstCol,lastCol>(onlyLowerTriangle);
824 }
825
829 MatrixAsTriplet<Scalar> getmat() const __attribute__((deprecated));
830
841 template <class Vector>
842 void rangeToVector(Range const& y, Vector& coefficients) const
843 {
844 IstlInterfaceDetail::toVector(y, coefficients);
845 }
846
857 template <class Vector>
858 void domainToVector(Domain const& x, Vector& coefficients) const
859 {
860 IstlInterfaceDetail::toVector(x, coefficients);
861 }
862
864
872 template <class Vector>
873 void vectorToDomain(Vector const& coefficients, Domain& x) const
874 {
875 IstlInterfaceDetail::fromVector(coefficients, x);
876 }
877
887 template <class Vector>
888 void vectorToRange(Vector const& coefficients, Range& x) const
889 {
890 IstlInterfaceDetail::fromVector(coefficients, x);
891 }
892
899 virtual void apply(Domain const& x, Range& b) const
900 {
901 assert(static_cast<void const*>(&x) != static_cast<void const*>(&b));
902 boost::fusion::for_each(blocks,ApplyScaleAdd(assembler,1.0,x,b,true));
903 }
904
908 void applyTransposed(Range const& x, Domain& b) const
909 {
910 assert(static_cast<void const*>(&x) != static_cast<void const*>(&b));
911 boost::fusion::for_each(blocks,TransposedApplyScaleAdd(assembler,1.0,x,b,true));
912 }
913
919 virtual Scalar applyDp(Domain const& x, Range& b) const
920 {
921 assert(static_cast<void const*>(&x) != static_cast<void const*>(&b));
922 Scalar dp = 0;
923 boost::fusion::for_each(blocks,ApplyScaleAdd(assembler,1.0,x,b,true,&dp));
924 return symmetric? dp: 0;
925 }
926
927 virtual Scalar dp(Domain const& x, Range const& y) const
928 {
929 std::cerr << "AssembledGalerkinOperator::dp not yet implemented!\n"; abort();
930 return 0; // TODO: fixme
931 }
932
938 virtual void applyscaleadd(Scalar alpha, Domain const& x, Range& b) const
939 {
940 assert(static_cast<void const*>(&x) != static_cast<void const*>(&b));
941 boost::fusion::for_each(blocks,ApplyScaleAdd(assembler,alpha,x,b,false));
942 }
943
949 virtual void applyscaleaddTransposed(Scalar alpha, Range const& x, Domain& b) const
950 {
951 assert(static_cast<void const*>(&x) != static_cast<void const*>(&b));
952 boost::fusion::for_each(blocks,TransposedApplyScaleAdd(assembler,alpha,x,b,false));
953 }
954
962 Assembler const& getAssembler() const
963 {
964 return assembler;
965 }
966
970 template <int i>
971 auto const& ansatzSpace() const
972 {
973 static_assert(0<=i && i<lastCol-firstCol,"ansatz variable index out of range");
974 int const varIdx = i-firstCol;
975 int const spaceIdx = Assembler::AnsatzVariableSetDescription::template spaceIndex<i>;
976 return *boost::fusion::at_c<spaceIdx>(assembler.spaces());
977 }
978
980
986 virtual Dune::SolverCategory::Category category() const override
987 {
988 return Dune::SolverCategory::sequential;
989 }
990
991 protected:
992 typedef typename boost::fusion::result_of::as_vector<
993 typename IstlInterfaceDetail::AllBlocks<Assembler>::result
994 >::type allblocks;
995
996 typedef typename boost::fusion::result_of::as_vector<
997 typename boost::fusion::result_of::filter_if<allblocks,BlockFilter>::type
998 >::type filtered;
999
1002
1003 typename boost::fusion::result_of::as_vector<
1004 typename boost::fusion::result_of::transform<filtered,
1005 IstlInterfaceDetail::Translate<firstRow,firstCol>>::type
1006 >::type blocks;
1008
1009
1011 {
1013 // Constructs the functor for matrix-vector multiplication and addition. If init is true, the first block
1014 // encountered in each row is called with apply (using alpha=1 and initializing the rhs to zero), otherwise
1015 // applyscaleadd is used. This prevents a double access of the right hand side, first for setting to zero,
1016 // then for adding the MV product.
1017 ApplyScaleAdd(Assembler const& as, Scalar a_, Domain const& x_, Range& y_, bool init, Scalar* dp_=0)
1018 : assembler(as)
1019 , a(a_)
1020 , x(x_)
1021 , y(y_)
1022 , dp(dp_? dp_: &dummy)
1023 {
1024 for (int i=0; i<lastRow; ++i)
1025 doInit[i] = init;
1026 *dp = 0;
1027 }
1028
1029 template <class Block>
1030 void operator()(Block const& b) const
1031 {
1032 using namespace boost::fusion;
1033
1034 auto const& xi = component<Block::colId>(x);
1035 auto & yi = component<Block::rowId>(y);
1036 if (!b.threadedMatrix.get())
1037 abort();
1038
1039 if (doInit[Block::rowId])
1040 {
1041 *dp += b.threadedMatrix->mv(xi,yi);
1042 doInit[Block::rowId] = false;
1043 }
1044 else
1045 *dp += b.threadedMatrix->usmv(a,xi,yi);
1046 }
1047
1048 private:
1049 Scalar a;
1050 Domain const& x;
1051 Range& y;
1052 Scalar* dp;
1053 Scalar dummy; // something to point to in case no target pointer has been provided
1054 mutable bool doInit[lastRow]; // ugly, but boost::fusion::for_each only works with const functors
1055 };
1056
1058 {
1060 // Constructs the functor for matrix-vector multiplication and addition. If init is true, the first block
1061 // encountered in each row is called with apply (using alpha=1 and initializing the rhs to zero), otherwise
1062 // applyscaleadd is used. This prevents a double access of the right hand side, first for setting to zero,
1063 // then for adding the MV product.
1064 TransposedApplyScaleAdd(Assembler const& as, Scalar a_, Range const& x_, Domain& y_, bool init, Scalar* dp_=0): assembler(as), a(a_), x(x_), y(y_), dp(dp_? dp_: &dummy)
1065 {
1066 for (int i=0; i<lastCol; ++i)
1067 doInit[i] = init;
1068 *dp = 0;
1069 }
1070
1071 template <class Block>
1072 void operator()(Block const& b) const {
1073 using namespace boost::fusion;
1074
1075 typename result_of::at_c<typename Range::Functions const,Block::rowId>::type xi = at_c<Block::rowId>(x.data);
1076 typename result_of::at_c<typename Domain::Functions,Block::colId>::type yi = at_c<Block::colId>(y.data);
1077 if (!b.threadedMatrix.get())
1078 abort();
1079
1080 if (doInit[Block::colId])
1081 {
1082 *dp += b.threadedMatrix->mv(xi,yi);
1083 doInit[Block::colId] = false;
1084 }
1085 else
1086 *dp += b.threadedMatrix->usmv(a,xi,yi);
1087
1088 return;
1089 }
1090
1091 private:
1092 Scalar a;
1093 Range const& x;
1094 Domain& y;
1095 Scalar* dp;
1096 Scalar dummy; // something to point to in case no target pointer has been provided
1097 mutable bool doInit[lastCol]; // ugly, but boost::fusion::for_each only works with const functors
1098 };
1099
1101 };
1102
1107 template <class Assembler,
1108 int firstRow=0, int lastRow=Assembler::TestVariableSetDescription::noOfVariables,
1109 int firstCol=0, int lastCol=Assembler::AnsatzVariableSetDescription::noOfVariables>
1112 {
1114 }
1115
1116 // -------------------------------------------------------------------------------------------------------
1117 // -------------------------------------------------------------------------------------------------------
1118
1119
1123 template <class NormalStepAssembler, class TangentialStepAssembler, int stateId=1, int controlId=0, int adjointId=2>
1124 class LagrangeOperator: public Dune::LinearOperator<typename NormalStepAssembler::AnsatzVariableSetDescription::template CoefficientVectorRepresentation<>::type,typename NormalStepAssembler::TestVariableSetDescription::template CoefficientVectorRepresentation<>::type>
1125 {
1126 typedef typename NormalStepAssembler::AnsatzVariableSetDescription::template CoefficientVectorRepresentation<>::type Domain;
1127 typedef typename NormalStepAssembler::TestVariableSetDescription::template CoefficientVectorRepresentation<>::type Range;
1128 static constexpr int firstRow = 0;
1129 static constexpr int firstCol = 0;
1130 static constexpr int lastRow = NormalStepAssembler::TestVariableSetDescription::noOfVariables;
1131 static constexpr int lastCol = NormalStepAssembler::AnsatzVariableSetDescription::noOfVariables;
1132 typedef IstlInterfaceDetail::RangeBlockSelector<firstRow,lastRow,firstCol,lastCol> NormalStepBlockFilter;
1133 typedef IstlInterfaceDetail::RangeBlockSelector<firstRow,adjointId,firstCol,adjointId> TangentialStepBlockFilter;
1134
1135 public:
1136 typedef typename NormalStepAssembler::Scalar Scalar;
1138
1139 typedef IstlInterfaceDetail::BlockInfo<firstRow,lastRow,firstCol,lastCol> BlockInfo;
1140
1141 static int const category = Dune::SolverCategory::sequential;
1142
1148 LagrangeOperator(NormalStepAssembler const& normalStepAssembler_, TangentialStepAssembler const& tangentialStepAssembler_, bool onlyLowerTriangle_=false, int nThreads_=0):
1149 onlyLowerTriangle(onlyLowerTriangle_),
1150 normalStepAssembler(normalStepAssembler_), tangentialStepAssembler(tangentialStepAssembler_),
1151 normalStepBlocks(boost::fusion::transform(boost::fusion::filter_if<NormalStepBlockFilter>(IstlInterfaceDetail::AllBlocks<NormalStepAssembler>::apply(normalStepAssembler)),IstlInterfaceDetail::Translate<firstRow,firstCol>(nThreads_))),
1152 tangentialStepBlocks(boost::fusion::transform(boost::fusion::filter_if<TangentialStepBlockFilter>(IstlInterfaceDetail::AllBlocks<TangentialStepAssembler>::apply(tangentialStepAssembler)),IstlInterfaceDetail::Translate<firstRow,firstCol>(nThreads_))),
1153 nThreads(nThreads_)
1154 {}
1155
1157
1159 void update()
1160 {
1161 assert(false);
1162 // blocks = boost::fusion::transform(boost::fusion::filter_if<BlockFilter>(IstlInterfaceDetail::AllBlocks<Assembler>::apply(assembler)),
1163 // IstlInterfaceDetail::Translate<firstRow,firstCol>(nThreads));
1164 }
1165
1167 {
1168 std::vector<size_t> offset(3,0);
1169 Triplet result, tmp;
1170 for(size_t i=0; i<3; ++i)
1171 {
1172 for(size_t j=0; j<3; ++j)
1173 {
1174 if(i==adjointId || j== adjointId || (i==controlId && j==controlId)) tmp = normalStepAssembler.template get<Triplet>(onlyLowerTriangle,i,i+1,j,j+1);
1175 else tmp = tangentialStepAssembler.template get<Triplet>(onlyLowerTriangle,i,i+1,j,j+1);
1176 tmp.shiftIndices(offset[i],offset[j]);
1177 result += tmp;
1178 if(i==0)
1179 {
1180 if(j==0) offset[1] = tmp.nrows();
1181 if(j==1) offset[2] = tmp.nrows();
1182 }
1183 }
1184 }
1185
1186 return result;
1187 }
1188
1189 // /// Access matrix. Use if Matrix does support move-semantics.
1190 // template <class Matrix> Matrix get() const
1191 // {
1192 // return assembler.template get<Matrix>(onlyLowerTriangle, firstRow, lastRow, firstCol, lastCol);
1193 // }
1194
1195 // /// Access matrix via unique_ptr. Use if Matrix does not support move-semantics.
1196 // template <class Matrix> std::unique_ptr<Matrix> getPointer() const
1197 // {
1198 // return assembler.template getPointer<Matrix,firstRow,lastRow,firstCol,lastCol>(onlyLowerTriangle);
1199 // }
1200
1204 // MatrixAsTriplet<Scalar> getmat() const __attribute__((deprecated));
1205
1207
1215 template <class Vector> void rangeToVector(Range const& y, Vector& coefficients) const
1216 {
1217 IstlInterfaceDetail::toVector(y, coefficients);
1218 }
1219
1221
1229 template <class Vector> void domainToVector(Domain const& x, Vector& coefficients) const
1230 {
1231 IstlInterfaceDetail::toVector(x, coefficients);
1232 }
1233
1235
1243 template <class Vector>
1244 void vectorToDomain(Vector const& coefficients, Domain& x) const
1245 {
1246 IstlInterfaceDetail::fromVector(coefficients, x);
1247 }
1248
1258 template <class Vector>
1259 void vectorToRange(Vector const& coefficients, Range& x) const
1260 {
1261 IstlInterfaceDetail::fromVector(coefficients, x);
1262 }
1263
1265 virtual void apply(Domain const& x, Range& b) const
1266 {
1267 assert(static_cast<void const*>(&x) != static_cast<void const*>(&b));
1268 boost::fusion::for_each(normalStepBlocks,NormalStepApplyScaleAdd(normalStepAssembler,1.0,x,b,true));
1269 boost::fusion::for_each(tangentialStepBlocks,TangentialStepApplyScaleAdd(tangentialStepAssembler,1.0,x,b,false));
1270 }
1271
1277 virtual Scalar applyDp(Domain const& x, Range& b) const
1278 {
1279 assert(static_cast<void const*>(&x) != static_cast<void const*>(&b));
1280 std::cerr << "AssembledGalerkinOperator::dp not yet implemented!\n"; abort();
1281 return 0;
1282 }
1283
1284 virtual Scalar dp(Domain const& x, Range const& y) const
1285 {
1286 std::cerr << "AssembledGalerkinOperator::dp not yet implemented!\n"; abort();
1287 return 0; // TODO: fixme
1288 }
1289
1294 virtual void applyscaleadd(Scalar alpha, Domain const& x, Range& b) const
1295 {
1296 assert(static_cast<void const*>(&x) != static_cast<void const*>(&b));
1297 boost::fusion::for_each(normalStepBlocks,NormalStepApplyScaleAdd(normalStepAssembler,1.0,x,b,false));
1298 boost::fusion::for_each(tangentialStepBlocks,TangentialStepApplyScaleAdd(tangentialStepAssembler,1.0,x,b,false));
1299 }
1300
1304 // Assembler const& getAssembler() const
1305 // {
1306 // return assembler;
1307 // }
1308 //
1309 // bool getOnlyLowerTriangle() const { return onlyLowerTriangle; }
1310
1311 protected:
1312 typedef typename IstlInterfaceDetail::AllBlocks<NormalStepAssembler>::result AllNormalStepBlocksSeq;
1313 typedef typename IstlInterfaceDetail::AllBlocks<TangentialStepAssembler>::result AllTangentialStepBlocksSeq;
1314 typedef typename boost::fusion::result_of::filter_if<AllNormalStepBlocksSeq,NormalStepBlockFilter>::type FilteredNormalStepBlocksSeq;
1315 typedef typename boost::fusion::result_of::filter_if<AllTangentialStepBlocksSeq,TangentialStepBlockFilter>::type FilteredTangentialStepBlocksSeq;
1316
1317 typedef typename boost::fusion::result_of::as_vector<AllNormalStepBlocksSeq>::type AllNormalStepBlocks;
1318 typedef typename boost::fusion::result_of::as_vector<AllTangentialStepBlocksSeq>::type AllTangentialStepBlocks;
1319 typedef typename boost::fusion::result_of::as_vector<FilteredNormalStepBlocksSeq>::type FilteredNormalStepBlocks;
1320 typedef typename boost::fusion::result_of::as_vector<FilteredTangentialStepBlocksSeq>::type FilteredTangentialStepBlocks;
1321
1322 typedef typename boost::fusion::result_of::as_vector<typename boost::fusion::result_of::transform<FilteredNormalStepBlocks,IstlInterfaceDetail::Translate<firstRow,firstCol>>::type>::type NormalBlocks;
1323 typedef typename boost::fusion::result_of::as_vector<typename boost::fusion::result_of::transform<FilteredTangentialStepBlocks,IstlInterfaceDetail::Translate<0,0>>::type>::type TangentialBlocks;
1324
1326 NormalStepAssembler const& normalStepAssembler;
1327 TangentialStepAssembler const& tangentialStepAssembler;
1328
1331
1334
1336 {
1337 NormalStepAssembler const& assembler;
1338 // Constructs the functor for matrix-vector multiplication and addition. If init is true, the first block
1339 // encountered in each row is called with apply (using alpha=1 and initializing the rhs to zero), otherwise
1340 // applyscaleadd is used. This prevents a double access of the right hand side, first for setting to zero,
1341 // then for adding the MV product.
1342 NormalStepApplyScaleAdd(NormalStepAssembler const& as, Scalar a_, Domain const& x_, Range& y_, bool init, Scalar* dp_=0): assembler(as), a(a_), x(x_), y(y_), dp(dp_? dp_: &dummy)
1343 {
1344 for (int i=0; i<lastRow; ++i)
1345 doInit[i] = init;
1346 *dp = 0;
1347 }
1348
1349 template <class Block>
1350 void operator()(Block const& b) const {
1351 if( ( (Block::rowId==stateId && Block::colId==stateId) || (Block::rowId==stateId && Block::colId==controlId) || (Block::colId==stateId && Block::rowId==controlId) ) ) return;
1352// if( (Block::rowId==stateId && Block::colId==stateId) ) return;
1353 using namespace boost::fusion;
1354
1355 typename result_of::at_c<typename Domain::Functions const,Block::colId>::type xi = at_c<Block::colId>(x.data);
1356 typename result_of::at_c<typename Range::Functions,Block::rowId>::type yi = at_c<Block::rowId>(y.data);
1357 if (!b.threadedMatrix.get())
1358 abort();
1359
1360 if (doInit[Block::rowId])
1361 {
1362 *dp += b.threadedMatrix->mv(xi,yi);
1363 doInit[Block::rowId] = false;
1364 }
1365 else
1366 *dp += b.threadedMatrix->usmv(a,xi,yi);
1367
1368 return;
1369 }
1370
1371 private:
1372 Scalar a;
1373 Domain const& x;
1374 Range& y;
1375 Scalar* dp;
1376 Scalar dummy; // something to point to in case no target pointer has been provided
1377 mutable bool doInit[lastRow]; // ugly, but boost::fusion::for_each only works with const functors
1378 };
1379
1380
1382 {
1383 TangentialStepAssembler const& assembler;
1384 // Constructs the functor for matrix-vector multiplication and addition. If init is true, the first block
1385 // encountered in each row is called with apply (using alpha=1 and initializing the rhs to zero), otherwise
1386 // applyscaleadd is used. This prevents a double access of the right hand side, first for setting to zero,
1387 // then for adding the MV product.
1388 TangentialStepApplyScaleAdd(TangentialStepAssembler const& as, Scalar a_, Domain const& x_, Range& y_, bool init, Scalar* dp_=0): assembler(as), a(a_), x(x_), y(y_), dp(dp_? dp_: &dummy)
1389 {
1390 for (int i=0; i<lastRow; ++i)
1391 doInit[i] = init;
1392 *dp = 0;
1393 }
1394
1395 template <class Block>
1396 void operator()(Block const& b) const {
1397 if( !( (Block::rowId==stateId && Block::colId==stateId) || (Block::rowId==stateId && Block::colId==controlId) || (Block::colId==stateId && Block::rowId==controlId) ) ) return;
1398 using namespace boost::fusion;
1399
1400 typename result_of::at_c<typename Domain::Functions const,Block::colId>::type xi = at_c<Block::colId>(x.data);
1401 typename result_of::at_c<typename Range::Functions,Block::rowId>::type yi = at_c<Block::rowId>(y.data);
1402 if (!b.threadedMatrix.get())
1403 abort();
1404
1405 if (doInit[Block::rowId])
1406 {
1407 *dp += b.threadedMatrix->mv(xi,yi);
1408 doInit[Block::rowId] = false;
1409 }
1410 else
1411 *dp += b.threadedMatrix->usmv(a,xi,yi);
1412
1413 return;
1414 }
1415
1416 private:
1417 Scalar a;
1418 Domain const& x;
1419 Range& y;
1420 Scalar* dp;
1421 Scalar dummy; // something to point to in case no target pointer has been provided
1422 mutable bool doInit[lastRow]; // ugly, but boost::fusion::for_each only works with const functors
1423 };
1424 };
1425
1429 template <class Operator>
1430 class TransposedOperator : public Dune::LinearOperator<typename Operator::Range,typename Operator::Domain>
1431 {
1432 public:
1433 typedef typename Operator::Scalar Scalar;
1434 typedef typename Operator::Range Domain;
1435 typedef typename Operator::Domain Range;
1436 typedef typename Operator::Assembler Assembler;
1437
1438 explicit TransposedOperator(Operator const& A_) : A(A_.getTriplet().transpose()){}
1439
1441
1442 virtual void apply(Domain const& x, Range& b) const
1443 {
1444 A.apply(x,b);
1445 }
1446
1447 virtual void applyscaleadd(Scalar alpha, Domain const& x, Range& b) const
1448 {
1449 A.applyscaleadd(alpha,x,b);
1450 }
1451
1452 MatrixAsTriplet<Scalar> getTriplet() const { return A.getTriplet(); }
1453
1454 private:
1456 };
1457
1458} // end of namespace Kaskade
1459
1460#endif
An adaptor presenting a Dune::LinearOperator <domain_type,range_type> interface to a contiguous sub-b...
std::unique_ptr< Matrix > getPointer() const
Access matrix via unique_ptr. Use if Matrix does not support move-semantics.
MatrixAsTriplet< Scalar > getmat() const __attribute__((deprecated))
DEPRECATED. Use get<MatrixAsTriplet<Scalar>>() instead.
IstlInterfaceDetail::Base< Assembler_, firstRow, lastRow, firstCol, lastCol, symmetric >::type Base
boost::fusion::result_of::as_vector< typenameboost::fusion::result_of::filter_if< allblocks, BlockFilter >::type >::type filtered
boost::fusion::result_of::as_vector< typenameboost::fusion::result_of::transform< filtered, IstlInterfaceDetail::Translate< firstRow, firstCol > >::type >::type blocks
virtual void applyscaleaddTransposed(Scalar alpha, Range const &x, Domain &b) const
Compute .
AssembledGalerkinOperator(Assembler const &assembler_, bool onlyLowerTriangle_=false, int nThreads_=0)
Constructor.
auto const & ansatzSpace() const
Returns a reference to the FE space of the i-th variable in this GOP.
virtual void apply(Domain const &x, Range &b) const
compute
virtual Scalar dp(Domain const &x, Range const &y) const
void applyTransposed(Range const &x, Domain &b) const
compute
typename Assembler::AnsatzVariableSetDescription::template CoefficientVector< firstCol, lastCol > Domain
boost::fusion::result_of::as_vector< typenameIstlInterfaceDetail::AllBlocks< Assembler >::result >::type allblocks
IstlInterfaceDetail::BlockInfo< firstRow, lastRow, firstCol, lastCol > BlockInfo
AssembledGalerkinOperator< Assembler, firstRow, lastRow, firstCol, lastCol > makeAssembledGalerkinOperator(Assembler const &assembler)
Convenience routine for creating assembled operators.
void vectorToRange(Vector const &coefficients, Range &x) const
Get from coefficient vector Apply to : .
Matrix get(int rowFirst=0, int rowLast=lastRow-firstRow, int colFirst=0, int colLast=lastCol-firstCol) const
Access matrix (or a submatrix).
virtual void applyscaleadd(Scalar alpha, Domain const &x, Range &b) const
Compute .
void update()
update operator if grid has changed or assemble(...) has been called.
virtual Dune::SolverCategory::Category category() const override
returns the category of the operator
typename Assembler::TestVariableSetDescription::template CoefficientVector< firstRow, lastRow > Range
virtual MatrixAsTriplet< Scalar > getTriplet() const __attribute__((deprecated))
DEPRECATED. Use get<MatrixAsTriplet<Scalar>>() instead.
virtual Scalar applyDp(Domain const &x, Range &b) const
Computes and, in case is symmetric, also .
void rangeToVector(Range const &y, Vector &coefficients) const
Get coefficient vector from .
void vectorToDomain(Vector const &coefficients, Domain &x) const
Get from coefficients vector .
Assembler const & getAssembler() const
Provides access to the underlying assembler.
void domainToVector(Domain const &x, Vector &coefficients) const
Get coefficients vector from .
boost::fusion::result_of::filter_if< AllTangentialStepBlocksSeq, TangentialStepBlockFilter >::type FilteredTangentialStepBlocksSeq
void domainToVector(Domain const &x, Vector &coefficients) const
Get coefficients vector from .
virtual void applyscaleadd(Scalar alpha, Domain const &x, Range &b) const
Compute Note that x and b must not refer to the same memory locations (in case Domain==Range).
IstlInterfaceDetail::AllBlocks< NormalStepAssembler >::result AllNormalStepBlocksSeq
Provides access to the underlying assembler.
boost::fusion::result_of::as_vector< typenameboost::fusion::result_of::transform< FilteredNormalStepBlocks, IstlInterfaceDetail::Translate< firstRow, firstCol > >::type >::type NormalBlocks
virtual Scalar applyDp(Domain const &x, Range &b) const
Computes and, in case is symmetric, also .
virtual void apply(Domain const &x, Range &b) const
compute
void rangeToVector(Range const &y, Vector &coefficients) const
returns a reference to the matrix
MatrixAsTriplet< Scalar > Triplet
boost::fusion::result_of::as_vector< AllTangentialStepBlocksSeq >::type AllTangentialStepBlocks
NormalStepAssembler::Scalar Scalar
virtual Scalar dp(Domain const &x, Range const &y) const
NormalStepAssembler const & normalStepAssembler
LagrangeOperator(NormalStepAssembler const &normalStepAssembler_, TangentialStepAssembler const &tangentialStepAssembler_, bool onlyLowerTriangle_=false, int nThreads_=0)
IstlInterfaceDetail::AllBlocks< TangentialStepAssembler >::result AllTangentialStepBlocksSeq
virtual MatrixAsTriplet< Scalar > getTriplet() const
IstlInterfaceDetail::BlockInfo< firstRow, lastRow, firstCol, lastCol > BlockInfo
void vectorToRange(Vector const &coefficients, Range &x) const
Get from coefficient vector Apply to : .
TangentialBlocks tangentialStepBlocks
void vectorToDomain(Vector const &coefficients, Domain &x) const
Get from coefficients vector .
boost::fusion::result_of::as_vector< typenameboost::fusion::result_of::transform< FilteredTangentialStepBlocks, IstlInterfaceDetail::Translate< 0, 0 > >::type >::type TangentialBlocks
TangentialStepAssembler const & tangentialStepAssembler
boost::fusion::result_of::as_vector< FilteredNormalStepBlocksSeq >::type FilteredNormalStepBlocks
void update()
update operator if grid has changed or assemble(...) has been called.
boost::fusion::result_of::filter_if< AllNormalStepBlocksSeq, NormalStepBlockFilter >::type FilteredNormalStepBlocksSeq
boost::fusion::result_of::as_vector< FilteredTangentialStepBlocksSeq >::type FilteredTangentialStepBlocks
boost::fusion::result_of::as_vector< AllNormalStepBlocksSeq >::type AllNormalStepBlocks
SparseIndexInt nrows() const
Returns number of rows (computes them, if not known)
Definition: triplet.hh:202
void shiftIndices(SparseIndexInt row, SparseIndexInt col)
Shifts matrix indices. Can be used together with += to concatenate sparese matrices.
Definition: triplet.hh:334
void vectorToRange(Vector const &coefficients, Range &x) const
Get from coefficient vector .
void vectorToDomain(Vector const &coefficients, Domain &x) const
Get from coefficients vector .
void domainToVector(Domain const &x, Vector &coefficients) const
Get coefficients vector from .
virtual Dune::SolverCategory::Category category() const override
returns the category of the operator
void rangeToVector(Range const &y, Vector &coefficients) const
Get coefficient vector from .
MatrixRepresentedOperator & operator=(MatrixRepresentedOperator const &other)=default
virtual Dune::SolverCategory::Category category() const override
returns the category of the operator
void vectorToRange(Vector const &coefficients, Range &x) const
Get from coefficient vector .
MatrixRepresentedOperator & operator=(MatrixRepresentedOperator const &other)=default
void domainToVector(Domain const &x, Vector &coefficients) const
Get coefficients vector from .
void rangeToVector(Range const &y, Vector &coefficients) const
Get coefficient vector from .
void vectorToDomain(Vector const &coefficients, Domain &x) const
Get from coefficients vector .
Operator with matrix-representation and coordinate mappings.
MatrixAsTriplet< Scalar > getTriplet() const
TransposedOperator(Operator const &A_)
virtual void apply(Domain const &x, Range &b) const
Operator::Assembler Assembler
virtual void applyscaleadd(Scalar alpha, Domain const &x, Range &b) const
Documentation of the concept of a quadratic variational functionalThe variational functional concept ...
This file contains various utility functions that augment the basic functionality of Dune.
FEFunctionSpace and FunctionSpaceElement and the like.
Dune::FieldVector< Scalar, dim > Vector
T transpose(T x)
OutIter vectorToSequence(double x, OutIter iter)
Definition: crsutil.hh:30
InIter vectorFromSequence(FunctionSpaceElement< Space, m > &v, InIter in)
A block filter specifying which subblocks of a stiffness matrix or right hand side shall be assembled...
Definition: concepts.hh:763
ApplyScaleAdd(Assembler const &as, Scalar a_, Domain const &x_, Range &y_, bool init, Scalar *dp_=0)
TransposedApplyScaleAdd(Assembler const &as, Scalar a_, Range const &x_, Domain &y_, bool init, Scalar *dp_=0)
!std ::is_same< decltype(hasFieldType< Type >(0)), TypeNotFound >::value ::type type
NormalStepApplyScaleAdd(NormalStepAssembler const &as, Scalar a_, Domain const &x_, Range &y_, bool init, Scalar *dp_=0)
TangentialStepApplyScaleAdd(TangentialStepAssembler const &as, Scalar a_, Domain const &x_, Range &y_, bool init, Scalar *dp_=0)
Returns the matrix type or its transposed type, depending on the given transpose flag.
Definition: fixdune.hh:597