DUNE PDELab (git)

vtk.hh
1#ifndef DUNE_PDELAB_GRIDFUNCTIONSPACE_VTK_HH
2#define DUNE_PDELAB_GRIDFUNCTIONSPACE_VTK_HH
3
4#include <vector>
5#include <sstream>
6
9
11
12#include <dune/localfunctions/common/interfaceswitch.hh>
13
14#include <dune/typetree/visitor.hh>
15#include <dune/typetree/traversal.hh>
16
17#include <dune/pdelab/common/function.hh>
18#include <dune/pdelab/common/vtkexport.hh>
19#include <dune/pdelab/common/vtkexport.hh>
20#include <dune/pdelab/gridfunctionspace/localfunctionspace.hh>
21#include <dune/pdelab/gridfunctionspace/lfsindexcache.hh>
23
24namespace Dune {
25
26 template<typename GV>
27 class VTKWriter;
28
29 template<typename GV>
30 class SubsamplingVTKWriter;
31
32 template<typename GV>
33 class VTKSequenceWriter;
34
35 namespace PDELab {
36
37 namespace vtk {
38
39 namespace {
40
41 template<typename VTKWriter>
42 struct vtk_writer_traits;
43
44 template<typename GV>
45 struct vtk_writer_traits<Dune::VTKWriter<GV> >
46 {
47 typedef GV GridView;
48 };
49
50 template<typename GV>
51 struct vtk_writer_traits<Dune::SubsamplingVTKWriter<GV> >
52 {
53 typedef GV GridView;
54 };
55
56 template<typename GV>
57 struct vtk_writer_traits<Dune::VTKSequenceWriter<GV> >
58 {
59 typedef GV GridView;
60 };
61
62 }
63
64 template<typename LFS, typename Data>
65 class DGFTreeLeafFunction;
66
67 template<typename LFS, typename Data>
68 class DGFTreeVectorFunction;
69
70 template<typename VTKWriter, typename Data>
71 struct OutputCollector;
72
73
75 template<typename GFS, typename X, typename Pred>
77 {
78
79 template<typename LFS, typename Data>
80 friend class DGFTreeLeafFunction;
81
82 template<typename LFS, typename Data>
83 friend class DGFTreeVectorFunction;
84
85 template<typename, typename>
86 friend struct OutputCollector;
87
89 typedef LFSIndexCache<LFS> LFSCache;
90 typedef typename X::template ConstLocalView<LFSCache> XView;
92 using EntitySet = typename GFS::Traits::EntitySet;
93 using Cell = typename EntitySet::Traits::Element;
94 using IndexSet = typename EntitySet::Traits::IndexSet;
95 typedef typename IndexSet::IndexType size_type;
96
97 static const auto dim = EntitySet::dimension;
98
99 public:
100
101 typedef GFS GridFunctionSpace;
102 typedef X Vector;
103 typedef Pred Predicate;
104
105 DGFTreeCommonData(std::shared_ptr<const GFS> gfs, std::shared_ptr<const X> x)
106 : _lfs(gfs)
107 , _lfs_cache(_lfs)
108 , _x_view(x)
109 , _x_local(_lfs.maxSize())
110 , _index_set(gfs->entitySet().indexSet())
111 , _current_cell_index(std::numeric_limits<size_type>::max())
112 , x(x)
113 {}
114
115 public:
116
117 void bind(const Cell& cell)
118 {
119 auto cell_index = _index_set.uniqueIndex(cell);
120 if (_current_cell_index == cell_index)
121 return;
122
123 _lfs.bind(cell);
124 _lfs_cache.update();
125 _x_view.bind(_lfs_cache);
126 _x_view.read(_x_local);
127 _x_view.unbind();
128 _current_cell_index = cell_index;
129 }
130
131 LFS _lfs;
132 LFSCache _lfs_cache;
133 XView _x_view;
134 XLocalVector _x_local;
135 const IndexSet& _index_set;
136 size_type _current_cell_index;
137
138 // This copy of x is stored here in order to have this object take ownership
139 // of the passed data. This is necessary to prevent a premature release.
140 std::shared_ptr<const X> x;
141 };
142
143
144
145 template<typename LFS, typename Data>
146 class DGFTreeLeafFunction
147 : public GridFunctionBase<GridFunctionTraits<
148 typename LFS::Traits::GridView,
149 typename BasisInterfaceSwitch<
150 typename FiniteElementInterfaceSwitch<
151 typename LFS::Traits::FiniteElement
152 >::Basis
153 >::RangeField,
154 BasisInterfaceSwitch<
155 typename FiniteElementInterfaceSwitch<
156 typename LFS::Traits::FiniteElement
157 >::Basis
158 >::dimRange,
159 typename BasisInterfaceSwitch<
160 typename FiniteElementInterfaceSwitch<
161 typename LFS::Traits::FiniteElement
162 >::Basis
163 >::Range
164 >,
165 DGFTreeLeafFunction<LFS,Data>
166 >
167 {
168
169 typedef BasisInterfaceSwitch<
171 typename LFS::Traits::FiniteElement
172 >::Basis
173 > BasisSwitch;
174
175 typedef GridFunctionBase<
177 typename LFS::Traits::GridView,
180 typename BasisSwitch::Range
181 >,
182 DGFTreeLeafFunction<LFS,Data>
183 > BaseT;
184
185 public:
186 typedef typename BaseT::Traits Traits;
187
188 DGFTreeLeafFunction (const LFS& lfs, const std::shared_ptr<Data>& data)
189 : BaseT(lfs.gridFunctionSpace().dataSetType())
190 , _lfs(lfs)
191 , _data(data)
192 , _basis(lfs.maxSize())
193 {}
194
195 // Evaluate
196 void evaluate (const typename Traits::ElementType& e,
197 const typename Traits::DomainType& x,
198 typename Traits::RangeType& y) const
199 {
200 _data->bind(e);
201
203 typename LFS::Traits::FiniteElement
204 > FESwitch;
205
206 y = 0;
207
208 if (_lfs.size()) {
209 FESwitch::basis(_lfs.finiteElement()).evaluateFunction(x,_basis);
210 for (std::size_t i = 0; i < _lfs.size(); ++i)
211 y.axpy(_data->_x_local(_lfs,i),_basis[i]);
212 }
213 }
214
216 const typename Traits::GridViewType& gridView() const
217 {
218 return _lfs.gridFunctionSpace().gridView();
219 }
220
221 const LFS& localFunctionSpace() const
222 {
223 return _lfs;
224 }
225
226 private:
227
228 const LFS& _lfs;
229 const std::shared_ptr<Data> _data;
230 mutable std::vector<typename Traits::RangeType> _basis;
231
232 };
233
234
235
236 template<typename LFS, typename Data>
237 class DGFTreeVectorFunction
238 : public GridFunctionBase<GridFunctionTraits<
239 typename LFS::Traits::GridView,
240 typename BasisInterfaceSwitch<
241 typename FiniteElementInterfaceSwitch<
242 typename LFS::ChildType::Traits::FiniteElement
243 >::Basis
244 >::RangeField,
245 TypeTree::StaticDegree<LFS>::value,
246 Dune::FieldVector<
247 typename BasisInterfaceSwitch<
248 typename FiniteElementInterfaceSwitch<
249 typename LFS::ChildType::Traits::FiniteElement
250 >::Basis
251 >::RangeField,
252 TypeTree::StaticDegree<LFS>::value
253 >
254 >,
255 DGFTreeVectorFunction<LFS,Data>
256 >
257 {
258
259 typedef BasisInterfaceSwitch<
260 typename FiniteElementInterfaceSwitch<
261 typename LFS::ChildType::Traits::FiniteElement
262 >::Basis
263 > BasisSwitch;
264
265 static_assert(BasisSwitch::dimRange == 1,
266 "Automatic conversion to vector-valued function only supported for scalar components");
267
268 typedef GridFunctionBase<
269 GridFunctionTraits<
270 typename LFS::Traits::GridView,
272 TypeTree::StaticDegree<LFS>::value,
275 TypeTree::StaticDegree<LFS>::value
276 >
277 >,
278 DGFTreeVectorFunction<LFS,Data>
279 > BaseT;
280
281 public:
282
283 typedef typename BaseT::Traits Traits;
284 typedef typename LFS::ChildType ChildLFS;
285 typedef typename ChildLFS::Traits::FiniteElement::Traits::LocalBasisType::Traits::RangeFieldType RF;
286 typedef typename ChildLFS::Traits::FiniteElement::Traits::LocalBasisType::Traits::RangeType RT;
287
288 DGFTreeVectorFunction (const LFS& lfs, const std::shared_ptr<Data>& data)
289 : BaseT(lfs.gridFunctionSpace().dataSetType())
290 , _lfs(lfs)
291 , _data(data)
292 , _basis(lfs.maxSize())
293 {}
294
295 void evaluate (const typename Traits::ElementType& e,
296 const typename Traits::DomainType& x,
297 typename Traits::RangeType& y) const
298 {
299 _data->bind(e);
300
301 typedef FiniteElementInterfaceSwitch<
302 typename ChildLFS::Traits::FiniteElement
303 > FESwitch;
304
305 y = 0;
306
307 for (std::size_t k = 0; k < TypeTree::degree(_lfs); ++k)
308 {
309 const ChildLFS& child_lfs = _lfs.child(k);
310 FESwitch::basis(child_lfs.finiteElement()).evaluateFunction(x,_basis);
311
312 for (std::size_t i = 0; i < child_lfs.size(); ++i)
313 y[k] += _data->_x_local(child_lfs,i) * _basis[i];
314 }
315 }
316
318 const typename Traits::GridViewType& gridView() const
319 {
320 return _lfs.gridFunctionSpace().gridView();
321 }
322
323 const LFS& localFunctionSpace() const
324 {
325 return _lfs;
326 }
327
328 private:
329
330 const LFS& _lfs;
331 const std::shared_ptr<Data> _data;
332 mutable std::vector<typename BasisSwitch::Range> _basis;
333
334 };
335
336
337 class DefaultFunctionNameGenerator
338 {
339
340 public:
341
342 template<typename TreePath>
343 std::string operator()(std::string component_name, TreePath tp) const
344 {
345 if (component_name.empty())
346 {
347
348 if (_prefix.empty() && _suffix.empty())
349 {
350 DUNE_THROW(IOError,
351 "You need to either name all GridFunctionSpaces "
352 "written to the VTK file or provide a prefix / suffix.");
353 }
354
355 std::stringstream name_stream;
356
357 if (!_prefix.empty())
358 name_stream << _prefix << _separator;
359
360 // Build a simple name based on the component's TreePath (e.g. 0_2_3)
361 for (std::size_t i = 0; i < tp.size(); ++i)
362 name_stream << (i > 0 ? _separator : "") << tp.element(i);
363
364 if (!_suffix.empty())
365 name_stream << _separator << _suffix;
366 return name_stream.str();
367 }
368 else
369 {
370 // construct name from prefix, component name and suffix
371 return _prefix + component_name + _suffix;
372 }
373 }
374
375 DefaultFunctionNameGenerator& prefix(std::string prefix)
376 {
377 _prefix = prefix;
378 return *this;
379 }
380
381 DefaultFunctionNameGenerator& suffix(std::string suffix)
382 {
383 _suffix = suffix;
384 return *this;
385 }
386
387 DefaultFunctionNameGenerator& separator(std::string separator)
388 {
389 _separator = separator;
390 return *this;
391 }
392
393 DefaultFunctionNameGenerator(std::string prefix = "",
394 std::string suffix = "",
395 std::string separator = "_")
396 : _prefix(prefix)
397 , _suffix(suffix)
398 , _separator(separator)
399 {}
400
401 private:
402
403 std::string _prefix;
404 std::string _suffix;
405 std::string _separator;
406
407 };
408
409 inline DefaultFunctionNameGenerator defaultNameScheme()
410 {
411 return DefaultFunctionNameGenerator();
412 }
413
414
415 template<typename VTKWriter, typename Data, typename NameGenerator>
416 struct add_solution_to_vtk_writer_visitor
417 : public TypeTree::DefaultVisitor
418 , public TypeTree::DynamicTraversal
419 {
420
421
422 template<typename LFS, typename Child, typename TreePath>
423 struct VisitChild
424 {
425
426 static const bool value =
427 // Do not descend into children of VectorGridFunctionSpace
428 !std::is_convertible<
429 TypeTree::ImplementationTag<typename LFS::Traits::GridFunctionSpace>,
430 VectorGridFunctionSpaceTag
431 >::value;
432
433 };
434
437 template<typename DGF, typename TreePath>
438 void add_to_vtk_writer(const std::shared_ptr<DGF>& dgf, TreePath tp)
439 {
440 std::string name = name_generator(dgf->localFunctionSpace().gridFunctionSpace().name(),tp);
441 switch (dgf->dataSetType())
442 {
443 case DGF::Output::vertexData:
444 vtk_writer.addVertexData(std::make_shared<VTKGridFunctionAdapter<DGF> >(dgf,name.c_str()));
445 break;
446 case DGF::Output::cellData:
447 vtk_writer.addCellData(std::make_shared<VTKGridFunctionAdapter<DGF> >(dgf,name.c_str()));
448 break;
449 default:
450 DUNE_THROW(NotImplemented,"Unsupported data set type");
451 }
452 }
453
455
458 template<typename LFS, typename TreePath>
459 void add_vector_solution(const LFS& lfs, TreePath tp, VectorGridFunctionSpaceTag tag)
460 {
461 add_to_vtk_writer(std::make_shared<DGFTreeVectorFunction<LFS,Data> >(lfs,data),tp);
462 }
463
465
468 template<typename LFS, typename TreePath>
469 void add_vector_solution(const LFS& lfs, TreePath tp, GridFunctionSpaceTag tag)
470 {
471 // do nothing here - not a vector space
472 }
473
474 // **********************************************************************
475 // Visitor functions for adding DiscreteGridFunctions to VTKWriter
476 //
477 // The visitor functions contain a switch that will make them ignore
478 // function spaces with a different underlying GridView type than
479 // the VTKWriter.
480 // This cannot happen in vanilla PDELab, but is required for MultiDomain
481 // support
482 // **********************************************************************
483
484 // don't do anything if GridView types differ
485 template<typename LFS, typename TreePath>
486 typename std::enable_if<
487 !std::is_same<
488 typename LFS::Traits::GridFunctionSpace::Traits::GridView,
489 typename vtk_writer_traits<VTKWriter>::GridView
490 >::value
491 >::type
492 post(const LFS& lfs, TreePath tp)
493 {
494 }
495
496 // don't do anything if GridView types differ
497 template<typename LFS, typename TreePath>
498 typename std::enable_if<
499 !std::is_same<
500 typename LFS::Traits::GridFunctionSpace::Traits::GridView,
501 typename vtk_writer_traits<VTKWriter>::GridView
502 >::value
503 >::type
504 leaf(const LFS& lfs, TreePath tp)
505 {
506 }
507
509 template<typename LFS, typename TreePath>
510 typename std::enable_if<
511 std::is_same<
512 typename LFS::Traits::GridFunctionSpace::Traits::GridView,
513 typename vtk_writer_traits<VTKWriter>::GridView
514 >::value
515 >::type
516 post(const LFS& lfs, TreePath tp)
517 {
518 if (predicate(lfs, tp))
519 add_vector_solution(lfs,tp,TypeTree::ImplementationTag<typename LFS::Traits::GridFunctionSpace>());
520 }
521
523 template<typename LFS, typename TreePath>
524 typename std::enable_if<
525 std::is_same<
526 typename LFS::Traits::GridFunctionSpace::Traits::GridView,
527 typename vtk_writer_traits<VTKWriter>::GridView
528 >::value
529 >::type
530 leaf(const LFS& lfs, TreePath tp)
531 {
532 if (predicate(lfs, tp))
533 add_to_vtk_writer(std::make_shared<DGFTreeLeafFunction<LFS,Data> >(lfs,data),tp);
534 }
535
536
537 add_solution_to_vtk_writer_visitor(VTKWriter& vtk_writer_, std::shared_ptr<Data> data_, const NameGenerator& name_generator_, const typename Data::Predicate& predicate_)
538 : vtk_writer(vtk_writer_)
539 , data(data_)
540 , name_generator(name_generator_)
541 , predicate(predicate_)
542 {}
543
544 VTKWriter& vtk_writer;
545 std::shared_ptr<Data> data;
546 const NameGenerator& name_generator;
547 typename Data::Predicate predicate;
548
549 };
550
551 struct DefaultPredicate
552 {
553 template<typename LFS, typename TP>
554 bool operator()(const LFS& lfs, TP tp) const
555 {
556 return true;
557 }
558 };
559
560 template<typename VTKWriter, typename Data_>
561 struct OutputCollector
562 {
563
565 typedef Data_ Data;
566
567 typedef typename Data::GridFunctionSpace GFS;
568 typedef typename Data::Vector Vector;
569 typedef typename Data::Predicate Predicate;
570
571 template<typename NameGenerator>
572 OutputCollector& addSolution(const NameGenerator& name_generator)
573 {
574
575 add_solution_to_vtk_writer_visitor<VTKWriter,Data,NameGenerator> visitor(_vtk_writer,_data,name_generator,_predicate);
576 TypeTree::applyToTree(_data->_lfs,visitor);
577 return *this;
578 }
579
580 template<typename Factory, typename TreePath>
581 OutputCollector& addCellFunction(Factory factory, TreePath tp, std::string name)
582 {
583 typedef typename std::remove_reference<decltype(*factory.create(_data->_lfs.child(tp),_data))>::type DGF;
584 _vtk_writer.addCellData(std::make_shared<VTKGridFunctionAdapter<DGF> >(factory.create(_data->_lfs.child(tp),_data),name));
585 return *this;
586 }
587
588 template<template<typename...> class Function, typename TreePath, typename... Params>
589 OutputCollector& addCellFunction(TreePath tp, std::string name, Params&&... params)
590 {
591 using LFS = TypeTree::ChildForTreePath<typename Data::LFS,TreePath>;
592 typedef Function<LFS,Data,Params...> DGF;
593 _vtk_writer.addCellData(
594 std::make_shared<VTKGridFunctionAdapter<DGF> >(
595 std::make_shared<DGF>(
596 TypeTree::child(_data->_lfs,tp)
597 ),
598 _data,
599 std::forward<Params>(params)...
600 ),
601 name
602 );
603 return *this;
604 }
605
606 template<typename Factory, typename TreePath>
607 OutputCollector& addVertexFunction(Factory factory, TreePath tp, std::string name)
608 {
609 typedef typename std::remove_reference<decltype(*factory.create(_data->_lfs.child(tp),_data))>::type DGF;
610 _vtk_writer.addVertexData(std::make_shared<VTKGridFunctionAdapter<DGF> >(factory.create(_data->_lfs.child(tp),_data),name));
611 return *this;
612 }
613
614 template<template<typename...> class Function, typename TreePath, typename... Params>
615 OutputCollector& addVertexFunction(TreePath tp, std::string name, Params&&... params)
616 {
617 using LFS = TypeTree::ChildForTreePath<typename Data::LFS,TreePath>;
618 typedef Function<LFS,Data,Params...> DGF;
619 _vtk_writer.addVertexData(
620 std::make_shared<VTKGridFunctionAdapter<DGF> >(
621 std::make_shared<DGF>(
622 TypeTree::child(_data->_lfs,tp)
623 ),
624 _data,
625 std::forward<Params>(params)...
626 ),
627 name
628 );
629 return *this;
630 }
631
632 OutputCollector(VTKWriter& vtk_writer, const std::shared_ptr<Data>& data, const Predicate& predicate = Predicate())
633 : _vtk_writer(vtk_writer)
634 , _data(data)
635 , _predicate(predicate)
636 {}
637
638 VTKWriter& _vtk_writer;
639 std::shared_ptr<Data> _data;
640 Predicate _predicate;
641
642 };
643
644 } // namespace vtk
645
646 template<typename VTKWriter,
647 typename GFS,
648 typename X,
649 typename NameGenerator = vtk::DefaultFunctionNameGenerator,
650 typename Predicate = vtk::DefaultPredicate>
651 vtk::OutputCollector<
652 VTKWriter,
653 vtk::DGFTreeCommonData<GFS,X,Predicate>
654 >
655 addSolutionToVTKWriter(VTKWriter& vtk_writer,
656 const GFS& gfs,
657 const X& x,
658 const NameGenerator& name_generator = vtk::defaultNameScheme(),
659 const Predicate& predicate = Predicate())
660 {
661 typedef vtk::DGFTreeCommonData<GFS,X,Predicate> Data;
662 auto data = std::make_shared<Data>(Dune::stackobject_to_shared_ptr(gfs), Dune::stackobject_to_shared_ptr(x));
663 vtk::OutputCollector<VTKWriter,Data> collector(vtk_writer, data, predicate);
664 collector.addSolution(name_generator);
665 return collector;
666 }
667
668
669 template<typename VTKWriter,
670 typename GFS,
671 typename X,
672 typename NameGenerator = vtk::DefaultFunctionNameGenerator,
673 typename Predicate = vtk::DefaultPredicate>
674 vtk::OutputCollector<
675 VTKWriter,
676 vtk::DGFTreeCommonData<GFS,X,Predicate>
677 >
678 addSolutionToVTKWriter(VTKWriter& vtk_writer,
679 std::shared_ptr<GFS> gfs,
680 std::shared_ptr<X> x,
681 const NameGenerator& name_generator = vtk::defaultNameScheme(),
682 const Predicate& predicate = Predicate())
683 {
684 typedef vtk::DGFTreeCommonData<GFS,X,Predicate> Data;
685 vtk::OutputCollector<VTKWriter,Data> collector(vtk_writer, std::make_shared<Data>(gfs,x),predicate);
686 collector.addSolution(name_generator);
687 return collector;
688 }
689
690 } // namespace PDELab
691} // namespace Dune
692
693#endif // DUNE_PDELAB_GRIDFUNCTIONSPACE_VTK_HH
vector space out of a tensor product of fields.
Definition: fvector.hh:95
IndexTypeImp IndexType
The type used for the indices.
Definition: indexidset.hh:92
leaf of a function tree
Definition: function.hh:302
T Traits
Export type traits.
Definition: function.hh:193
Output::DataSetType dataSetType() const
Return the data set type of this function.
Definition: function.hh:154
Helper class for common data of a DGFTree.
Definition: vtk.hh:77
A few common exception classes.
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
constexpr auto max
Function object that returns the greater of the given values.
Definition: hybridutilities.hh:484
std::size_t degree(const Node &node)
Returns the degree of node as run time information.
Definition: nodeinterface.hh:79
void applyToTree(Tree &&tree, Visitor &&visitor)
Apply visitor to TypeTree.
Definition: traversal.hh:239
ImplementationDefined child(Node &&node, Indices... indices)
Extracts the child of a node given by a sequence of compile-time and run-time indices.
Definition: childextraction.hh:128
Dune namespace.
Definition: alignedallocator.hh:13
std::shared_ptr< T > stackobject_to_shared_ptr(T &t)
Create a shared_ptr for a stack-allocated object.
Definition: shared_ptr.hh:72
This file implements several utilities related to std::shared_ptr.
Switch for uniform treatment of local and global basis classes.
Definition: interfaceswitch.hh:154
static const std::size_t dimRange
export dimension of the values
Definition: interfaceswitch.hh:165
Basis::Traits::RangeField RangeField
export field type of the values
Definition: interfaceswitch.hh:163
Basis::Traits::Range Range
export vector type of the values
Definition: interfaceswitch.hh:167
Switch for uniform treatment of finite element with either the local or the global interface.
Definition: interfaceswitch.hh:30
traits class holding the function signature, same as in local function
Definition: function.hh:183
void post(T &&, TreePath) const
Method for postfix tree traversal.
Definition: visitor.hh:83
void leaf(T &&, TreePath) const
Method for leaf traversal.
Definition: visitor.hh:93
Helper classes to provide indices for geometrytypes for use in a vector.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 15, 22:36, 2024)