KASKADE 7 development version
iterate_grid.hh
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the library KASKADE 7 */
4/* https://www.zib.de/research/projects/kaskade7-finite-element-toolbox */
5/* */
6/* Copyright (C) 2002-2023 Zuse Institute Berlin */
7/* */
8/* KASKADE 7 is distributed under the terms of the ZIB Academic License. */
9/* see $KASKADE/academic.txt */
10/* */
11/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13#ifndef ITERATE_GRID_HH
14#define ITERATE_GRID_HH
15
16#include <boost/fusion/algorithm.hpp>
17#include <boost/fusion/sequence.hpp>
18
19#include "dune/grid/common/grid.hh"
20#include "dune/geometry/quadraturerules.hh"
21
22#include "fem/functionspace.hh"
23#include "fem/quadrature.hh"
24#include "fem/variables.hh"
25
27
28namespace Kaskade
29{
30 namespace GridIterateDetail
31 {
32 template <class VariableDescriptions, class Functor, class Functions, class Spaces, class CellRange>
33 void gridIterateRange(VariableDescriptions const& , Functions const& functions, Spaces const& spaces,
34 Functor& f, CellRange cells)
35 {
36 using namespace boost::fusion;
37 using namespace Dune;
38
39 typedef typename SpaceType<Spaces,0>::type::Grid Grid;
40 typedef typename SpaceType<Spaces,0>::type::Scalar Scalar;
41 typedef typename Grid::ctype CoordType;
42 int const dim = Grid::dimension;
43
44 auto const& gridView = at_c<0>(spaces)->gridView();
45
46 // Shape function cache. Remember that every thread has to use its own cache!
47 typedef ShapeFunctionCache<Grid,Scalar> SfCache;
48 SfCache sfCache;
49
50 // Quadrature rule cache
52 QuadratureTraits<QuadRule> quadratureCache;
53
54 // Evaluators for shape functions of all FE spaces. Remember that
55 // every thread has to use its own collection of evaluators!
56 auto evaluators = getEvaluators(spaces,&sfCache);
57
58 // Iterate over all cells.
59 for (auto const& cell: cells)
60 {
61 // for all spaces involved, compute the shape functions and
62 // their global indices, which are needed for evaluating the
63 // functional's derivative.
64 auto idx = gridView.indexSet().index(cell);
65 moveEvaluatorsToCell(evaluators,cell,idx);
66
67 // loop over all quadrature points and evaluate variables
68 int const p = f.integrationOrder(cell,maxOrder(evaluators));
69
70 QuadRule const& qr = quadratureCache.rule(cell.type(),p);
71 useQuadratureRuleInEvaluators(evaluators,qr,0);
72
73 size_t nQuadPos = qr.size();
74 for (size_t g=0; g<nQuadPos; ++g)
75 {
76 // pos of integration point
77 auto const& quadPos = qr[g].position();
78
79 // for all spaces involved, update the evaluators associated
80 // to this quadrature point
81 moveEvaluatorsToIntegrationPoint(evaluators,quadPos,qr,g,0);
82
83 // evaluate functions and call functor
84 f(cell,idx,quadPos,cell.geometry().integrationElement(quadPos)*qr[g].weight(),
85 evaluateFunctions<VariableDescriptions>(functions,evaluators,valueMethod));
86 }
87 }
88 };
89
90 } // end of namespace GridIterateDetail
91
120 template <class VariableList, class Collector, class Functions, class Spaces>
121 void gridIterate(VariableList const& vars, Functions const& functions, Spaces const& spaces, Collector& f)
122 {
123 using namespace boost::fusion;
124 auto const& gridView = at_c<0>(spaces)->gridView();
125 auto const& cellRanges = at_c<0>(spaces)->gridManager().cellRanges(gridView);
126
127 int n = std::min(NumaThreadPool::instance().cpus(),cellRanges.maxRanges());
128 std::vector<Collector> fs(n,f);
129
130 parallelFor([&vars,&functions,&spaces,&cellRanges,&fs](int i, int n)
131 {
132 GridIterateDetail::gridIterateRange(vars,functions,spaces,fs[i],cellRanges.range(n,i));
133 },n);
134
135 for (auto& g: fs)
136 f.join(g);
137 }
138
147 template <class VariableSet, class Collector>
148 void gridIterate(VariableSet const& functions, Collector& f)
149 {
150 gridIterate(typename VariableSet::Descriptions::Variables(),functions.data,
151 functions.descriptions.spaces,f);
152 }
153
154
155
156 //---------------------------------------------------------------------
157
165 {
166 template <class Cell, class F>
167 void operator()(Cell const&,
169 F&) const {}
170 };
171
172
179 {
180 template <class Cell>
181 int integrationOrder(Cell const& /* ci */, int shapeFunctionOrder) const
182 {
183 return shapeFunctionOrder;
184 }
185
186 template <class Cell, class Index, class LocalPosition, class Sequence>
187 void operator()(Cell const&, Index, LocalPosition const&, double weight, Sequence const& x)
188 {
189 if (sum.empty())
190 sum.resize(boost::fusion::size(x),0);
191 auto i = sum.begin(); // provide a reference to the iterator
192 boost::fusion::for_each(x,Add(weight,i)); // because that is incremented on each call of Add
193 } // (hack: for_each requires an immutable functor)
194
196 {
197 if (sum.empty())
198 sum = c.sum;
199 else
200 {
201 assert(sum.size()==c.sum.size());
202 for (int i=0; i<sum.size(); ++i)
203 sum[i] += c.sum[i];
204 }
205 }
206
207 std::vector<double> sum;
208
209 private:
210 struct Add
211 {
212 Add(double w_, std::vector<double>::iterator& i_): w(w_), i(i_) {}
213 template <class T>
214 void operator()(T const& t) const { *i += w*t; ++i; }
215
216 private:
217 double w;
218 std::vector<double>::iterator& i;
219 };
220 };
221
222
223
224
231 template <class Functions, class Scaling, class Collector>
233 {
234 public:
235
242 ScaledTwoNorm2Collector(Scaling const& scaling_, Collector& collector_)
243 : scaling(scaling_)
244 , collector(collector_)
245 { }
246
247 template <class Cell>
248 int integrationOrder(Cell const& cell, int shapeFunctionOrder) const
249 {
250 return 2*collector.integrationOrder(cell,shapeFunctionOrder);
251 }
252
253 template <class Cell, class Index, class Sequence>
254 void operator()(Cell const& cell, Index idx,
256 double weight, Sequence const& seq)
257 {
258 using namespace boost::fusion;
259 typename result_of::as_vector<Sequence>::type values(seq);
260 scaling(cell,xi,values);
261 collector(cell,idx,xi,weight,transform(values,TwoNorm2()));
262 }
263
265 {
266 collector.join(c.collector);
267 }
268
269 Collector const& data() const { return collector; }
270
271 private:
272 // a boost::fusion functor computing the squared euclidean norm of given vectors
273 struct TwoNorm2
274 {
275 template <class T> struct result {};
276
277 template <class Vec>
278 struct result<TwoNorm2(Vec)> { typedef Dune::FieldVector<double,1> type; };
279
280 template <class Vec>
281 typename result<TwoNorm2(Vec)>::type operator()(Vec const& v) const { return v.two_norm2(); }
282 };
283
284 Scaling const& scaling;
285 Collector collector; // keep collector by value as we write concurrently in different objects.
286 };
287
303 template <class Variables, class Functions, class Spaces, class Scaling, class Collector>
304 void scaledTwoNormSquared(Variables const& varDesc, Functions const& f, Spaces const& spaces,
305 Scaling const& scaling, Collector& sum)
306 {
308 gridIterate(varDesc,f,spaces,collector);
309 sum = collector.data();
310 }
311
312
313 //---------------------------------------------------------------------
314
318 namespace relativeErrorDetail {
319
320 template <class F>
321 struct Difference
322 {
323 typedef typename F::Scalar RT;
324 typedef RT Scalar;
325
326 static int const Components = F::components;
327
328 typedef typename F::Space Space;
329 typedef typename F::ValueType ValueType;
330
331 Difference(F const& f1_, F const& f2_): f1(f1_), f2(f2_) { }
332
333 ValueType value(typename Space::Evaluator const& evaluator) const
334 {
335 return f1.value(evaluator)-f2.value(evaluator);
336 }
337
338 Space const& space() const { return f1.space(); }
339
340 private:
341 F const& f1;
342 F const& f2;
343 };
344
345
346 struct MakeDifference
347 {
348 template <class T> struct result {};
349
350 template <class Pair>
351 struct result<MakeDifference(Pair)>
352 {
353 typedef typename boost::fusion::result_of::value_at_c<Pair,0>::type T;
354
355 typedef Difference<typename boost::remove_const<typename boost::remove_reference<T>::type>::type> type;
356 };
357
358 template <class Pair>
359 typename result<MakeDifference(Pair)>::type operator()(Pair const& pair) const
360 {
361 return typename result<MakeDifference(Pair)>::type(boost::fusion::at_c<0>(pair),boost::fusion::at_c<1>(pair));
362 }
363 };
364
365
366 } // End of namespace relativeErrorDetail
381 template <class Variables, class OutIter, class Functions, class Spaces, class Scaling>
382 void relativeError(Variables const& varDesc, Functions const& f1, Functions const& f2, Functions const& f3,
383 Spaces const& spaces, Scaling const& scaling, OutIter out)
384 {
385 using namespace boost::fusion;
386
387 int const s = size(f1);
389 // scaledTwoNormSquared(join(varDesc,varDesc),
390 // join( f3, as_vector(transform(zip(f1,f2),relativeErrorDetail::MakeDifference())) ),
391 // spaces,scaling,sum);
392 scaledTwoNormSquared(join(varDesc,varDesc),
393 join(as_vector(transform(zip(f1,f2),relativeErrorDetail::MakeDifference())),f3),
394 spaces,scaling,sum);
395 // To my understanding, the as_vector call in the statement above
396 // should not be necessary. However, it prevents a (rare but
397 // reproducible) segfault with gcc 4.3.4 -O2. Funny thing is, some
398 // output statements to cerr have the same effect. The cause may be
399 // either a wild pointer bug in the code exposed by -O2 or a code
400 // generation bug in gcc. Sigh. At least, since Difference objects
401 // are lightweight, the explicit vector construction should not be a
402 // performance penalty. ws 2009-12-03
403
404 for (int i=0; i<s; ++i) {
405 *out = std::make_pair(std::sqrt(sum.sum[i]),std::sqrt(sum.sum[i+s]));
406 ++out;
407 }
408 }
409} // end of namespace Kaskade
410
411
412#endif
Defines an interface for integrating values computed over a grid.
Definition: concepts.hh:526
void join(Collector &c)
Merges the result of two concurrently filled collectors.
int integrationOrder(Cell const &, int shapeFunctionOrder) const
static NumaThreadPool & instance(int maxThreads=std::numeric_limits< int >::max())
Returns a globally unique thread pool instance.
A functor for computing scaled -norms of a set of (possibly vector-valued) functions.
void join(ScaledTwoNorm2Collector const &c)
int integrationOrder(Cell const &cell, int shapeFunctionOrder) const
ScaledTwoNorm2Collector(Scaling const &scaling_, Collector &collector_)
Constructor.
Collector const & data() const
void operator()(Cell const &cell, Index idx, Dune::FieldVector< typename Cell::Geometry::ctype, Cell::dimension > const &xi, double weight, Sequence const &seq)
A class for storing a heterogeneous collection of FunctionSpaceElement s.
Definition: variables.hh:341
Descriptions const & descriptions
Descriptions of variable set, of type VariableSetDescription (lots of useful infos)
Definition: variables.hh:510
A callable that allows to implement weighted (scaled) norms.
Definition: concepts.hh:405
FEFunctionSpace and FunctionSpaceElement and the like.
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 GridView::template Codim< 0 >::Entity Cell
The type of cells (entities of codimension 0) in the grid view.
Definition: gridBasics.hh:35
Dune::FieldVector< T, n > min(Dune::FieldVector< T, n > x, Dune::FieldVector< T, n > const &y)
Componentwise minimum.
Definition: fixdune.hh:122
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.
Definition: threading.hh:489
constexpr auto valueMethod
Helper method for evaluating whole variable sets.
Definition: variables.hh:1018
void gridIterateRange(VariableDescriptions const &, Functions const &functions, Spaces const &spaces, Functor &f, CellRange cells)
Definition: iterate_grid.hh:33
void gridIterate(VariableList const &vars, Functions const &functions, Spaces const &spaces, Collector &f)
A function that supports general iterations over a spatial domain and supports efficient evaluation o...
void scaledTwoNormSquared(Variables const &varDesc, Functions const &f, Spaces const &spaces, Scaling const &scaling, Collector &sum)
Evaluates the square of the scaled -norms of a set of functions.
void relativeError(Variables const &varDesc, Functions const &f1, Functions const &f2, Functions const &f3, Spaces const &spaces, Scaling const &scaling, OutIter out)
void moveEvaluatorsToCell(Evaluators &evals, Cell const &cell)
Moves all provided evaluators to the given cell.
A trivial Scaling.
void operator()(Cell const &, Dune::FieldVector< typename Cell::Geometry::ctype, Cell::dimension > const &, F &) const
A cache that stores suitable quadrature rules for quick retrieval.
Definition: quadrature.hh:35
static Rule const & rule(const Dune::GeometryType &t, int p)
Definition: quadrature.hh:38
Extracts the type of FE space with given index from set of spaces.
A Collector that sums up the weighted contributions.
void join(SummationCollector const &c)
int integrationOrder(Cell const &, int shapeFunctionOrder) const
void operator()(Cell const &, Index, LocalPosition const &, double weight, Sequence const &x)
std::vector< double > sum
Variables and their descriptions.