1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2006 - 2020 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 
17 #ifndef dealii_mesh_worker_integration_info_h
18 #define dealii_mesh_worker_integration_info_h
19 
20 #include <deal.II/base/config.h>
21 
22 #include <deal.II/base/quadrature_lib.h>
23 
24 #include <deal.II/dofs/block_info.h>
25 
26 #include <deal.II/fe/fe_values.h>
27 
28 #include <deal.II/meshworker/dof_info.h>
29 #include <deal.II/meshworker/local_results.h>
30 #include <deal.II/meshworker/vector_selector.h>
31 
32 #include <memory>
33 
34 DEAL_II_NAMESPACE_OPEN
35 
36 namespace MeshWorker
37 {
38   /**
39    * Class for objects handed to local integration functions.
40    *
41    * Objects of this class contain one or more objects of type FEValues,
42    * FEFaceValues or FESubfaceValues to be used in local integration. They are
43    * stored in an array of pointers to the base classes FEValuesBase. The
44    * template parameter VectorType allows the use of different data types for
45    * the global system.
46    *
47    * Additionally, this function contains space to store the values of finite
48    * element functions stored in #global_data in the quadrature points. These
49    * vectors are initialized automatically on each cell or face. In order to
50    * avoid initializing unused vectors, you can use initialize_selector() to
51    * select the vectors by name that you actually want to use.
52    *
53    * <h3>Integration models</h3>
54    *
55    * This class supports two local integration models, corresponding to the
56    * data models in the documentation of the Assembler namespace. One is the
57    * standard model suggested by the use of FESystem. Namely, there is one
58    * FEValuesBase object in this class, containing all shape functions of the
59    * whole system, and having as many components as the system. Using this
60    * model involves loops over all system shape functions. It requires to
61    * identify the system components for each shape function and to select the
62    * correct bilinear form, usually in an @p if or @p switch statement.
63    *
64    * The second integration model builds one FEValuesBase object per base
65    * element of the system. The degrees of freedom on each cell are renumbered
66    * by block, such that they represent the same block structure as the global
67    * system. Objects performing the integration can then process each block
68    * separately, which improves reusability of code considerably.
69    *
70    * @note As described in DoFInfo, the use of the local block model is
71    * triggered by calling BlockInfo::initialize_local() before using
72    * initialize() in this class.
73    *
74    * @ingroup MeshWorker
75    */
76   template <int dim, int spacedim = dim>
77   class IntegrationInfo
78   {
79   private:
80     /// vector of FEValues objects
81     std::vector<std::shared_ptr<FEValuesBase<dim, spacedim>>> fevalv;
82 
83   public:
84     static const unsigned int dimension       = dim;
85     static const unsigned int space_dimension = spacedim;
86 
87     /**
88      * Constructor.
89      */
90     IntegrationInfo();
91 
92     /**
93      * Copy constructor, creating a clone to be used by WorkStream::run().
94      */
95     IntegrationInfo(const IntegrationInfo<dim, spacedim> &other);
96 
97     /**
98      * Build all internal structures, in particular the FEValuesBase objects
99      * and allocate space for data vectors.
100      *
101      * @param el is the finite element of the DoFHandler.
102      *
103      * @param mapping is the Mapping object used to map the mesh cells.
104      *
105      * @param quadrature is a Quadrature formula used in the constructor of
106      * the FEVALUES objects.
107      *
108      * @param flags are the UpdateFlags used in the constructor of the
109      * FEVALUES objects.
110      *
111      * @param local_block_info is an optional parameter for systems of PDE. If
112      * it is provided with reasonable data, then the degrees of freedom on the
113      * cells will be re-ordered to reflect the block structure of the system.
114      */
115     template <class FEVALUES>
116     void
117     initialize(const FiniteElement<dim, spacedim> &            el,
118                const Mapping<dim, spacedim> &                  mapping,
119                const Quadrature<FEVALUES::integral_dimension> &quadrature,
120                const UpdateFlags                               flags,
121                const BlockInfo *local_block_info = nullptr);
122 
123     /**
124      * Initialize the data vector and cache the selector.
125      */
126     void
127     initialize_data(const std::shared_ptr<VectorDataBase<dim, spacedim>> &data);
128 
129     /**
130      * Delete the data created by initialize().
131      */
132     void
133     clear();
134 
135     /**
136      * Return a reference to the FiniteElement that was used to initialize
137      * this object.
138      */
139     const FiniteElement<dim, spacedim> &
140     finite_element() const;
141 
142     /// This is true if we are assembling for multigrid
143     bool multigrid;
144     /// Access to finite element
145     /**
146      * This is the access function being used, if initialize() for a single
147      * element was used (without the BlockInfo argument). It throws an
148      * exception, if applied to a vector of elements.
149      */
150     const FEValuesBase<dim, spacedim> &
151     fe_values() const;
152 
153     /// Access to finite elements
154     /**
155      * This access function must be used if the initialize() for a group of
156      * elements was used (with a valid BlockInfo object).
157      */
158     const FEValuesBase<dim, spacedim> &
159     fe_values(const unsigned int i) const;
160 
161     /**
162      * The vector containing the values of finite element functions in the
163      * quadrature points.
164      *
165      * There is one vector per selected finite element function, containing
166      * one vector for each component, containing vectors with values for each
167      * quadrature point.
168      */
169     std::vector<std::vector<std::vector<double>>> values;
170 
171     /**
172      * The vector containing the derivatives of finite element functions in
173      * the quadrature points.
174      *
175      * There is one vector per selected finite element function, containing
176      * one vector for each component, containing vectors with values for each
177      * quadrature point.
178      */
179     std::vector<std::vector<std::vector<Tensor<1, spacedim>>>> gradients;
180 
181     /**
182      * The vector containing the second derivatives of finite element
183      * functions in the quadrature points.
184      *
185      * There is one vector per selected finite element function, containing
186      * one vector for each component, containing vectors with values for each
187      * quadrature point.
188      */
189     std::vector<std::vector<std::vector<Tensor<2, spacedim>>>> hessians;
190 
191     /**
192      * Reinitialize internal data structures for use on a cell.
193      */
194     template <typename number>
195     void
196     reinit(const DoFInfo<dim, spacedim, number> &i);
197 
198     /**
199      * Use the finite element functions in #global_data and fill the vectors
200      * #values, #gradients and #hessians.
201      */
202     template <typename number>
203     void
204     fill_local_data(const DoFInfo<dim, spacedim, number> &info,
205                     bool                                  split_fevalues);
206 
207     /**
208      * The global data vector used to compute function values in quadrature
209      * points.
210      */
211     std::shared_ptr<VectorDataBase<dim, spacedim>> global_data;
212 
213     /**
214      * The memory used by this object.
215      */
216     std::size_t
217     memory_consumption() const;
218 
219   private:
220     /**
221      * The pointer to the (system) element used for initialization.
222      */
223     SmartPointer<const FiniteElement<dim, spacedim>,
224                  IntegrationInfo<dim, spacedim>>
225       fe_pointer;
226 
227     /**
228      * Use the finite element functions in #global_data and fill the vectors
229      * #values, #gradients and #hessians with values according to the
230      * selector.
231      */
232     template <typename TYPE>
233     void
234     fill_local_data(std::vector<std::vector<std::vector<TYPE>>> &data,
235                     VectorSelector &                             selector,
236                     bool split_fevalues) const;
237     /**
238      * Cache the number of components of the system element.
239      */
240     unsigned int n_components;
241   };
242 
243   /**
244    * The object holding the scratch data for integrating over cells and faces.
245    * IntegrationInfoBox serves three main purposes:
246    *
247    * <ol>
248    * <li> It provides the interface needed by MeshWorker::loop(), namely the
249    * two functions post_cell() and post_faces(), as well as the data members
250    * #cell, #boundary, #face, #subface, and #neighbor.
251    *
252    * <li> It contains all information needed to initialize the FEValues and
253    * FEFaceValues objects in the IntegrationInfo data members.
254    *
255    * <li> It stores information on finite element vectors and whether their
256    * data should be used to compute values or derivatives of functions at
257    * quadrature points.
258    *
259    * <li> It makes educated guesses on quadrature rules and update flags, so
260    * that minimal code has to be written when default parameters are
261    * sufficient.
262    * </ol>
263    *
264    * In order to allow for sufficient generality, a few steps have to be
265    * undertaken to use this class.
266    *
267    * First, you should consider if you need values from any vectors in a
268    * AnyData object. If so, fill the VectorSelector objects #cell_selector,
269    * #boundary_selector and #face_selector with their names and the data type
270    * (value, gradient, Hessian) to be extracted.
271    *
272    * Afterwards, you will need to consider UpdateFlags for FEValues objects. A
273    * good start is initialize_update_flags(), which looks at the selectors
274    * filled before and adds all the flags needed to get the selection.
275    * Additional flags can be set with add_update_flags().
276    *
277    * Finally, we need to choose quadrature formulas. In the simplest case, you
278    * might be happy with the default settings, which are <i>n</i>-point Gauss
279    * formulas. If only derivatives of the shape functions are used
280    * (#update_values is not set) <i>n</i> equals the highest polynomial degree
281    * in the FiniteElement, if #update_values is set, <i>n</i> is one higher
282    * than this degree.  If you choose to use Gauss formulas of other size, use
283    * initialize_gauss_quadrature() with appropriate values. Otherwise, you can
284    * fill the variables #cell_quadrature, #boundary_quadrature and
285    * #face_quadrature directly.
286    *
287    * In order to save time, you can set the variables boundary_fluxes and
288    * interior_fluxes of the base class to false, thus telling the
289    * Meshworker::loop() not to loop over those faces.
290    *
291    * All the information in here is used to set up IntegrationInfo objects
292    * correctly, typically in an IntegrationInfoBox.
293    *
294    * @ingroup MeshWorker
295    */
296   template <int dim, int spacedim = dim>
297   class IntegrationInfoBox
298   {
299   public:
300     /**
301      * The type of the @p info object for cells.
302      */
303     using CellInfo = IntegrationInfo<dim, spacedim>;
304 
305     /**
306      * Default constructor.
307      */
308     IntegrationInfoBox();
309 
310     /**
311      * Initialize the IntegrationInfo objects contained.
312      *
313      * Before doing so, add update flags necessary to produce the data needed
314      * and also set uninitialized quadrature rules to Gauss formulas, which
315      * integrate polynomial bilinear forms exactly.
316      */
317     void
318     initialize(const FiniteElement<dim, spacedim> &el,
319                const Mapping<dim, spacedim> &      mapping,
320                const BlockInfo *                   block_info = nullptr);
321 
322     /**
323      * Initialize the IntegrationInfo objects contained.
324      *
325      * Before doing so, add update flags necessary to produce the data needed
326      * and also set uninitialized quadrature rules to Gauss formulas, which
327      * integrate polynomial bilinear forms exactly.
328      */
329     template <typename VectorType>
330     void
331     initialize(const FiniteElement<dim, spacedim> &el,
332                const Mapping<dim, spacedim> &      mapping,
333                const AnyData &                     data,
334                const VectorType &                  dummy,
335                const BlockInfo *                   block_info = nullptr);
336     /**
337      * Initialize the IntegrationInfo objects contained.
338      *
339      * Before doing so, add update flags necessary to produce the data needed
340      * and also set uninitialized quadrature rules to Gauss formulas, which
341      * integrate polynomial bilinear forms exactly.
342      */
343     template <typename VectorType>
344     void
345     initialize(const FiniteElement<dim, spacedim> &el,
346                const Mapping<dim, spacedim> &      mapping,
347                const AnyData &                     data,
348                const MGLevelObject<VectorType> &   dummy,
349                const BlockInfo *                   block_info = nullptr);
350     /**
351      * @name FEValues setup
352      */
353     /* @{ */
354 
355     /**
356      * Call this function before initialize() in order to guess the update
357      * flags needed, based on the data selected.
358      *
359      * When computing face fluxes, we normally can use the geometry
360      * (integration weights and normal vectors) from the original cell and
361      * thus can avoid updating these values on the neighboring cell. Set
362      * <tt>neighbor_geometry</tt> to true in order to initialize these values
363      * as well.
364      */
365     void
366     initialize_update_flags(bool neighbor_geometry = false);
367 
368     /**
369      * Add FEValues UpdateFlags for integration on all objects (cells,
370      * boundary faces and all interior faces).
371      */
372     void
373     add_update_flags_all(const UpdateFlags flags);
374 
375     /**
376      * Add FEValues UpdateFlags for integration on cells.
377      */
378     void
379     add_update_flags_cell(const UpdateFlags flags);
380 
381     /**
382      * Add FEValues UpdateFlags for integration on boundary faces.
383      */
384     void
385     add_update_flags_boundary(const UpdateFlags flags);
386 
387     /**
388      * Add FEValues UpdateFlags for integration on interior faces.
389      */
390     void
391     add_update_flags_face(const UpdateFlags flags);
392 
393     /**
394      * Add additional update flags to the ones already set in this program.
395      * The four boolean flags indicate whether the additional flags should be
396      * set for cell, boundary, interelement face for the cell itself or
397      * neighbor cell, or any combination thereof.
398      */
399     void
400     add_update_flags(const UpdateFlags flags,
401                      const bool        cell     = true,
402                      const bool        boundary = true,
403                      const bool        face     = true,
404                      const bool        neighbor = true);
405 
406     /**
407      * Assign n-point Gauss quadratures to each of the quadrature rules. Here,
408      * a size of zero points means that no loop over these grid entities
409      * should be performed.
410      *
411      * If the parameter <tt>force</tt> is true, then all quadrature sets are
412      * filled with new quadrature rules. If it is false, then only empty rules
413      * are changed.
414      */
415     void
416     initialize_gauss_quadrature(unsigned int n_cell_points,
417                                 unsigned int n_boundary_points,
418                                 unsigned int n_face_points,
419                                 const bool   force = true);
420 
421     /**
422      * The memory used by this object.
423      */
424     std::size_t
425     memory_consumption() const;
426 
427     /**
428      * The set of update flags for boundary cell integration.
429      *
430      * Defaults to #update_JxW_values.
431      */
432     UpdateFlags cell_flags;
433     /**
434      * The set of update flags for boundary face integration.
435      *
436      * Defaults to #update_JxW_values and #update_normal_vectors.
437      */
438     UpdateFlags boundary_flags;
439 
440     /**
441      * The set of update flags for interior face integration.
442      *
443      * Defaults to #update_JxW_values and #update_normal_vectors.
444      */
445     UpdateFlags face_flags;
446 
447     /**
448      * The set of update flags for interior face integration.
449      *
450      * Defaults to #update_default, since quadrature weights are taken from
451      * the other cell.
452      */
453     UpdateFlags neighbor_flags;
454 
455     /**
456      * The quadrature rule used on cells.
457      */
458     Quadrature<dim> cell_quadrature;
459 
460     /**
461      * The quadrature rule used on boundary faces.
462      */
463     Quadrature<dim - 1> boundary_quadrature;
464 
465     /**
466      * The quadrature rule used on interior faces.
467      */
468     Quadrature<dim - 1> face_quadrature;
469     /* @} */
470 
471     /**
472      * @name Data vectors
473      */
474     /* @{ */
475 
476     /**
477      * Initialize the VectorSelector objects #cell_selector,
478      * #boundary_selector and #face_selector in order to save computational
479      * effort. If no selectors are used, then values for all named vectors in
480      * DoFInfo::global_data will be computed in all quadrature points.
481      *
482      * This function will also add UpdateFlags to the flags stored in this
483      * class.
484      */
485     /**
486      * Select the vectors from DoFInfo::global_data that should be computed in
487      * the quadrature points on cells.
488      */
489     MeshWorker::VectorSelector cell_selector;
490 
491     /**
492      * Select the vectors from DoFInfo::global_data that should be computed in
493      * the quadrature points on boundary faces.
494      */
495     MeshWorker::VectorSelector boundary_selector;
496 
497     /**
498      * Select the vectors from DoFInfo::global_data that should be computed in
499      * the quadrature points on interior faces.
500      */
501     MeshWorker::VectorSelector face_selector;
502 
503     std::shared_ptr<MeshWorker::VectorDataBase<dim, spacedim>> cell_data;
504     std::shared_ptr<MeshWorker::VectorDataBase<dim, spacedim>> boundary_data;
505     std::shared_ptr<MeshWorker::VectorDataBase<dim, spacedim>> face_data;
506     /* @} */
507 
508     /**
509      * @name Interface for MeshWorker::loop()
510      */
511     /* @{ */
512     /**
513      * A callback function which is called in the loop over all cells, after
514      * the action on a cell has been performed and before the faces are dealt
515      * with.
516      *
517      * In order for this function to have this effect, at least either of the
518      * arguments <tt>boundary_worker</tt> or <tt>face_worker</tt> arguments of
519      * loop() should be nonzero. Additionally, <tt>cells_first</tt> should be
520      * true. If <tt>cells_first</tt> is false, this function is called before
521      * any action on a cell is taken.
522      *
523      * And empty function in this class, but can be replaced in other classes
524      * given to loop() instead.
525      *
526      * See loop() and cell_action() for more details of how this function can
527      * be used.
528      */
529     template <class DOFINFO>
530     void
531     post_cell(const DoFInfoBox<dim, DOFINFO> &);
532 
533     /**
534      * A callback function which is called in the loop over all cells, after
535      * the action on the faces of a cell has been performed and before the
536      * cell itself is dealt with (assumes <tt>cells_first</tt> is false).
537      *
538      * In order for this function to have a reasonable effect, at least either
539      * of the arguments <tt>boundary_worker</tt> or <tt>face_worker</tt>
540      * arguments of loop() should be nonzero. Additionally,
541      * <tt>cells_first</tt> should be false.
542      *
543      * And empty function in this class, but can be replaced in other classes
544      * given to loop() instead.
545      *
546      * See loop() and cell_action() for more details of how this function can
547      * be used.
548      */
549     template <class DOFINFO>
550     void
551     post_faces(const DoFInfoBox<dim, DOFINFO> &);
552 
553     /**
554      * The @p info object for a cell.
555      */
556     CellInfo cell;
557     /**
558      * The @p info object for a boundary face.
559      */
560     CellInfo boundary;
561     /**
562      * The @p info object for a regular interior face, seen from the first cell.
563      */
564     CellInfo face;
565     /**
566      * The @p info object for the refined side of an interior face seen from the
567      * first cell.
568      */
569     CellInfo subface;
570     /**
571      * The @p info object for an interior face, seen from the other cell.
572      */
573     CellInfo neighbor;
574 
575     /* @} */
576   };
577 
578 
579   //----------------------------------------------------------------------//
580 
581   template <int dim, int sdim>
IntegrationInfo()582   inline IntegrationInfo<dim, sdim>::IntegrationInfo()
583     : fevalv(0)
584     , multigrid(false)
585     , global_data(std::make_shared<VectorDataBase<dim, sdim>>())
586     , n_components(numbers::invalid_unsigned_int)
587   {}
588 
589 
590   template <int dim, int sdim>
IntegrationInfo(const IntegrationInfo<dim,sdim> & other)591   inline IntegrationInfo<dim, sdim>::IntegrationInfo(
592     const IntegrationInfo<dim, sdim> &other)
593     : multigrid(other.multigrid)
594     , values(other.values)
595     , gradients(other.gradients)
596     , hessians(other.hessians)
597     , global_data(other.global_data)
598     , fe_pointer(other.fe_pointer)
599     , n_components(other.n_components)
600   {
601     fevalv.resize(other.fevalv.size());
602     for (unsigned int i = 0; i < other.fevalv.size(); ++i)
603       {
604         const FEValuesBase<dim, sdim> &p = *other.fevalv[i];
605         const FEValues<dim, sdim> *    pc =
606           dynamic_cast<const FEValues<dim, sdim> *>(&p);
607         const FEFaceValues<dim, sdim> *pf =
608           dynamic_cast<const FEFaceValues<dim, sdim> *>(&p);
609         const FESubfaceValues<dim, sdim> *ps =
610           dynamic_cast<const FESubfaceValues<dim, sdim> *>(&p);
611 
612         if (pc != nullptr)
613           fevalv[i] =
614             std::make_shared<FEValues<dim, sdim>>(pc->get_mapping(),
615                                                   pc->get_fe(),
616                                                   pc->get_quadrature(),
617                                                   pc->get_update_flags());
618         else if (pf != nullptr)
619           fevalv[i] =
620             std::make_shared<FEFaceValues<dim, sdim>>(pf->get_mapping(),
621                                                       pf->get_fe(),
622                                                       pf->get_quadrature(),
623                                                       pf->get_update_flags());
624         else if (ps != nullptr)
625           fevalv[i] = std::make_shared<FESubfaceValues<dim, sdim>>(
626             ps->get_mapping(),
627             ps->get_fe(),
628             ps->get_quadrature(),
629             ps->get_update_flags());
630         else
631           Assert(false, ExcInternalError());
632       }
633   }
634 
635 
636 
637   template <int dim, int sdim>
638   template <class FEVALUES>
639   inline void
initialize(const FiniteElement<dim,sdim> & el,const Mapping<dim,sdim> & mapping,const Quadrature<FEVALUES::integral_dimension> & quadrature,const UpdateFlags flags,const BlockInfo * block_info)640   IntegrationInfo<dim, sdim>::initialize(
641     const FiniteElement<dim, sdim> &                el,
642     const Mapping<dim, sdim> &                      mapping,
643     const Quadrature<FEVALUES::integral_dimension> &quadrature,
644     const UpdateFlags                               flags,
645     const BlockInfo *                               block_info)
646   {
647     fe_pointer = &el;
648     if (block_info == nullptr || block_info->local().size() == 0)
649       {
650         fevalv.resize(1);
651         fevalv[0] = std::make_shared<FEVALUES>(mapping, el, quadrature, flags);
652       }
653     else
654       {
655         fevalv.resize(el.n_base_elements());
656         for (unsigned int i = 0; i < fevalv.size(); ++i)
657           fevalv[i] = std::make_shared<FEVALUES>(mapping,
658                                                  el.base_element(i),
659                                                  quadrature,
660                                                  flags);
661       }
662     n_components = el.n_components();
663   }
664 
665 
666   template <int dim, int spacedim>
667   inline const FiniteElement<dim, spacedim> &
finite_element()668   IntegrationInfo<dim, spacedim>::finite_element() const
669   {
670     Assert(fe_pointer != nullptr, ExcNotInitialized());
671     return *fe_pointer;
672   }
673 
674   template <int dim, int spacedim>
675   inline const FEValuesBase<dim, spacedim> &
fe_values()676   IntegrationInfo<dim, spacedim>::fe_values() const
677   {
678     AssertDimension(fevalv.size(), 1);
679     return *fevalv[0];
680   }
681 
682 
683   template <int dim, int spacedim>
684   inline const FEValuesBase<dim, spacedim> &
fe_values(unsigned int i)685   IntegrationInfo<dim, spacedim>::fe_values(unsigned int i) const
686   {
687     AssertIndexRange(i, fevalv.size());
688     return *fevalv[i];
689   }
690 
691 
692   template <int dim, int spacedim>
693   template <typename number>
694   inline void
reinit(const DoFInfo<dim,spacedim,number> & info)695   IntegrationInfo<dim, spacedim>::reinit(
696     const DoFInfo<dim, spacedim, number> &info)
697   {
698     for (unsigned int i = 0; i < fevalv.size(); ++i)
699       {
700         FEValuesBase<dim, spacedim> &febase = *fevalv[i];
701         if (info.sub_number != numbers::invalid_unsigned_int)
702           {
703             // This is a subface
704             FESubfaceValues<dim, spacedim> &fe =
705               dynamic_cast<FESubfaceValues<dim, spacedim> &>(febase);
706             fe.reinit(info.cell, info.face_number, info.sub_number);
707           }
708         else if (info.face_number != numbers::invalid_unsigned_int)
709           {
710             // This is a face
711             FEFaceValues<dim, spacedim> &fe =
712               dynamic_cast<FEFaceValues<dim, spacedim> &>(febase);
713             fe.reinit(info.cell, info.face_number);
714           }
715         else
716           {
717             // This is a cell
718             FEValues<dim, spacedim> &fe =
719               dynamic_cast<FEValues<dim, spacedim> &>(febase);
720             fe.reinit(info.cell);
721           }
722       }
723 
724     const bool split_fevalues = info.block_info != nullptr;
725     if (!global_data->empty())
726       fill_local_data(info, split_fevalues);
727   }
728 
729 
730 
731   //----------------------------------------------------------------------//
732 
733   template <int dim, int sdim>
734   inline void
initialize_gauss_quadrature(unsigned int cp,unsigned int bp,unsigned int fp,bool force)735   IntegrationInfoBox<dim, sdim>::initialize_gauss_quadrature(unsigned int cp,
736                                                              unsigned int bp,
737                                                              unsigned int fp,
738                                                              bool         force)
739   {
740     if (force || cell_quadrature.size() == 0)
741       cell_quadrature = QGauss<dim>(cp);
742     if (force || boundary_quadrature.size() == 0)
743       boundary_quadrature = QGauss<dim - 1>(bp);
744     if (force || face_quadrature.size() == 0)
745       face_quadrature = QGauss<dim - 1>(fp);
746   }
747 
748 
749   template <int dim, int sdim>
750   inline void
add_update_flags_all(const UpdateFlags flags)751   IntegrationInfoBox<dim, sdim>::add_update_flags_all(const UpdateFlags flags)
752   {
753     add_update_flags(flags, true, true, true, true);
754   }
755 
756 
757   template <int dim, int sdim>
758   inline void
add_update_flags_cell(const UpdateFlags flags)759   IntegrationInfoBox<dim, sdim>::add_update_flags_cell(const UpdateFlags flags)
760   {
761     add_update_flags(flags, true, false, false, false);
762   }
763 
764 
765   template <int dim, int sdim>
766   inline void
add_update_flags_boundary(const UpdateFlags flags)767   IntegrationInfoBox<dim, sdim>::add_update_flags_boundary(
768     const UpdateFlags flags)
769   {
770     add_update_flags(flags, false, true, false, false);
771   }
772 
773 
774   template <int dim, int sdim>
775   inline void
add_update_flags_face(const UpdateFlags flags)776   IntegrationInfoBox<dim, sdim>::add_update_flags_face(const UpdateFlags flags)
777   {
778     add_update_flags(flags, false, false, true, true);
779   }
780 
781 
782   template <int dim, int sdim>
783   inline void
initialize(const FiniteElement<dim,sdim> & el,const Mapping<dim,sdim> & mapping,const BlockInfo * block_info)784   IntegrationInfoBox<dim, sdim>::initialize(const FiniteElement<dim, sdim> &el,
785                                             const Mapping<dim, sdim> &mapping,
786                                             const BlockInfo *block_info)
787   {
788     initialize_update_flags();
789     initialize_gauss_quadrature((cell_flags & update_values) ?
790                                   (el.tensor_degree() + 1) :
791                                   el.tensor_degree(),
792                                 (boundary_flags & update_values) ?
793                                   (el.tensor_degree() + 1) :
794                                   el.tensor_degree(),
795                                 (face_flags & update_values) ?
796                                   (el.tensor_degree() + 1) :
797                                   el.tensor_degree(),
798                                 false);
799 
800     cell.template initialize<FEValues<dim, sdim>>(
801       el, mapping, cell_quadrature, cell_flags, block_info);
802     boundary.template initialize<FEFaceValues<dim, sdim>>(
803       el, mapping, boundary_quadrature, boundary_flags, block_info);
804     face.template initialize<FEFaceValues<dim, sdim>>(
805       el, mapping, face_quadrature, face_flags, block_info);
806     subface.template initialize<FESubfaceValues<dim, sdim>>(
807       el, mapping, face_quadrature, face_flags, block_info);
808     neighbor.template initialize<FEFaceValues<dim, sdim>>(
809       el, mapping, face_quadrature, neighbor_flags, block_info);
810   }
811 
812 
813   template <int dim, int sdim>
814   template <typename VectorType>
815   void
initialize(const FiniteElement<dim,sdim> & el,const Mapping<dim,sdim> & mapping,const AnyData & data,const VectorType &,const BlockInfo * block_info)816   IntegrationInfoBox<dim, sdim>::initialize(const FiniteElement<dim, sdim> &el,
817                                             const Mapping<dim, sdim> &mapping,
818                                             const AnyData &           data,
819                                             const VectorType &,
820                                             const BlockInfo *block_info)
821   {
822     initialize(el, mapping, block_info);
823     std::shared_ptr<VectorData<VectorType, dim, sdim>> p;
824     VectorDataBase<dim, sdim> *                        pp;
825 
826     p = std::make_shared<VectorData<VectorType, dim, sdim>>(cell_selector);
827     // Public member function of parent class was not found without
828     // explicit cast
829     pp = &*p;
830     pp->initialize(data);
831     cell_data = p;
832     cell.initialize_data(p);
833 
834     p  = std::make_shared<VectorData<VectorType, dim, sdim>>(boundary_selector);
835     pp = &*p;
836     pp->initialize(data);
837     boundary_data = p;
838     boundary.initialize_data(p);
839 
840     p  = std::make_shared<VectorData<VectorType, dim, sdim>>(face_selector);
841     pp = &*p;
842     pp->initialize(data);
843     face_data = p;
844     face.initialize_data(p);
845     subface.initialize_data(p);
846     neighbor.initialize_data(p);
847   }
848 
849   template <int dim, int sdim>
850   template <typename VectorType>
851   void
initialize(const FiniteElement<dim,sdim> & el,const Mapping<dim,sdim> & mapping,const AnyData & data,const MGLevelObject<VectorType> &,const BlockInfo * block_info)852   IntegrationInfoBox<dim, sdim>::initialize(const FiniteElement<dim, sdim> &el,
853                                             const Mapping<dim, sdim> &mapping,
854                                             const AnyData &           data,
855                                             const MGLevelObject<VectorType> &,
856                                             const BlockInfo *block_info)
857   {
858     initialize(el, mapping, block_info);
859     std::shared_ptr<MGVectorData<VectorType, dim, sdim>> p;
860     VectorDataBase<dim, sdim> *                          pp;
861 
862     p = std::make_shared<MGVectorData<VectorType, dim, sdim>>(cell_selector);
863     // Public member function of parent class was not found without
864     // explicit cast
865     pp = &*p;
866     pp->initialize(data);
867     cell_data = p;
868     cell.initialize_data(p);
869 
870     p =
871       std::make_shared<MGVectorData<VectorType, dim, sdim>>(boundary_selector);
872     pp = &*p;
873     pp->initialize(data);
874     boundary_data = p;
875     boundary.initialize_data(p);
876 
877     p  = std::make_shared<MGVectorData<VectorType, dim, sdim>>(face_selector);
878     pp = &*p;
879     pp->initialize(data);
880     face_data = p;
881     face.initialize_data(p);
882     subface.initialize_data(p);
883     neighbor.initialize_data(p);
884   }
885 
886   template <int dim, int sdim>
887   template <class DOFINFO>
888   void
post_cell(const DoFInfoBox<dim,DOFINFO> &)889   IntegrationInfoBox<dim, sdim>::post_cell(const DoFInfoBox<dim, DOFINFO> &)
890   {}
891 
892 
893   template <int dim, int sdim>
894   template <class DOFINFO>
895   void
post_faces(const DoFInfoBox<dim,DOFINFO> &)896   IntegrationInfoBox<dim, sdim>::post_faces(const DoFInfoBox<dim, DOFINFO> &)
897   {}
898 
899 
900 } // namespace MeshWorker
901 
902 DEAL_II_NAMESPACE_CLOSE
903 
904 #endif
905