1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 
4 #ifndef DUNE_GRID_IO_FILE_VTK_FUNCTION_HH
5 #define DUNE_GRID_IO_FILE_VTK_FUNCTION_HH
6 
7 #include <string>
8 
9 #include <dune/common/exceptions.hh>
10 #include <dune/common/fvector.hh>
11 
12 #include <dune/geometry/type.hh>
13 #include <dune/geometry/referenceelements.hh>
14 #include <dune/geometry/multilineargeometry.hh>
15 
16 #include <dune/grid/common/mcmgmapper.hh>
17 #include <dune/grid/io/file/vtk/common.hh>
18 
19 /** @file
20     @author Peter Bastian, Christian Engwer
21     @brief Functions for VTK output
22  */
23 
24 namespace Dune
25 {
26   //! \addtogroup VTK
27   //! \{
28 
29   //////////////////////////////////////////////////////////////////////
30   //
31   //  Base VTKFunction
32   //
33 
34   /** \brief A base class for grid functions with any return type and dimension
35 
36       Trick : use double as return type
37    */
38   template< class GridView >
39   class VTKFunction
40   {
41   public:
42     typedef typename GridView::ctype ctype;
43     enum { dim = GridView::dimension };
44     typedef typename GridView::template Codim< 0 >::Entity Entity;
45 
46     //! return number of components (1 for scalar valued functions, 3 for
47     //! vector valued function in 3D etc.)
48     virtual int ncomps () const = 0;
49 
50     //! evaluate single component comp in the entity e at local coordinates xi
51     /*! Evaluate the function in an entity at local coordinates.
52        @param[in]  comp   number of component to be evaluated
53        @param[in]  e      reference to grid entity of codimension 0
54        @param[in]  xi     point in local coordinates of the reference element
55                          of e
56        \return            value of the component
57      */
58     virtual double evaluate (int comp, const Entity& e,
59                              const Dune::FieldVector<ctype,dim>& xi) const = 0;
60 
61     //! get name
62     virtual std::string name () const = 0;
63 
64     //! get output precision for the field
precision() const65     virtual VTK::Precision precision() const
66     { return VTK::Precision::float32; }
67 
68     //! virtual destructor
~VTKFunction()69     virtual ~VTKFunction () {}
70   };
71 
72   //////////////////////////////////////////////////////////////////////
73   //
74   //  P0VTKFunction
75   //
76 
77   //! Take a vector and interpret it as cell data for the VTKWriter
78   /**
79    * This class turns a generic vector containing cell data into a
80    * VTKFunction.  The vector must allow read access to the data via
81    * operator[]() and store the data in the order given by
82    * MultipleCodimMultipleGeomTypeMapper with a layout class that allows only
83    * elements.  Also, it must support the method size().
84    *
85    * While the number of components of the function is always 1, the vector
86    * may represent a field with multiple components of which one may be
87    * selected.
88    *
89    * \tparam GV Type of GridView the vector applies to.
90    * \tparam V  Type of vector.
91    */
92   template<typename GV, typename V>
93   class P0VTKFunction
94     : public VTKFunction< GV >
95   {
96     //! Base class
97     typedef VTKFunction< GV > Base;
98     //! Mapper for elements
99     typedef MultipleCodimMultipleGeomTypeMapper<GV> Mapper;
100 
101     //! store a reference to the vector
102     const V& v;
103     //! name of this function
104     std::string s;
105     //! number of components of the field stored in the vector
106     int ncomps_;
107     //! index of the component of the field in the vector this function is
108     //! responsible for
109     int mycomp_;
110     //! precision with which to output the field
111     VTK::Precision prec_;
112     //! mapper used to map elements to indices
113     Mapper mapper;
114 
115   public:
116     typedef typename Base::Entity Entity;
117     typedef typename Base::ctype ctype;
118     using Base::dim;
119 
120     //! return number of components
ncomps() const121     int ncomps () const override
122     {
123       return 1;
124     }
125 
126     //! evaluate
evaluate(int,const Entity & e,const Dune::FieldVector<ctype,dim> &) const127     double evaluate (int, const Entity& e,
128                      const Dune::FieldVector<ctype,dim>&) const override
129     {
130       return v[mapper.index(e)*ncomps_+mycomp_];
131     }
132 
133     //! get name
name() const134     std::string name () const override
135     {
136       return s;
137     }
138 
139     //! get output precision for the field
precision() const140     VTK::Precision precision() const override
141     {
142       return prec_;
143     }
144 
145     //! construct from a vector and a name
146     /**
147      * \param gv     GridView to operate on (used to instantiate a
148      *               MultipleCodimMultipleGeomeTypeMapper, otherwise no
149      *               reference or copy is stored).  Note that this must be the
150      *               GridView the vector applies to as well as the GridView
151      *               later used by the VTKWriter -- i.e. we do not implicitly
152      *               restrict or prolongate the data.
153      * \param v_     Reference to the vector holding the data.  The reference
154      *               is stored internally and must be valid for as long as
155      *               this functions evaluate method is used.
156      * \param s_     Name of this function in the VTK file.
157      * \param ncomps Number of components of the field represented by the
158      *               vector.
159      * \param mycomp Number of the field component this function is
160      *               responsible for.
161      * \param prec   the precision with which to output the field
162      */
P0VTKFunction(const GV & gv,const V & v_,const std::string & s_,int ncomps=1,int mycomp=0,VTK::Precision prec=VTK::Precision::float32)163     P0VTKFunction(const GV &gv, const V &v_, const std::string &s_,
164                   int ncomps=1, int mycomp=0, VTK::Precision prec = VTK::Precision::float32)
165       : v( v_ ),
166         s( s_ ),
167         ncomps_(ncomps),
168         mycomp_(mycomp),
169         prec_(prec),
170         mapper( gv, mcmgElementLayout() )
171     {
172       if (v.size()!=(unsigned int)(mapper.size()*ncomps_))
173         DUNE_THROW(IOError, "P0VTKFunction: size mismatch");
174     }
175 
176     //! destructor
~P0VTKFunction()177     virtual ~P0VTKFunction() {}
178   };
179 
180   //////////////////////////////////////////////////////////////////////
181   //
182   //  P1VTKFunction
183   //
184 
185   //! Take a vector and interpret it as point data for the VTKWriter
186   /**
187    * This class turns a generic vector containing point data into a
188    * VTKFunction.  The vector must allow read access to the data via
189    * operator[]() and store the data in the order given by
190    * MultipleCodimMultipleGeomTypeMapper with a layout class that allows only
191    * vertices.  Also, it must support the method size().
192    *
193    * While the number of components of the function is always 1, the vector
194    * may represent a field with multiple components of which one may be
195    * selected.
196    *
197    * \tparam GV Type of GridView the vector applies to.
198    * \tparam V  Type of vector.
199    */
200   template<typename GV, typename V>
201   class P1VTKFunction
202     : public VTKFunction< GV >
203   {
204     //! Base class
205     typedef VTKFunction< GV > Base;
206     //! Mapper for vertices
207     typedef MultipleCodimMultipleGeomTypeMapper<GV> Mapper;
208 
209     //! store a reference to the vector
210     const V& v;
211     //! name of this function
212     std::string s;
213     //! number of components of the field stored in the vector
214     int ncomps_;
215     //! index of the component of the field in the vector this function is
216     //! responsible for
217     int mycomp_;
218     //! precision with which to output the field
219     VTK::Precision prec_;
220     //! mapper used to map elements to indices
221     Mapper mapper;
222 
223   public:
224     typedef typename Base::Entity Entity;
225     typedef typename Base::ctype ctype;
226     using Base::dim;
227 
228     //! return number of components
ncomps() const229     int ncomps () const override
230     {
231       return 1;
232     }
233 
234     //! evaluate
evaluate(int comp,const Entity & e,const Dune::FieldVector<ctype,dim> & xi) const235     double evaluate ([[maybe_unused]] int comp, const Entity& e,
236                      const Dune::FieldVector<ctype,dim>& xi) const override
237     {
238       const unsigned int myDim = Entity::mydimension;
239       const unsigned int nVertices = e.subEntities(dim);
240 
241       std::vector<FieldVector<ctype,1> > cornerValues(nVertices);
242       for (unsigned i=0; i<nVertices; ++i)
243         cornerValues[i] = v[mapper.subIndex(e,i,myDim)*ncomps_+mycomp_];
244 
245       // (Ab)use the MultiLinearGeometry class to do multi-linear interpolation between scalars
246       const MultiLinearGeometry<ctype,dim,1> interpolation(e.type(), cornerValues);
247       return interpolation.global(xi);
248     }
249 
250     //! get name
name() const251     std::string name () const override
252     {
253       return s;
254     }
255 
256     //! get output precision for the field
precision() const257     VTK::Precision precision() const override
258     {
259       return prec_;
260     }
261 
262     //! construct from a vector and a name
263     /**
264      * \param gv     GridView to operate on (used to instantiate a
265      *               MultipleCodimMultipleGeomTypeMapper, otherwise no
266      *               reference or copy is stored).  Note that this must be the
267      *               GridView the vector applies to as well as the GridView
268      *               later used by the VTKWriter -- i.e. we do not implicitly
269      *               restrict or prolongate the data.
270      * \param v_     Reference to the vector holding the data.  The reference
271      *               is stored internally and must be valid for as long as
272      *               this functions evaluate method is used.
273      * \param s_     Name of this function in the VTK file.
274      * \param ncomps Number of components of the field represented by the
275      *               vector.
276      * \param mycomp Number of the field component this function is
277      *               responsible for.
278      * \param prec   the precision with which to output the field
279      */
P1VTKFunction(const GV & gv,const V & v_,const std::string & s_,int ncomps=1,int mycomp=0,VTK::Precision prec=VTK::Precision::float32)280     P1VTKFunction(const GV& gv, const V &v_, const std::string &s_,
281                   int ncomps=1, int mycomp=0, VTK::Precision prec = VTK::Precision::float32)
282       : v( v_ ),
283         s( s_ ),
284         ncomps_(ncomps),
285         mycomp_(mycomp),
286         prec_(prec),
287         mapper( gv, mcmgVertexLayout() )
288     {
289       if (v.size()!=(unsigned int)(mapper.size()*ncomps_))
290         DUNE_THROW(IOError,"P1VTKFunction: size mismatch");
291     }
292 
293     //! destructor
~P1VTKFunction()294     virtual ~P1VTKFunction() {}
295   };
296 
297   //! \} group VTK
298 
299 } // namespace Dune
300 
301 #endif // DUNE_GRID_IO_FILE_VTK_FUNCTION_HH
302