13#ifndef ASSEMBLERCORE_HH
14#define ASSEMBLERCORE_HH
24#include <boost/version.hpp>
25#include <boost/mpl/accumulate.hpp>
26#include <boost/mpl/bool.hpp>
27#include <boost/mpl/if.hpp>
28#include <boost/timer/timer.hpp>
30#include <boost/exception/diagnostic_information.hpp>
31#include <boost/fusion/algorithm.hpp>
32#include <boost/fusion/sequence.hpp>
33#include <boost/fusion/include/find_if.hpp>
35#include "dune/common/config.h"
37#include "dune/common/fvector.hh"
38#include "dune/common/fmatrix.hh"
39#include "dune/geometry/type.hh"
40#include "dune/grid/common/capabilities.hh"
41#include "dune/istl/bcrsmatrix.hh"
42#include "dune/istl/bdmatrix.hh"
74 static int const timerStatistics = 0x1;
75 static int const scatterStatistics = 0x2;
76 static int const lockStatistics = 0x4;
77 static int const localTimerStatistics = 0x0;
88 static int const statistics = 0;
100 using namespace boost::fusion;
109 class RowGroupManager
120 virtual ~RowGroupManager();
123 RowGroupManager(RowGroupManager
const& m) =
delete;
124 RowGroupManager& operator=(RowGroupManager
const& m) =
delete;
131 void init(
int nrg,
size_t rows);
139 void init(
int nrg, std::vector<std::vector<size_t>>
const& colIndex);
148 void init(
int nrg, std::vector<size_t>
const& weight);
154 std::pair<size_t,size_t> range(
int n)
const;
159 std::mutex& mutex(
int n)
const;
169 std::vector<size_t> rowGroupStart;
190 template <
class Policy,
class RowVar,
class ColVar,
class SparseIdx>
193 static int const rowId = RowVar::id;
194 static int const colId = ColVar::id;
195 static int const rowSpaceIndex = RowVar::spaceIndex;
196 static int const colSpaceIndex = ColVar::spaceIndex;
197 static bool const symmetric = Policy::template BlockInfo<rowId,colId>::symmetric;
198 static bool const mirror = Policy::template BlockInfo<rowId,colId>::mirror;
199 static bool const lumped = Policy::template BlockInfo<rowId,colId>::lumped;
200 static bool const makePositive = Policy::template BlockInfo<rowId,colId>::makePositive;
202 using SparseIndex = SparseIdx;
203 typedef MatrixBlock<Policy,RowVar,ColVar,SparseIndex> Self;
204 typedef typename Policy::Scalar Scalar;
205 typedef typename Policy::Spaces Spaces;
206 typedef Dune::FieldMatrix<Scalar,RowVar::m,ColVar::m> BlockType;
207 typedef NumaBCRSMatrix<BlockType, SparseIndex> Matrix;
209 typedef typename SpaceType<Spaces,RowVar::spaceIndex>::type RowSpace;
210 typedef typename SpaceType<Spaces,ColVar::spaceIndex>::type ColSpace;
211 typedef typename RowSpace::GridView GridView;
212 typedef typename GridView::template Codim<0>::Iterator CellIterator;
214 static int const dim = ColSpace::dim;
224 MatrixBlock(MatrixBlock
const& mb)
225 : matrix(new Matrix(*mb.matrix))
226 , isDense(mb.isDense)
232 MatrixBlock& operator=(MatrixBlock
const& mb)
234 *matrix = *mb.matrix;
235 isDense = mb.isDense;
238 MatrixBlock& operator=(Scalar x)
240 assert(matrix.get());
245 MatrixBlock& operator+=(MatrixBlock
const& mb)
247 *matrix += *mb.matrix;
255 Matrix& globalMatrix()
257 assert(matrix.get());
264 Matrix
const& globalMatrix()
const
266 assert(matrix.get());
277 std::shared_ptr<Matrix const> globalMatrixPointer()
const {
return matrix; }
293 template <
class FaceOracle>
294 void init(Spaces
const& spaces, CellIterator first, CellIterator last,
295 FaceOracle
const& considerFace)
297 RowSpace
const& rowSpace = *at_c<RowVar::spaceIndex>(spaces);
298 ColSpace
const& colSpace = *at_c<ColVar::spaceIndex>(spaces);
302 if (!Policy::template BlockInfo<rowId,colId>::present)
304 assert(
"Aieee! Nonpresent matrix block detected!\n"==0);
308 boost::timer::cpu_timer timer;
311 size_t const rows = rowSpace.degreesOfFreedom();
312 size_t const cols = colSpace.degreesOfFreedom();
317 if (Policy::template BlockInfo<rowId,colId>::lumped)
319 assert(RowVar::spaceIndex==ColVar::spaceIndex && rows==cols);
320 NumaCRSPatternCreator<SparseIndex> creator(rows,cols,
false,1);
321 for (
size_t i=0; i<rows; ++i)
322 creator.addElements(&i,&i+1,&i,&i+1);
323 matrix.reset(
new Matrix(creator));
330 bool const dense = RowSpace::Mapper::globalSupport || ColSpace::Mapper::globalSupport;
338 int preallocateEntriesPerRow = 0;
339 if (NumaThreadPool::instance().nodes()==1)
341 int localSize = colSpace.mapper().globalIndices(0).size();
342 preallocateEntriesPerRow = dense? 0:
347 NumaCRSPatternCreator<SparseIndex> creator(rows,cols,symmetric,preallocateEntriesPerRow);
349 if (statistics & timerStatistics)
350 std::cout <<
"initial creator construction (" << rowId <<
"," << colId <<
"): " << timer.format();
356 creator.addAllElements();
357 if (statistics & timerStatistics)
358 std::cout <<
"entering indices for (" << rowId <<
"," << colId <<
"): " << timer.format();
372 size_t const nCells = rowSpace.indexSet().size(0);
374 std::vector<typename RowSpace::Mapper::GlobalIndexRange> rIndices(nCells,rowSpace.mapper().initGlobalIndexRange());
375 std::vector<typename ColSpace::Mapper::GlobalIndexRange> cIndices(nCells,colSpace.mapper().initGlobalIndexRange());
376 for (
size_t i=0; i<nCells; ++i)
378 rIndices[i] = rowSpace.mapper().globalIndices(i);
379 cIndices[i] = colSpace.mapper().globalIndices(i);
381 if (statistics & timerStatistics)
382 std::cout <<
"gathering indices for (" << rowId <<
"," << colId <<
"): " << timer.format();
385 creator.addElements(rIndices,cIndices);
389 if(Policy::considerInnerFaces)
391 GridView
const& gridView = rowSpace.gridView();
393 for (CellIterator ci=first; ci!=last; ++ci)
395 auto const& rIndices = rowSpace.mapper().globalIndices(*ci);
397 for (
auto const& face: intersections(gridView,*ci))
400 if (face.boundary() || !face.neighbor() ||
considerFace(face)==
false)
403 auto const& cIndices = colSpace.mapper().globalIndices(face.outside());
405 creator.addElements(begin(rIndices),end(rIndices),
406 begin(cIndices),end(cIndices));
411 if (statistics & timerStatistics)
412 std::cout <<
"entering indices for (" << rowId <<
"," << colId <<
"): " << timer.format();
416 if (statistics & timerStatistics)
417 std::cout <<
"balancing for (" << rowId <<
"," << colId <<
"): " << timer.format();
424 nnz = creator.nonzeroes();
427 matrix.reset(
new Matrix(creator));
428 if (statistics & timerStatistics)
429 std::cout <<
"creating pattern & matrix for (" << rowId <<
"," << colId <<
"): " << timer.format();
435 if (std::min(rows,cols)>0)
436 isDense = nnz/std::min(rows,cols) > std::max(rows,cols)/2;
440 if (statistics & timerStatistics)
441 std::cout <<
"init cleanup for (" << rowId <<
"," << colId <<
"): " << timer.format() <<
"\n";
445 bool dense()
const {
return isDense; }
448 std::shared_ptr<Matrix> matrix;
455 template <
int row,
int col>
458 template <
class MatrixBlock>
461 using type = std::conditional_t<MatrixBlock::rowId==row && MatrixBlock::colId==col,boost::mpl::true_,boost::mpl::false_>;
483 template <
class Filter,
class AnsatzVariables,
class TestVariables,
class SparseIndex>
487 struct PresenceFilter
489 template <
class Block>
492 typedef boost::mpl::bool_<Filter::template BlockInfo<Block::rowId,Block::colId>::present> type;
502 using type =
decltype(as_vector(filter_if<PresenceFilter>(
503 transform(AllSystemBlocks<AnsatzVariables,TestVariables>(),
506 using RowVar =
typename decltype(varPair)::first_type;
507 using ColVar =
typename decltype(varPair)::second_type;
508 return MatrixBlock<Filter,RowVar,ColVar,SparseIndex>();
520 template <
class Policy,
class RV>
523 typedef typename std::remove_reference<RV>::type RowVar;
525 static int const rowId = RowVar::id;
527 typedef typename Policy::Scalar Scalar;
528 typedef typename Policy::Spaces Spaces;
529 typedef Dune::FieldVector<Scalar,RowVar::m> BlockType;
530 typedef typename Dune::BlockVector<BlockType> Rhs;
531 typedef RhsBlock<Policy,RowVar> Self;
533 static int const rowSpaceIndex = RowVar::spaceIndex;
534 typedef typename SpaceType<Spaces,RowVar::spaceIndex>::type RowSpace;
535 typedef typename RowSpace::GridView::template Codim<0>::Iterator CellIterator;
541 void init(Spaces
const& spaces, CellIterator , CellIterator ,
int nrg)
543 RowSpace
const& rowSpace = *at_c<RowVar::spaceIndex>(spaces);
544 size_t rows = rowSpace.degreesOfFreedom();
546 rowGroupManager = std::make_unique<RowGroupManager>();
547 rowGroupManager->init(nrg,rows);
550 RowGroupManager& rowGroup() {
return *rowGroupManager; }
556 LocalVector(): ridx(RowSpace::Mapper::initSortedIndexRange()) {}
558 std::vector<BlockType>
vector;
560 typedef typename RowSpace::Mapper::SortedIndexRange SortedRowIdx;
572 typedef Self RhsBlock;
573 typedef std::vector<BlockType> LocalVectorType;
575 LocalVectors(
int n, RhsBlock& rb_): localVectors(n), currentLocalVector(0), rb(&rb_) {}
578 std::vector<LocalVector> localVectors;
581 int currentLocalVector;
588 std::unique_ptr<RowGroupManager> rowGroupManager;
594 template <
class Policy,
class TestVariables>
599 struct PresenceFilter
601 template <
class Block>
604 typedef boost::mpl::bool_<Policy::template RhsBlockInfo<Block::rowId>::present> type;
608 static auto create(TestVariables t)
610 auto allBlocks = transform(t,[](
auto tvar) {
return RhsBlock<Policy,decltype(tvar)>(); });
611 return as_vector(filter_if<PresenceFilter>(allBlocks));
615 typedef decltype(create(TestVariables())) type;
624 template <
class Policy>
630 RhsLocalData(
int n_): n(n_) {}
632 template <
class RhsBlock>
633 typename RhsBlock::LocalVectors operator()(RhsBlock
const& rb)
const
637 return typename RhsBlock::LocalVectors(n,
removeConst(rb));
647 struct MatrixLocalData
653 MatrixLocalData(
size_t s_)
656 template <
class MatrixBlock>
657 auto operator()(MatrixBlock
const& mb)
const
664 return LocalMatrices<
typename MatrixBlock::BlockType,
666 typename MatrixBlock::RowSpace::Mapper::SortedIndexRange,
667 typename MatrixBlock::ColSpace::Mapper::SortedIndexRange,
677 template <
class Spaces>
678 class GetMaxDerivativeBase
681 GetMaxDerivativeBase(Spaces
const& spaces_, std::map<void const*,int>& deriv_): spaces(spaces_), deriv(deriv_) {}
684 Spaces
const& spaces;
685 std::map<void const*,int>& deriv;
688 template <
int spaceIndex>
689 void enterSpace(
int d)
const
691 void const* space = at_c<spaceIndex>(spaces);
692 auto i = deriv.find(space);
696 i->second = std::max(i->second,d);
700 template <
class Functional,
class Spaces>
701 class GetMaxDerivativeMatrix:
public GetMaxDerivativeBase<Spaces>
704 GetMaxDerivativeMatrix(Spaces
const& spaces, std::map<void const*,int>& deriv): GetMaxDerivativeBase<Spaces>(spaces,deriv) {}
706 template <
class LocalMatrices>
707 void operator()(LocalMatrices
const&)
const
709 using MatrixBlock =
typename LocalMatrices::InfoType;
710 int d = Functional::template D2<MatrixBlock::rowId,MatrixBlock::colId>::derivatives;
711 this->
template enterSpace<MatrixBlock::rowSpaceIndex>(d);
712 this->
template enterSpace<MatrixBlock::colSpaceIndex>(d);
717 template <
class Functional,
class Spaces>
718 class GetMaxDerivativeRhs:
public GetMaxDerivativeBase<Spaces>
721 GetMaxDerivativeRhs(Spaces
const& spaces, std::map<void const*,int>& deriv): GetMaxDerivativeBase<Spaces>(spaces,deriv) {}
723 template <
class RBlock>
724 void operator()(RBlock
const&)
const
726 int d = Functional::template D1<RBlock::RhsBlock::rowId>::derivatives;
727 this->
template enterSpace<RBlock::RhsBlock::rowSpaceIndex>(d);
737 template <
class Functional,
class Spaces,
class LocalMatrices,
class RBlocks>
738 std::map<void const*,int> derivatives(Functional
const& f, Spaces
const& spaces, LocalMatrices
const& localMatrices, RBlocks
const& rblocks)
740 std::map<void const*,int> deriv;
742 for_each(localMatrices,GetMaxDerivativeMatrix<Functional,Spaces>(spaces,deriv));
743 for_each(rblocks,GetMaxDerivativeRhs<Functional,Spaces>(spaces,deriv));
752 template <
class Evaluators,
class TestVariables>
759 template <
class LocalVectors>
760 void operator()(LocalVectors& lv)
const
766 assert(lv.currentLocalVector < lv.localVectors.size());
768 int const rSpaceIdx = result_of::value_at_c<TestVariables,LocalVectors::RhsBlock::rowId>::type::spaceIndex;
770 auto& reval = at_c<rSpaceIdx>(eval);
772 auto& rc = lv.localVectors[lv.currentLocalVector];
775 rc.vector.resize(reval.size());
776 std::fill(rc.vector.begin(),rc.vector.end(),0);
779 rc.ridx = reval.sortedIndices();
788 template <
class Evaluators,
class AnsatzVariableSetDescription,
class TestVariableSetDescription>
789 struct NewLocalMatrix
792 : reval(reval_), ceval(ceval_)
795 template <
class LocalMatrices>
796 void operator()(LocalMatrices& lm)
const
800 int const cSpaceIdx = spaceIndex<AnsatzVariableSetDescription,MatrixBlock::colId>;
801 int const rSpaceIdx = spaceIndex<TestVariableSetDescription ,MatrixBlock::rowId>;
803 lm.push_back(at_c<rSpaceIdx>(reval).sortedIndices(),at_c<cSpaceIdx>(ceval).sortedIndices());
816 template <
class TestVariableSetDescription,
class Evaluators,
class Real,
class Cache>
817 struct UpdateLocalRhs
819 UpdateLocalRhs(
Evaluators const& evaluators_, Real integrationFactor_, Cache
const& cache_)
820 : evaluators(evaluators_)
821 , integrationFactor(integrationFactor_)
825 template <
class LocalVectors>
826 void operator()(LocalVectors& lv)
const
828 typedef typename LocalVectors::RhsBlock RhsBlock;
830 int const rSpaceIndex = spaceIndex<TestVariableSetDescription,RhsBlock::rowId>;
831 auto& rc = lv.localVectors[lv.currentLocalVector].vector;
832 size_t const rows = rc.size();
833 for (
size_t i=0; i<rows; ++i)
837 using rhsEntryType = std::remove_reference_t<
decltype(rc[i])>;
838 using d1ResultType =
decltype(cache.template d1<RhsBlock::rowId>(at_c<rSpaceIndex>(evaluators).evalData[i]));
839 static_assert(std::is_same<rhsEntryType,d1ResultType>::value,
840 "Types don't match. Check return type of d1() in problem formulation.");
842 rc[i] += integrationFactor * cache.template d1<RhsBlock::rowId>(at_c<rSpaceIndex>(evaluators).evalData[i]);
843 assert(!std::isnan(rc[i][0]));
848 Real integrationFactor;
856 template <
class AnsatzVariableSetDescription,
class TestVariableSetDescription,
class Evaluators,
class Real,
class Cache>
857 struct UpdateLocalMatrix
859 UpdateLocalMatrix(
Evaluators const& evaluators_, Real integrationFactor_, Cache
const& cache_):
860 evaluators(evaluators_), integrationFactor(integrationFactor_), cache(cache_)
863 template <
class LocalMatrices>
864 void operator()(LocalMatrices& lm)
const
869 int const rowId = MatrixBlock::rowId;
870 int const colId = MatrixBlock::colId;
871 int const rSpaceIndex = spaceIndex<TestVariableSetDescription,rowId>;
872 int const cSpaceIndex = spaceIndex<AnsatzVariableSetDescription,colId>;
873 auto const& rEval = at_c<rSpaceIndex>(evaluators).evalData;
874 auto const& cEval = at_c<cSpaceIndex>(evaluators).evalData;
879 int const rows = A.ridx().size();
880 int const cols = A.cidx().size();
883 for (
int i=0; i<rows; ++i)
885 int begin = MatrixBlock::lumped? i: 0;
886 int end = (MatrixBlock::symmetric||MatrixBlock::lumped)? i+1: cols;
887 for (
int j=begin; j<end; ++j)
889 static_assert(std::is_same<std::remove_reference_t<
decltype(A(i,j))>,
890 decltype(cache.template d2<rowId,colId>(rEval[i],cEval[j]))
891 >::value,
"Types don't match. Check return type of d2() in problem formulation.");
892 A(i,j) += integrationFactor * cache.template d2<rowId,colId>(rEval[i], cEval[j]);
893 assert(!std::isnan(A(i,j)[0][0]));
899 Real integrationFactor;
905 template <
class AnsatzVariableSetDescription,
class TestVariableSetDescription,
907 struct UpdateLocalMatrixFromInnerBoundaryCache
909 UpdateLocalMatrixFromInnerBoundaryCache(Evaluators
const& insideEval, Evaluators
const& outsideEval,
910 Real integrationFactor_, Cache
const& cache_,
bool sameCell_)
911 : insideEvaluator(insideEval)
912 , outsideEvaluator(outsideEval)
913 , integrationFactor(integrationFactor_)
915 , sameCell(sameCell_)
918 template <
class LocalMatrices>
919 void operator()(LocalMatrices& lm)
const
921 using MatrixBlock =
typename LocalMatrices::InfoType;
923 int const rSpaceIndex = spaceIndex<TestVariableSetDescription, MatrixBlock::rowId>;
924 int const cSpaceIndex = spaceIndex<AnsatzVariableSetDescription,MatrixBlock::colId>;
926 auto& A = lm.localMatrices.back();
929 int const rows = A.ridx().size();
930 int const cols = A.cidx().size();
933 for (
int i=0; i<rows; ++i)
935 int begin = MatrixBlock::lumped? i: 0;
936 int end = ((MatrixBlock::symmetric && sameCell)||MatrixBlock::lumped)? i+1: cols;
937 for (
int j=begin; j<end; ++j)
939 auto tmp = cache.template d2<MatrixBlock::rowId,MatrixBlock::colId>(
940 at_c<rSpaceIndex>(insideEvaluator).evalData[i],
941 at_c<cSpaceIndex>(outsideEvaluator).evalData[j], sameCell);
942 A(i,j) += integrationFactor * tmp;
943 assert(!std::isnan(A(i,j)[0][0]));
948 Evaluators const& insideEvaluator, outsideEvaluator;
949 Real integrationFactor;
958 template <
class GlobalRhs>
959 struct ScatterLocalRhs
967 ScatterLocalRhs(GlobalRhs& globalRhs_,
bool immediate_ =
false):
968 globalRhs(globalRhs_), immediate(immediate_)
971 template <
class LocalVectors>
972 void operator()(LocalVectors& lv)
const
974 auto& gRhs = at_c<LocalVectors::RhsBlock::rowId>(globalRhs.data);
976 auto const& rowGroups = lv.rb->rowGroup();
978 if (immediate || lv.currentLocalVector+1==lv.localVectors.size())
980 int const last = immediate ? lv.currentLocalVector : lv.localVectors.size();
983 for (
int rg=0; rg<rowGroups.size(); ++rg)
986 auto const [firstRow,lastRow] = rowGroups.range(rg);
987 std::lock_guard lock(rowGroups.mutex(rg));
990 for (
int i=0; i<last; ++i)
992 auto& ri = lv.localVectors[i].vector;
993 auto& ridx = lv.localVectors[i].ridx;
995 assert(ri.size()==ridx.size());
997 for (
int r=0; r<ridx.size(); ++r)
999 size_t const rGlobalIndex = ridx[r].first;
1002 if (firstRow<=rGlobalIndex && rGlobalIndex<lastRow)
1004 size_t const rLocalIndex = ridx[r].second;
1005 gRhs[rGlobalIndex] += ri[rLocalIndex];
1012 lv.currentLocalVector = 0;
1015 ++lv.currentLocalVector;
1018 GlobalRhs& globalRhs;
1034 template <
class Functional>
1035 struct SymmetrizeLocalMatrix
1037 template <
class LocalMatrices>
1038 void operator()(LocalMatrices& lm)
const
1040 using MatrixBlock =
typename LocalMatrices::InfoType;
1046 if constexpr (!MatrixBlock::lumped && MatrixBlock::symmetric)
1048 auto& m = lm.back();
1049 int const N = m.ridx().size();
1050 assert(N==m.cidx().size());
1054 for (
int i=0; i<N-1; ++i)
1055 for (
int j=i+1; j<N; ++j)
1061 if constexpr (MatrixBlock::makePositive)
1064 constexpr int row = MatrixBlock::rowId;
1065 constexpr int col = MatrixBlock::colId;
1068 using Entry =
typename MatrixBlock::BlockType;
1069 DynamicMatrix<Entry> Aloc(N,N);
1070 for (
int j=0; j<N; ++j)
1071 for (
int i=0; i<N; ++i)
1072 Aloc[i][j] = m(i,j);
1079 for (
int j=0; j<N; ++j)
1080 for (
int i=0; i<N; ++i)
1081 m(i,j) = Aloc[i][j];
1086 Functional
const* f;
1098 template <
class Functional>
1099 struct VariationalFunctionalPolicy
1101 typedef typename Functional::Scalar Scalar;
1102 typedef typename Functional::AnsatzVars::Spaces Spaces;
1103 static constexpr bool considerInnerFaces = hasInnerBoundaryCache<Functional>;
1105 template <
int rowId>
1108 static bool const present = Functional::template D1<rowId>::present;
1112 template <
int rowId,
int colId>
1115 static bool const present = Functional::template D2<rowId,colId>::present && rowId>=colId;
1116 static bool const symmetric = (rowId==colId || Functional::template D2<rowId,colId>::symmetric)
1117 && (result_of::value_at_c<typename Functional::TestVars::Variables,rowId>::type::spaceIndex
1118 == result_of::value_at_c<typename Functional::AnsatzVars::Variables,colId>::type::spaceIndex);
1119 static bool const mirror = rowId>colId;
1120 static bool const lumped = symmetric && Functional::template D2<rowId,colId>::lumped;
1121 static bool const makePositive = symmetric && Functional::template D2<rowId,colId>::makePositive;
1129 Scalar functional()
const {
return fValue; }
1131 static constexpr bool hasValue =
true;
1143 template <
class Functional>
1144 struct WeakFormulationPolicy
1146 typedef typename Functional::Scalar Scalar;
1147 typedef typename Functional::AnsatzVars::Spaces Spaces;
1148 static constexpr bool considerInnerFaces = hasInnerBoundaryCache<Functional>;
1150 template <
int rowId>
1153 static bool const present = Functional::template D1<rowId>::present;
1157 template <
int rowId,
int colId>
1160 static bool const present = Functional::template D2<rowId,colId>::present;
1161 static bool const symmetric = Functional::template D2<rowId,colId>::symmetric
1162 && (result_of::value_at_c<typename Functional::TestVars::Variables,rowId>::type::spaceIndex
1163 == result_of::value_at_c<typename Functional::AnsatzVars::Variables,colId>::type::spaceIndex);
1164 static bool const mirror =
false;
1165 static bool const lumped = symmetric && Functional::template D2<rowId,colId>::lumped;
1166 static bool const makePositive = symmetric && Functional::template D2<rowId,colId>::makePositive;
1170 static constexpr bool hasValue =
false;
1181 template <
class Problem>
1183 VariationalFunctionalPolicy<Problem>,
1184 WeakFormulationPolicy<Problem>>;
1192 struct TakeAllBlocks
1194 template <
int row>
struct D1 {
static bool const assemble =
true; };
1195 template <
int row,
int col>
struct D2 {
static bool const assemble =
true; };
1199 template <
class BlockFilter>
1200 struct MatrixBlockFilter
1205 typedef boost::mpl::bool_<BlockFilter::template D2<X::rowId,X::colId>::assemble> type;
1209 template <
class>
struct Fill;
1211 template <
class Block,
bool,
bool>
1214 template <
class OtherBlock>
1215 static void apply(OtherBlock
const&, std::unique_ptr<Block>&,
bool,
size_t){}
1218 template <
class Scalar,
int n,
class Allocator,
bool symmetric>
1219 struct CopyBlock<Dune::BCRSMatrix<Dune::FieldMatrix<Scalar,n,n>,Allocator>,symmetric,true>
1221 typedef Dune::BCRSMatrix<Dune::FieldMatrix<Scalar,n,n>,Allocator> Block;
1223 static void apply(Block
const& from, std::unique_ptr<Block>& to,
bool extractOnlyLowerTriangle,
size_t nnz)
1226 if(extractOnlyLowerTriangle == symmetric)
1228 to.reset(
new Block(from));
1233 if( (!extractOnlyLowerTriangle && symmetric) || (extractOnlyLowerTriangle && !symmetric) )
1235 std::vector<std::vector<size_t> > bcrsPattern(from.N());
1236 for(
size_t i=0; i<from.N(); ++i)
1237 for(
size_t j=0; j<=i; ++j)
1239 if(from.exists(i,j))
1241 bcrsPattern[i].push_back(j);
1242 if(i!=j && !extractOnlyLowerTriangle)
1243 bcrsPattern[j].push_back(i);
1246 for(std::vector<size_t>& row : bcrsPattern) std::sort(row.begin(),row.end());
1248 to.reset(
new Block(from.N(),from.M(),nnz,Block::row_wise));
1251 for (
typename Block::CreateIterator row=to->createbegin(); row!=to->createend(); ++row)
1252 for(
size_t col : bcrsPattern[row.index()]) row.insert(col);
1255 for(
size_t row=0; row<bcrsPattern.size(); ++row)
1256 for(
size_t col : bcrsPattern[row])
1258 if(row >= col) (*to)[row][col] = from[row][col];
1259 else if(!extractOnlyLowerTriangle)
1261 for(
size_t i=0; i<n; ++i)
1262 for(
size_t j=0; j<n; ++j)
1263 (*to)[row][col][i][j] = from[col][row][j][i];
1271 template <
class BCRSMat,
int rowIndex,
int columnIndex>
1274 explicit BlockToBCRS(std::unique_ptr<BCRSMat>& m,
bool extractOnlyLowerTriangle_,
size_t nnz_)
1275 : mat(m), extractOnlyLowerTriangle(extractOnlyLowerTriangle_), nnz(nnz_)
1278 template <
class MatrixBlock>
1279 void operator()(MatrixBlock
const& mb)
const
1281 CopyBlock<BCRSMat,MatrixBlock::symmetric,MatrixBlock::rowId==rowIndex && MatrixBlock::colId==columnIndex>::apply(mb.globalMatrix(),mat,extractOnlyLowerTriangle,nnz);
1285 std::unique_ptr<BCRSMat>& mat;
1286 bool extractOnlyLowerTriangle;
1308 template <
class Gr
idView>
1316 gridView(gridView_), indexSet(gridView.indexSet())
1324 gridView(gridView_), indexSet(gridView.indexSet())
1331 assert(indexSet.size(0)==boundaryFlag.size());
1332 return boundaryFlag[indexSet.index(cell)];
1337 typename GridView::IndexSet
const& indexSet;
1338 std::vector<bool> boundaryFlag;
1339 boost::signals2::scoped_connection refConnection;
1341 void update(
int const status)
1343 using namespace Dune;
1347 boundaryFlag.resize(indexSet.size(0));
1349 for (
auto const& cell: elements(gridView))
1350 boundaryFlag[indexSet.index(cell)] = cell.hasBoundaryIntersections();
1364 template <
class Gr
idView>
1368 template <
class Gr
idView>
1372 template <
class Entity>
1375 return cell.hasBoundaryIntersections();
1388 template <
class Gr
idView>
1392 template <
class Gr
idView>
1396 template <
class Entity>
1427 class SparseIndex = size_t,
1428 class BoundaryDetector = CachingBoundaryDetector<typename F::AnsatzVars::GridView>,
1429 class QuadRule = Dune::QuadratureRule<
typename F::AnsatzVars::Grid::ctype,
1430 F::AnsatzVars::Grid::dimension>>
1431 class VariationalFunctionalAssembler
1432 :
public AssemblyDetail::FormulationPolicy<F>
1435 typedef typename AssemblyDetail::FormulationPolicy<F>
Policy;
1438 typedef VariationalFunctionalAssembler<F,SparseIndex,BoundaryDetector,QuadRule>
Self;
1449 typedef typename AnsatzVariableSetDescription::Grid
Grid;
1454 typedef typename AnsatzVariableSetDescription::GridView
GridView;
1457 typedef typename AnsatzVariableSetDescription::Spaces
Spaces;
1459 typedef typename AnsatzVariableSetDescription::IndexSet
IndexSet;
1472 static_assert(std::is_same<typename AnsatzVariableSetDescription::Spaces, typename TestVariableSetDescription::Spaces>::value,
1473 "VariableSetDescriptions for ansatz spaces and test spaces must provide the same space list.");
1474 static_assert(Functional::type==
WeakFormulation || std::is_same<AnsatzVariableSetDescription,TestVariableSetDescription>::value,
1475 "For problem type VariationalFunctional, ansatz and test variables must be the same.");
1488 using MatrixBlockArray =
typename AssemblyDetail::BlockArray<Policy,AnsatzVariables,TestVariables,SparseIndex>::type;
1495 typedef typename AssemblyDetail::RhsBlockArray<Policy,TestVariables>::type
RhsBlockArray;
1500 typedef typename TestVariableSetDescription::template CoefficientVector<>
RhsArray;
1514 TestVariableSetDescription::noOfVariables)>,
1515 "If a problem is of type VariationalFunctional, the present diagonal blocks need to be marked as symmetric in D2.");
1604 flags,nThreads,verbose);
1610 typedef typename CellIterator::Entity
Entity;
1653 template <
class BlockFilter,
class CellFilter>
1655 int nTasks=0,
bool verbose=
false)
1657 using namespace Dune;
1675 std::cout <<
"Grid is not thread safe. Reducing number of used threads to 1." <<
'\n';
1679 if(verbose) std::cout <<
"#tasks:" << nTasks <<
" " <<
'\n';
1682 nTasks = std::min(nTasks,cellRanges.maxRanges());
1684 if (
gatherTimings) timings.start(
"creating rhs/matrix data structures");
1686 auto clearGlobalData = [](
auto& x) { x = 0; };
1689 for_each(
getRhs().first.data,clearGlobalData);
1693 typedef filter_view<MatrixBlockArray,MatrixBlockFilter<BlockFilter>> MatrixBlockFilter;
1694 for_each(MatrixBlockFilter(
getMatrix(f)),clearGlobalData);
1696 if (
gatherTimings) timings.stop(
"creating rhs/matrix data structures");
1703 assembleCellRange<BlockFilter>(f,cellFilter,flags,
gv.template begin<0>(),
gv.template end<0>(),0);
1705 this->fValue = retval;
1711 std::vector<Scalar> values(nTasks,0.0);
1713 parallelFor([&cellRanges,
this,&f,flags,&values,&cellFilter](
int i,
int n) {
1714 auto range = cellRanges.range(n,i);
1715 values[i] = this->assembleCellRange<BlockFilter>(f,cellFilter,flags,range.begin(),range.end(),i);
1721 this->fValue = std::accumulate(values.begin(),values.end(),0.0);
1742 template <
class BlockFilter,
class CellFilter>
1743 Scalar assembleCellRange(F
const& f, CellFilter
const& cellFilter,
1746 using namespace Dune;
1751 boost::timer::cpu_timer scatterTimer, evalTimer, localTimer, setupTimer, totalTimer;
1752 if (statistics & localTimerStatistics)
1755 scatterTimer.stop();
1766 using MatrixBlockFilter = filter_view<MatrixBlockArray,AssemblyDetail::MatrixBlockFilter<BlockFilter>>;
1771 int const dim = Grid::dimension;
1772 typedef typename Grid::ctype CoordType;
1778 auto localRhs = as_vector(transform(*globalRhsBlocks,RhsLocalData<Policy>(
nSimultaneousBlocks)));
1784 using LocalMatrices =
decltype(as_vector(transform(MatrixBlockFilter(*globalMatrix),MatrixLocalData(0))));
1785 LocalMatrices localMatrices, localNeighborMatrices;
1788 localMatrices = as_vector(transform(MatrixBlockFilter(*globalMatrix),
1790 localNeighborMatrices = as_vector(transform(MatrixBlockFilter(*globalMatrix),
1799 using SfCache = ShapeFunctionCache<Grid,Scalar>;
1803 QuadratureTraits<QuadRule> quadratureCache;
1804 QuadratureTraits<QuadratureRule<CoordType,dim-1>> faceQuadratureCache;
1811 auto neighbourEvaluators = evaluators;
1815 auto domainCache = f.createDomainCache(flags);
1816 auto boundaryCache = f.createBoundaryCache(flags);
1817 auto innerBoundaryCache = [&](){
if constexpr (
innerBoundaries)
return f.createInnerBoundaryCache(flags);
1822 SymmetrizeLocalMatrix<Functional> symmetrizeLocalMatrix{&f};
1825 typename AnsatzVariableSetDescription::Variables ansatzVars;
1826 typename TestVariableSetDescription::Variables testVars;
1828 if (statistics & localTimerStatistics)
1834 if (statistics & localTimerStatistics)
1840 if (!cellFilter(*cell))
1847 domainCache.moveTo(*cell);
1853 int const shapeFunctionMaxOrder =
maxOrder(evaluators);
1855 if (statistics & localTimerStatistics) localTimer.resume();
1856 if (statistics & localTimerStatistics) evalTimer.stop();
1861 for_each(localRhs,ClearLocalRhs<Evaluators,TestVariables>(evaluators));
1868 int const integrationOrderOnCell = f.integrationOrder(*cell,shapeFunctionMaxOrder,
false);
1869 GeometryType gt = cell->type();
1871 QuadRule
const qr = quadratureCache.rule(gt,integrationOrderOnCell);
1874 size_t nQuadPos =
qr.size();
1875 for (
size_t g=0; g<nQuadPos; ++g)
1878 FieldVector<CoordType,dim>
const& quadPos =
qr[g].position();
1884 domainCache.evaluateAt(quadPos,evaluators);
1886 CoordType weightTimesDetJac(cell->geometry().integrationElement(quadPos));
1887 assert(weightTimesDetJac > 0);
1889 weightTimesDetJac *=
qr[g].weight();
1892 if constexpr (Self::hasValue)
1894 floc += weightTimesDetJac*domainCache.d0();
1897 typename F::DomainCache>(evaluators,weightTimesDetJac,domainCache));
1901 evaluators,weightTimesDetJac,domainCache));
1911 int const integrationOrderOnFace = f.integrationOrder(*cell,shapeFunctionMaxOrder,
true);
1920 auto faceEnd =
gv.iend(*cell);
1921 for (
auto face=
gv.ibegin(*cell); face!=faceEnd; ++face)
1932 bool const onBoundary = face->boundary();
1937 GeometryType gt = face->type();
1938 QuadratureRule<CoordType,dim-1>
const qr = faceQuadratureCache.rule(gt,integrationOrderOnFace);
1939 size_t const nQuadPos =
qr.size();
1943 boundaryCache.moveTo(face);
1946 assert(face->neighbor());
1947 assert(gt == face->geometryInOutside().type());
1950 if (! f.considerFace(*face))
1953 innerBoundaryCache.moveTo(face);
1960 for_each(localNeighborMatrices,
1966 for (
size_t g=0; g<nQuadPos; ++g)
1974 Dune::FieldVector<CoordType,dim-1> quadPos =
qr[g].position();
1975 CoordType weightTimesDetJac =
qr[g].weight() * face->geometry().integrationElement(quadPos);
1988 FieldVector<CoordType,dim>
const quadPosInCell = face->geometryInInside().global(quadPos);
1998 boundaryCache.evaluateAt(quadPos,evaluators);
2001 if constexpr (Self::hasValue)
2003 floc += weightTimesDetJac*boundaryCache.d0();
2006 typename F::BoundaryCache>(evaluators,weightTimesDetJac,boundaryCache));
2009 Evaluators,
Scalar,
typename F::BoundaryCache>(evaluators,weightTimesDetJac,boundaryCache));
2017 innerBoundaryCache.evaluateAt(quadPos,evaluators,neighbourEvaluators);
2020 if constexpr (Self::hasValue)
2022 floc += 0.5 * weightTimesDetJac*innerBoundaryCache.d0();
2024 using InnerBoundaryCache =
typename Functional::InnerBoundaryCache;
2032 Scalar,InnerBoundaryCache>
2033 (evaluators,weightTimesDetJac,innerBoundaryCache));
2041 (evaluators,evaluators,weightTimesDetJac,innerBoundaryCache,
true));
2045 (evaluators,neighbourEvaluators,weightTimesDetJac,innerBoundaryCache,
false));
2056 for_each(localMatrices,symmetrizeLocalMatrix);
2058 if (statistics & localTimerStatistics) scatterTimer.resume();
2059 if (statistics & localTimerStatistics) localTimer.stop();
2067 for_each(localRhs,ScatterLocalRhs<RhsArray>(*globalRhs));
2069 if (statistics & localTimerStatistics) evalTimer.resume();
2070 if (statistics & localTimerStatistics) scatterTimer.stop();
2073 if (statistics & localTimerStatistics) scatterTimer.resume();
2074 if (statistics & localTimerStatistics) evalTimer.stop();
2079 for_each(localRhs,ScatterLocalRhs<RhsArray>(*globalRhs,
true));
2081 if (statistics & localTimerStatistics) scatterTimer.stop();
2084 if (statistics & localTimerStatistics)
2086 std::cerr <<
"--------------\nThread " << threadNo <<
":\n";
2087 double totalTime = setupTimer.elapsed().wall + evalTimer.elapsed().wall + scatterTimer.elapsed().wall + localTimer.elapsed().wall;
2088 std::cerr.precision(1);
2089 std::cerr.setf(std::ios_base::fixed,std::ios_base::floatfield);
2090 std::cerr <<
"Total time: " << 100* totalTimer.elapsed().wall / totalTime <<
"% -- " << totalTimer.format()
2091 <<
"Setup time: " << 100* setupTimer.elapsed().wall / totalTime <<
"% -- " << setupTimer.format()
2092 <<
"Eval times: " << 100* evalTimer.elapsed().wall / totalTime <<
"% -- " << evalTimer.format()
2093 <<
"Scatter times: " << 100* scatterTimer.elapsed().wall / totalTime <<
"% -- " << scatterTimer.format()
2094 <<
"Local times: " << 100 * localTimer.elapsed().wall / totalTime <<
"% -- " << localTimer.format();
2095 std::cerr <<
"--------------\n";
2116 if (flags &
VALUE) this->fValue = 0;
2129 std::pair<size_t,size_t>
size(
int row,
int col)
const
2131 return std::make_pair(TestVariableSetDescription::degreesOfFreedom(
spaces(),row,row+1),
2132 AnsatzVariableSetDescription::degreesOfFreedom(
spaces(),col,col+1));
2163 template <
class Matrix>
2165 int rbegin=0,
int rend=TestVariableSetDescription::noOfVariables,
2166 int cbegin=0,
int cend=AnsatzVariableSetDescription::noOfVariables)
const
2169 auto cSizes = AnsatzVariableSetDescription::variableDimensions(
spaces());
2170 auto rSizes = TestVariableSetDescription::variableDimensions(
spaces());
2173 std::vector<size_t> rowOff(rend-rbegin,0), colOff(cend-cbegin,0);
2174 std::partial_sum(rSizes.begin()+rbegin,rSizes.begin()+rend-1,rowOff.begin()+1);
2175 std::partial_sum(cSizes.begin()+cbegin,cSizes.begin()+cend-1,colOff.begin()+1);
2178 extractOnlyLowerTriangle,
2179 nnz(rbegin, rend, cbegin, cend,
2180 extractOnlyLowerTriangle),
2191 template <
int row,
int col>
2194 return (*boost::fusion::find_if<AssemblyDetail::IsBlock<row,col>>(
getMatrix())).globalMatrix();
2202 template <
class MatrixType,
class BlockInformation>
2203 MatrixType
get(
bool extractOnlyLowerTriangle)
const
2205 using BI = BlockInformation;
2216 template <
class DataOutIter>
2221 for_each(
getRhs().first.data,BlockToSequence<DataOutIter>(rbegin,rend,xi));
2238 size_t nnz(
size_t rbegin=0,
size_t rend=TestVariableSetDescription::noOfVariables,
2239 size_t cbegin=0,
size_t cend=AnsatzVariableSetDescription::noOfVariables,
bool extractOnlyLowerTriangle=
false)
const
2242 boost::fusion::for_each(
getMatrix(),CountNonzeros(n,rbegin,rend,cbegin,cend,extractOnlyLowerTriangle));
2249 size_t nrows(
int firstBlock=0,
int lastBlock=TestVariableSetDescription::noOfVariables)
const
2251 return TestVariableSetDescription::degreesOfFreedom(
spaces(),firstBlock,lastBlock);
2257 size_t ncols(
int firstBlock=0,
int lastBlock=AnsatzVariableSetDescription::noOfVariables)
const
2259 return AnsatzVariableSetDescription::degreesOfFreedom(
spaces(),firstBlock,lastBlock);
2292 createMatrix([](
auto const& face) {
return true; });
2301 createMatrix([&](
auto const& face)
2304 return f.considerFace(face);
2313 template <
class FaceOracle>
2314 void createMatrix(FaceOracle
const& considerFace)
const
2319 block.init(this->
spaces(),
gv.template begin<0>(),
gv.template end<0>(),
2330 template <
int first=0,
int last=TestVariableSetDescription::noOfVariables>
2331 typename TestVariableSetDescription::template CoefficientVector<first,last>
rhs()
const
2333 using Rhs =
typename TestVariableSetDescription::template CoefficientVector<first,last>;
2338 std::pair<RhsArray&,RhsBlockArray&>
getRhs()
const
2346 rhss.reset(
new RhsArray(TestVariableSetDescription::template zeroCoefficientVector<>(
spaces())));
2353 int nrg = std::max((
int)(
rowBlockFactor*boost::thread::hardware_concurrency()),4);
2354 boost::fusion::for_each(*
rhsBlocks,[&](
auto& block)
2356 block.init(this->
spaces(),
gv.template begin<0>(),
gv.template end<0>(),nrg);
2360 return std::pair<RhsArray&,RhsBlockArray&>(*
rhss,*
rhsBlocks);
2382 mutable std::shared_ptr<RhsArray>
rhss;
2394 template <
class IdxOutIter,
class DataOutIter>
2397 BlockToTriplet(
size_t rbegin_,
size_t cbegin_, std::vector<size_t>
const& rowOff_, std::vector<size_t>
const& colOff_,
2398 IdxOutIter& ri_, IdxOutIter& ci_, DataOutIter& xi_,
bool extractOnlyLowerTriangle_):
2403 template <
class MatrixBlock>
2407 if (
inRange(mb.rowId,mb.colId))
2440 CountNonzeros(
size_t& n_,
size_t rbegin_,
size_t rend_,
size_t cbegin_,
size_t cend_,
bool onlyLowerTriangle_):
2444 template <
class MatrixBlock>
2451 if (
inRange(MatrixBlock::rowId,MatrixBlock::colId))
2474 template <
class DataOutIter>
2477 BlockToSequence(
int& rbegin_,
int& rend_, DataOutIter& out_): rbegin(rbegin_), rend(rend_), out(out_) {}
2478 template <
class VectorBlock>
void operator()(VectorBlock
const& v)
const
2480 if (rbegin<=0 && rend>0)
CachingBoundaryDetector(GridView const &gridView_)
bool hasBoundaryIntersections(Cell const &cell) const
CachingBoundaryDetector(GridSignals &signals, GridView const &gridView_)
ForwardingBoundaryDetector(GridView const &)
ForwardingBoundaryDetector(GridSignals const &, GridView const &)
bool hasBoundaryIntersections(Entity const &cell) const
Basic functionality for managing grids and their refinement.
static NumaThreadPool & instance(int maxThreads=std::numeric_limits< int >::max())
Returns a globally unique thread pool instance.
int cpus() const
Reports the total number of CPUs (usually a multiple of nodes).
A scope guard object that automatically closes a timing section on destruction.
static Timings & instance()
Returns a reference to a single default instance.
TrivialBoundaryDetector(GridView const &)
TrivialBoundaryDetector(GridSignals const &, GridView const &)
bool hasBoundaryIntersections(Entity const &cell) const
AnsatzVariableSetDescription::GridView GridView
Functional::AnsatzVars AnsatzVariableSetDescription
Self & setNSimultaneousBlocks(int n)
Defines how many cells are assembled locally before scattering them together into the global data str...
CellIterator::Entity Entity
int valid()
Returns a bitfield specifyign which of the parts have been assembled since construction or flush() ac...
void flush(int flags=(VALUE|RHS|MATRIX))
Destructs parts of the assembled quatities according to the format (VALUE|RHS|MATRX)
static unsigned int const VALUE
Self & setLocalStorageSize(size_t s)
Defines how many memory the locally assembled matrices may occupy before they are scattered.
Matrix get(bool extractOnlyLowerTriangle=false, int rbegin=0, int rend=TestVariableSetDescription::noOfVariables, int cbegin=0, int cend=AnsatzVariableSetDescription::noOfVariables) const
Extracts the submatrix defined by the half-open block ranges [rbegin,rend), [cbegin,...
Self & setGatherTimings(bool gt)
Whether to gather timing statistics using Kaskade::Timings.
AssemblyDetail::FormulationPolicy< F > Policy
GridView const & gridView() const
Functional::Scalar field_type
void assemble(F const &f, CellFilter const &cellFilter, unsigned int flags=Assembler::EVERYTHING, int nTasks=0, bool verbose=false)
Create data in assembler.
Functional::TestVars TestVariableSetDescription
typename AssemblyDetail::BlockArray< Policy, AnsatzVariables, TestVariables, SparseIndex >::type MatrixBlockArray
void toSequence(int rbegin, int rend, DataOutIter xi) const
Writes the subvector defined by the half-open block range [rbegin,rend) to the output iterator xi.
auto const & get() const
Extracts a raw single submatrix block indexed by row and column.
void reactToRefinement(GridSignals::Status const status)
static constexpr bool innerBoundaries
static unsigned int const RHS
AnsatzVariableSetDescription::Grid Grid
static unsigned int const MATRIX
std::shared_ptr< RhsArray > rhss
TestVariableSetDescription::Variables TestVariables
GridView::template Codim< 0 >::Iterator CellIterator
size_t ncols(int firstBlock=0, int lastBlock=AnsatzVariableSetDescription::noOfVariables) const
Returns the number of scalar cols in the column block range [firstBlock,lastBlock[.
AssemblyDetail::RhsBlockArray< Policy, TestVariables >::type RhsBlockArray
AnsatzVariableSetDescription::Spaces Spaces
std::shared_ptr< MatrixBlockArray > matrixBlocks
TestVariableSetDescription::template CoefficientVector< first, last > rhs() const
Returns a contiguous subrange of the rhs coefficient vectors.
size_t nrows(int firstBlock=0, int lastBlock=TestVariableSetDescription::noOfVariables) const
Returns the number of scalar rows in the row block range [firstBlock,lastBlock[.
AnsatzVariableSetDescription::Variables AnsatzVariables
TestVariableSetDescription::template CoefficientVector RhsArray
Spaces const & spaces() const
VariationalFunctionalAssembler< F, SparseIndex, BoundaryDetector, QuadRule > Self
VariationalFunctionalAssembler(Spaces const &spaces)
Construct an empty assembler, gridManager is implicitly obtained from the first space.
AnsatzVariableSetDescription::IndexSet IndexSet
std::pair< size_t, size_t > size(int row, int col) const
the size of a matrix block (in terms of scalar rows/columns)
size_t nnz(size_t rbegin=0, size_t rend=TestVariableSetDescription::noOfVariables, size_t cbegin=0, size_t cend=AnsatzVariableSetDescription::noOfVariables, bool extractOnlyLowerTriangle=false) const
Returns the number of structurally nonzero entries in the submatrix defined by the half-open block ra...
MatrixType get(bool extractOnlyLowerTriangle) const
Extracts the submatrix defined by the half-open block ranges given as template parameter.
std::pair< RhsArray &, RhsBlockArray & > getRhs() const
GridManagerBase< Grid > const & gridManager
static unsigned int const EVERYTHING
boost::signals2::scoped_connection refConnection
BoundaryDetector boundaryDetector
void assemble(F const &f, unsigned int flags=Assembler::EVERYTHING, int nThreads=0, bool verbose=false)
Assembly without block filter or cell filter.
std::shared_ptr< RhsBlockArray > rhsBlocks
MatrixBlockArray & getMatrix() const
Returns a mutable reference to the sequence of matrix blocks.
Self & setRowBlockFactor(double a)
Defines how many more row blocks in each matrix are used compared to the number of threads.
IndexSet const & indexSet
boost::fusion::result_of::make_range< First, Last, Sequence >::type make_range(Sequence &s)
Constructs a boost::fusion view that picks a certain range from a forward sequence.
Utility classes for the definition and use of variational functionals.
std::tuple< std::vector< typename EntryTraits< Entry >::field_type >, DynamicMatrix< typename EntryTraits< Entry >::field_type >, std::vector< int > > qr(DynamicMatrix< Entry > const &A)
Computes a rank-revealing QR decomposition of using column pivoting.
void useQuadratureRuleInEvaluators(Evaluator &evals, QuadratureRule const &qr, int subId)
Tells all evaluators to use the given quadrature rule on the given subentity.
void moveEvaluatorsToIntegrationPoint(Evaluators &evals, Dune::FieldVector< CoordType, dim > const &x, Dune::QuadratureRule< CoordType, subDim > const &qr, int ip, int subId)
Moves all provided evaluators to the given integration point, evaluating the shape functions there.
int maxOrder(Evaluators const &evals)
Computes the maximum ansatz order used in a collection of evaluators.
typename boost::fusion::result_of::as_vector< typename boost::fusion::result_of::transform< Spaces, GetEvaluatorTypes >::type >::type Evaluators
the heterogeneous sequence type of Evaluators for the given spaces
auto getEvaluators(Spaces const &spaces, ShapeFunctionCache *cache, std::map< void const *, int > const &deriv=std::map< void const *, int >())
returns a heterogeneous sequence of evaluators for the given spaces
constexpr bool hasInnerBoundaryCache
Checks whether InnerBoundaryCache is declared in Functional.
boost::signals2::signal< void(Status)> informAboutRefinement
A signal that is emitted thrice on grid modifications, once before adaptation takes place and twice a...
typename GridView::template Codim< 0 >::Entity Cell
The type of cells (entities of codimension 0) in the grid view.
Status
The argument type of the signal that is emitted before and after grid adaptation.
bool makePositiveSemiDefinite(Dune::FieldMatrix< Scalar, d, d > &A)
Computes a positive semi-definite approximation to by cutting off negative eigenvalues.
void parallelFor(Func const &f, int maxTasks=std::numeric_limits< int >::max())
A parallel for loop that executes the given functor in parallel on different CPUs.
T & removeConst(T const &t)
A convenience template for removing the const qualifier from references and pointers.
void vector(char const *phase, char const *direction, int id, int peer, char const *stage, std::vector< T > const &data)
double transpose(double x)
bool considerFace(Face const &face, std::vector< int > const &boundaryIds, std::vector< int > const &usedIds)
OutIter vectorToSequence(double x, OutIter iter)
void moveEvaluatorsToCell(Evaluators &evals, Cell const &cell)
Moves all provided evaluators to the given cell.
constexpr bool symmetryCheck
Specialize this template for your matrix type in order to use it with VariationalFunctionalAssembler:...
A class that provides access to signals that are emitted from the grid manager on various occasions.
A class template that supports converting certain Dune matrices into the coordinate (triplet) format.
BlockToSequence(int &rbegin_, int &rend_, DataOutIter &out_)
void operator()(VectorBlock const &v) const
std::vector< size_t > const & colOff
bool extractOnlyLowerTriangle
bool inRange(size_t r, size_t c) const
void operator()(MatrixBlock const &mb) const
BlockToTriplet(size_t rbegin_, size_t cbegin_, std::vector< size_t > const &rowOff_, std::vector< size_t > const &colOff_, IdxOutIter &ri_, IdxOutIter &ci_, DataOutIter &xi_, bool extractOnlyLowerTriangle_)
std::vector< size_t > const & rowOff
CountNonzeros(size_t &n_, size_t rbegin_, size_t rend_, size_t cbegin_, size_t cend_, bool onlyLowerTriangle_)
bool inRange(size_t r, size_t c) const
void operator()(MatrixBlock const &mb) const
Variables and their descriptions.