};
/**
- * @name Auxiliary functions
+ * @name Functions to support code that generically uses both DoFHandler and hp::DoFHandler
* @{
*/
/**
*/
/**
- * @name Sparsity Pattern Generation
+ * @name Sparsity pattern generation
* @{
*/
const Table<2,Coupling> &int_mask,
const Table<2,Coupling> &flux_mask);
- //@}
/**
- * @name Hanging Nodes
+ * @}
+ */
+ /**
+ * @name Hanging nodes and other constraints
* @{
*/
void
make_hanging_node_constraints (const DH &dof_handler,
ConstraintMatrix &constraints);
+
+ /**
+ * This function can be used when different variables shall be
+ * discretized on different grids, where one grid is coarser than
+ * the other. This idea might seem nonsensical at first, but has
+ * reasonable applications in inverse (parameter estimation)
+ * problems, where there might not be enough information to recover
+ * the parameter on the same grid as the state variable;
+ * furthermore, the smoothness properties of state variable and
+ * parameter might not be too much related, so using different grids
+ * might be an alternative to using stronger regularization of the
+ * problem.
+ *
+ * The basic idea of this function is explained in the
+ * following. Let us, for convenience, denote by ``parameter grid''
+ * the coarser of the two grids, and by ``state grid'' the finer of
+ * the two. We furthermore assume that the finer grid can be
+ * obtained by refinement of the coarser one, i.e. the fine grid is
+ * at least as much refined as the coarse grid at each point of the
+ * domain. Then, each shape function on the coarse grid can be
+ * represented as a linear combination of shape functions on the
+ * fine grid (assuming identical ansatz spaces). Thus, if we
+ * discretize as usual, using shape functions on the fine grid, we
+ * can consider the restriction that the parameter variable shall in
+ * fact be discretized by shape functions on the coarse grid as a
+ * constraint. These constraints are linear and happen to have the
+ * form managed by the ``ConstraintMatrix'' class.
+ *
+ * The construction of these constraints is done as follows: for
+ * each of the degrees of freedom (i.e. shape functions) on the
+ * coarse grid, we compute its representation on the fine grid,
+ * i.e. how the linear combination of shape functions on the fine
+ * grid looks like that resembles the shape function on the coarse
+ * grid. From this information, we can then compute the constraints
+ * which have to hold if a solution of a linear equation on the fine
+ * grid shall be representable on the coarse grid. The exact
+ * algorithm how these constraints can be computed is rather
+ * complicated and is best understood by reading the source code,
+ * which contains many comments.
+ *
+ * Before explaining the use of this function, we would like to
+ * state that the total number of degrees of freedom used for the
+ * discretization is not reduced by the use of this function,
+ * i.e. even though we discretize one variable on a coarser grid,
+ * the total number of degrees of freedom is that of the fine
+ * grid. This seems to be counter-productive, since it does not give
+ * us a benefit from using a coarser grid. The reason why it may be
+ * useful to choose this approach nonetheless is three-fold: first,
+ * as stated above, there might not be enough information to recover
+ * a parameter on a fine grid, i.e. we chose to discretize it on the
+ * coarse grid not to save DoFs, but for other reasons. Second, the
+ * ``ConstraintMatrix'' includes the constraints into the linear
+ * system of equations, by which constrained nodes become dummy
+ * nodes; we may therefore exclude them from the linear algebra, for
+ * example by sorting them to the back of the DoF numbers and simply
+ * calling the solver for the upper left block of the matrix which
+ * works on the non-constrained nodes only, thus actually realizing
+ * the savings in numerical effort from the reduced number of actual
+ * degrees of freedom. The third reason is that for some or other
+ * reason we have chosen to use two different grids, it may be
+ * actually quite difficult to write a function that assembles the
+ * system matrix for finite element spaces on different grids; using
+ * the approach of constraints as with this function allows to use
+ * standard techniques when discretizing on only one grid (the finer
+ * one) without having to take care of the fact that one or several
+ * of the variable actually belong to different grids.
+ *
+ * The use of this function is as follows: it accepts as parameters
+ * two DoF Handlers, the first of which refers to the coarse grid
+ * and the second of which is the fine grid. On both, a finite
+ * element is represented by the DoF handler objects, which will
+ * usually have several components, which may belong to different
+ * finite elements. The second and fourth parameter of this function
+ * therefore state which variable on the coarse grid shall be used
+ * to restrict the stated component on the fine grid. Of course, the
+ * finite elements used for the respective components on the two
+ * grids need to be the same. An example may clarify this: consider
+ * the parameter estimation mentioned briefly above; there, on the
+ * fine grid the whole discretization is done, thus the variables
+ * are ``u'', ``q'', and the Lagrange multiplier ``lambda'', which
+ * are discretized using continuous linear, piecewise constant
+ * discontinuous, and continuous linear elements, respectively. Only
+ * the parameter ``q'' shall be represented on the coarse grid, thus
+ * the DoFHandler object on the coarse grid represents only one
+ * variable, discretized using piecewise constant discontinuous
+ * elements. Then, the parameter denoting the component on the
+ * coarse grid would be zero (the only possible choice, since the
+ * variable on the coarse grid is scalar), and one on the fine grid
+ * (corresponding to the variable ``q''; zero would be ``u'', two
+ * would be ``lambda''). Furthermore, an object of type IntergridMap
+ * is needed; this could in principle be generated by the function
+ * itself from the two DoFHandler objects, but since it is probably
+ * available anyway in programs that use this function, we shall use
+ * it instead of re-generating it. Finally, the computed constraints
+ * are entered into a variable of type ConstraintMatrix; the
+ * constraints are added, i.e. previous contents which may have, for
+ * example, be obtained from hanging nodes, are not deleted, so that
+ * you only need one object of this type.
+ */
+ template <int dim, int spacedim>
+ void
+ compute_intergrid_constraints (const DoFHandler<dim,spacedim> &coarse_grid,
+ const unsigned int coarse_component,
+ const DoFHandler<dim,spacedim> &fine_grid,
+ const unsigned int fine_component,
+ const InterGridMap<DoFHandler<dim,spacedim> > &coarse_to_fine_grid_map,
+ ConstraintMatrix &constraints);
+
+
+ /**
+ * This function generates a matrix such that when a vector of data
+ * with as many elements as there are degrees of freedom of this
+ * component on the coarse grid is multiplied to this matrix, we
+ * obtain a vector with as many elements as there are global
+ * degrees of freedom on the fine grid. All the elements of the
+ * other components of the finite element fields on the fine grid
+ * are not touched.
+ *
+ * The output of this function is a compressed format that can be
+ * given to the @p reinit functions of the SparsityPattern ad
+ * SparseMatrix classes.
+ */
+ template <int dim, int spacedim>
+ void
+ compute_intergrid_transfer_representation (const DoFHandler<dim,spacedim> &coarse_grid,
+ const unsigned int coarse_component,
+ const DoFHandler<dim,spacedim> &fine_grid,
+ const unsigned int fine_component,
+ const InterGridMap<DoFHandler<dim,spacedim> > &coarse_to_fine_grid_map,
+ std::vector<std::map<types::global_dof_index, float> > &transfer_representation);
+
//@}
/**
- * @name Periodic Boundary Conditions
+ * @name Periodic boundary conditions
* @{
*/
Vector<double> &dof_data,
const unsigned int component = 0);
+ /**
+ * @}
+ */
+ /**
+ * @name Identifying subsets of degrees of freedom with particular properties
+ * @{
+ */
+
/**
* Extract the indices of the degrees of freedom belonging to
* certain vector components of a vector-valued finite element. The
const std::set<types::boundary_id> &boundary_indicators = std::set<types::boundary_id>());
/**
- * @name Hanging Nodes
+ * Extract a vector that represents the constant modes of the
+ * DoFHandler for the components chosen by <tt>component_mask</tt>
+ * (see @ref GlossComponentMask). The constant modes on a
+ * discretization are the null space of a Laplace operator on the
+ * selected components with Neumann boundary conditions applied. The
+ * null space is a necessary ingredient for obtaining a good AMG
+ * preconditioner when using the class
+ * TrilinosWrappers::PreconditionAMG. Since the ML AMG package only
+ * works on algebraic properties of the respective matrix, it has no
+ * chance to detect whether the matrix comes from a scalar or a
+ * vector valued problem. However, a near null space supplies
+ * exactly the needed information about the components placement of vector
+ * components within the matrix. The null space (or rather, the constant
+ * modes) is provided by the finite element underlying the given DoFHandler
+ * and for most elements, the null space will consist of as many vectors as
+ * there are true arguments in <tt>component_mask</tt> (see @ref
+ * GlossComponentMask), each of which will be one in one vector component
+ * and zero in all others. However, the representation of the constant
+ * function for e.g. FE_DGP is different (the first component on each
+ * element one, all other components zero), and some scalar elements may
+ * even have two constant modes (FE_Q_DG0). Therefore, we store this object
+ * in a vector of vectors, where the outer vector contains the collection of
+ * the actual constant modes on the DoFHandler. Each inner vector has as
+ * many components as there are (locally owned) degrees of freedom in the
+ * selected components. Note that any matrix associated with this null space
+ * must have been constructed using the same <tt>component_mask</tt>
+ * argument, since the numbering of DoFs is done relative to the selected
+ * dofs, not to all dofs.
+ *
+ * The main reason for this program is the use of the null space
+ * with the AMG preconditioner.
+ */
+ template <class DH>
+ void
+ extract_constant_modes (const DH &dof_handler,
+ const ComponentMask &component_mask,
+ std::vector<std::vector<bool> > &constant_modes);
+
+ /**
+ * @}
+ */
+ /**
+ * @name Hanging nodes
* @{
*/
const types::subdomain_id subdomain);
// @}
/**
- * @name Dof indices for patches
+ * @name DoF indices on patches of cells
*
* Create structures containing a large set of degrees of freedom
* for small patches of cells. The resulting objects can be used in
const unsigned int level,
const bool interior_dofs_only = false);
- //@}
/**
- * Extract a vector that represents the constant modes of the
- * DoFHandler for the components chosen by <tt>component_mask</tt>
- * (see @ref GlossComponentMask). The constant modes on a
- * discretization are the null space of a Laplace operator on the
- * selected components with Neumann boundary conditions applied. The
- * null space is a necessary ingredient for obtaining a good AMG
- * preconditioner when using the class
- * TrilinosWrappers::PreconditionAMG. Since the ML AMG package only
- * works on algebraic properties of the respective matrix, it has no
- * chance to detect whether the matrix comes from a scalar or a
- * vector valued problem. However, a near null space supplies
- * exactly the needed information about the components placement of vector
- * components within the matrix. The null space (or rather, the constant
- * modes) is provided by the finite element underlying the given DoFHandler
- * and for most elements, the null space will consist of as many vectors as
- * there are true arguments in <tt>component_mask</tt> (see @ref
- * GlossComponentMask), each of which will be one in one vector component
- * and zero in all others. However, the representation of the constant
- * function for e.g. FE_DGP is different (the first component on each
- * element one, all other components zero), and some scalar elements may
- * even have two constant modes (FE_Q_DG0). Therefore, we store this object
- * in a vector of vectors, where the outer vector contains the collection of
- * the actual constant modes on the DoFHandler. Each inner vector has as
- * many components as there are (locally owned) degrees of freedom in the
- * selected components. Note that any matrix associated with this null space
- * must have been constructed using the same <tt>component_mask</tt>
- * argument, since the numbering of DoFs is done relative to the selected
- * dofs, not to all dofs.
- *
- * The main reason for this program is the use of the null space
- * with the AMG preconditioner.
+ * @}
*/
- template <class DH>
- void
- extract_constant_modes (const DH &dof_handler,
- const ComponentMask &component_mask,
- std::vector<std::vector<bool> > &constant_modes);
-
/**
- * For each active cell of a DoFHandler or hp::DoFHandler, extract
- * the active finite element index and fill the vector given as
- * second argument. This vector is assumed to have as many entries
- * as there are active cells.
- *
- * For non-hp DoFHandler objects given as first argument, the
- * returned vector will consist of only zeros, indicating that all
- * cells use the same finite element. For a hp::DoFHandler, the
- * values may be different, though.
+ * @name Counting degrees of freedom and related functions
+ * @{
*/
- template <class DH>
- void
- get_active_fe_indices (const DH &dof_handler,
- std::vector<unsigned int> &active_fe_indices);
/**
* Count how many degrees of freedom out of the total number belong
std::vector<types::global_dof_index> &dofs_per_component,
std::vector<unsigned int> target_component) DEAL_II_DEPRECATED;
+
/**
- * This function can be used when different variables shall be
- * discretized on different grids, where one grid is coarser than
- * the other. This idea might seem nonsensical at first, but has
- * reasonable applications in inverse (parameter estimation)
- * problems, where there might not be enough information to recover
- * the parameter on the same grid as the state variable;
- * furthermore, the smoothness properties of state variable and
- * parameter might not be too much related, so using different grids
- * might be an alternative to using stronger regularization of the
- * problem.
- *
- * The basic idea of this function is explained in the
- * following. Let us, for convenience, denote by ``parameter grid''
- * the coarser of the two grids, and by ``state grid'' the finer of
- * the two. We furthermore assume that the finer grid can be
- * obtained by refinement of the coarser one, i.e. the fine grid is
- * at least as much refined as the coarse grid at each point of the
- * domain. Then, each shape function on the coarse grid can be
- * represented as a linear combination of shape functions on the
- * fine grid (assuming identical ansatz spaces). Thus, if we
- * discretize as usual, using shape functions on the fine grid, we
- * can consider the restriction that the parameter variable shall in
- * fact be discretized by shape functions on the coarse grid as a
- * constraint. These constraints are linear and happen to have the
- * form managed by the ``ConstraintMatrix'' class.
- *
- * The construction of these constraints is done as follows: for
- * each of the degrees of freedom (i.e. shape functions) on the
- * coarse grid, we compute its representation on the fine grid,
- * i.e. how the linear combination of shape functions on the fine
- * grid looks like that resembles the shape function on the coarse
- * grid. From this information, we can then compute the constraints
- * which have to hold if a solution of a linear equation on the fine
- * grid shall be representable on the coarse grid. The exact
- * algorithm how these constraints can be computed is rather
- * complicated and is best understood by reading the source code,
- * which contains many comments.
- *
- * Before explaining the use of this function, we would like to
- * state that the total number of degrees of freedom used for the
- * discretization is not reduced by the use of this function,
- * i.e. even though we discretize one variable on a coarser grid,
- * the total number of degrees of freedom is that of the fine
- * grid. This seems to be counter-productive, since it does not give
- * us a benefit from using a coarser grid. The reason why it may be
- * useful to choose this approach nonetheless is three-fold: first,
- * as stated above, there might not be enough information to recover
- * a parameter on a fine grid, i.e. we chose to discretize it on the
- * coarse grid not to save DoFs, but for other reasons. Second, the
- * ``ConstraintMatrix'' includes the constraints into the linear
- * system of equations, by which constrained nodes become dummy
- * nodes; we may therefore exclude them from the linear algebra, for
- * example by sorting them to the back of the DoF numbers and simply
- * calling the solver for the upper left block of the matrix which
- * works on the non-constrained nodes only, thus actually realizing
- * the savings in numerical effort from the reduced number of actual
- * degrees of freedom. The third reason is that for some or other
- * reason we have chosen to use two different grids, it may be
- * actually quite difficult to write a function that assembles the
- * system matrix for finite element spaces on different grids; using
- * the approach of constraints as with this function allows to use
- * standard techniques when discretizing on only one grid (the finer
- * one) without having to take care of the fact that one or several
- * of the variable actually belong to different grids.
+ * For each active cell of a DoFHandler or hp::DoFHandler, extract
+ * the active finite element index and fill the vector given as
+ * second argument. This vector is assumed to have as many entries
+ * as there are active cells.
*
- * The use of this function is as follows: it accepts as parameters
- * two DoF Handlers, the first of which refers to the coarse grid
- * and the second of which is the fine grid. On both, a finite
- * element is represented by the DoF handler objects, which will
- * usually have several components, which may belong to different
- * finite elements. The second and fourth parameter of this function
- * therefore state which variable on the coarse grid shall be used
- * to restrict the stated component on the fine grid. Of course, the
- * finite elements used for the respective components on the two
- * grids need to be the same. An example may clarify this: consider
- * the parameter estimation mentioned briefly above; there, on the
- * fine grid the whole discretization is done, thus the variables
- * are ``u'', ``q'', and the Lagrange multiplier ``lambda'', which
- * are discretized using continuous linear, piecewise constant
- * discontinuous, and continuous linear elements, respectively. Only
- * the parameter ``q'' shall be represented on the coarse grid, thus
- * the DoFHandler object on the coarse grid represents only one
- * variable, discretized using piecewise constant discontinuous
- * elements. Then, the parameter denoting the component on the
- * coarse grid would be zero (the only possible choice, since the
- * variable on the coarse grid is scalar), and one on the fine grid
- * (corresponding to the variable ``q''; zero would be ``u'', two
- * would be ``lambda''). Furthermore, an object of type IntergridMap
- * is needed; this could in principle be generated by the function
- * itself from the two DoFHandler objects, but since it is probably
- * available anyway in programs that use this function, we shall use
- * it instead of re-generating it. Finally, the computed constraints
- * are entered into a variable of type ConstraintMatrix; the
- * constraints are added, i.e. previous contents which may have, for
- * example, be obtained from hanging nodes, are not deleted, so that
- * you only need one object of this type.
+ * For non-hp DoFHandler objects given as first argument, the
+ * returned vector will consist of only zeros, indicating that all
+ * cells use the same finite element. For a hp::DoFHandler, the
+ * values may be different, though.
*/
- template <int dim, int spacedim>
+ template <class DH>
void
- compute_intergrid_constraints (const DoFHandler<dim,spacedim> &coarse_grid,
- const unsigned int coarse_component,
- const DoFHandler<dim,spacedim> &fine_grid,
- const unsigned int fine_component,
- const InterGridMap<DoFHandler<dim,spacedim> > &coarse_to_fine_grid_map,
- ConstraintMatrix &constraints);
-
+ get_active_fe_indices (const DH &dof_handler,
+ std::vector<unsigned int> &active_fe_indices);
/**
- * This function generates a matrix such that when a vector of data
- * with as many elements as there are degrees of freedom of this
- * component on the coarse grid is multiplied to this matrix, we
- * obtain a vector with as many elements as there are global
- * degrees of freedom on the fine grid. All the elements of the
- * other components of the finite element fields on the fine grid
- * are not touched.
- *
- * The output of this function is a compressed format that can be
- * given to the @p reinit functions of the SparsityPattern ad
- * SparseMatrix classes.
+ * @}
*/
- template <int dim, int spacedim>
- void
- compute_intergrid_transfer_representation (const DoFHandler<dim,spacedim> &coarse_grid,
- const unsigned int coarse_component,
- const DoFHandler<dim,spacedim> &fine_grid,
- const unsigned int fine_component,
- const InterGridMap<DoFHandler<dim,spacedim> > &coarse_to_fine_grid_map,
- std::vector<std::map<types::global_dof_index, float> > &transfer_representation);
-
+
/**
* Create a mapping from degree of freedom indices to the index of
* that degree of freedom on the boundary. After this operation,